【问题标题】:Clear the selection of one ListBox if we select in another ListBox如果我们在另一个 ListBox 中选择,则清除对一个 ListBox 的选择
【发布时间】:2020-05-08 13:07:03
【问题描述】:

我有一个场景,两个列表将显示在一个窗口中,但用户只能选择列表中的任何一个并继续。

如果用户在 listbox1 中选择一个项目并再次从 listbox2 中选择,则假设 listbox1 和 listbox2 应该删除 listbox1 中的选定项目。

我只能通过 xaml 而不是代码隐藏来实现这一点。所以我在下面尝试:

  <Grid.Resources>
            <Storyboard  x:Key="temp" >
                <Int32Animation Storyboard.TargetName="lstbox"   Storyboard.TargetProperty="(ListBox.SelectedIndex)" 
                                     To="-1" Duration="0:0:.2" />
            </Storyboard>
            <Storyboard  x:Key="temp1" >
                <Int32Animation Storyboard.TargetName="listBox1"   Storyboard.TargetProperty="(ListBox.SelectedIndex)" 
                                     To="-1" Duration="0:0:.2" />
            </Storyboard>
        </Grid.Resources>

如上所述,创建了两个故事板,将 selectedIndex 设置为 -1,并在选择更改事件触发器时调用该故事板,如下所示:

 <ListBox Name="listBox1" HorizontalAlignment="Left"  Grid.Column="1">
            <ListBox.Triggers>
                <EventTrigger RoutedEvent="ListBox.SelectionChanged">
                    <BeginStoryboard Storyboard="{StaticResource temp}"/>
                </EventTrigger>
            </ListBox.Triggers>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="Background" Value="AliceBlue" />
                    <Setter Property="BorderBrush" Value="BlanchedAlmond" />
                    <Setter Property="BorderThickness" Value="2" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Foreground" Value="Red" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
            <ListBoxItem Content="Coffie"></ListBoxItem>
            <ListBoxItem Content="Tea"></ListBoxItem>
            <ListBoxItem Content="Orange Juice"></ListBoxItem>
            <ListBoxItem Content="Milk"></ListBoxItem>
            <ListBoxItem Content="Iced Tea"></ListBoxItem>
            <ListBoxItem Content="Mango Shake"></ListBoxItem>
        </ListBox>
  <ListBox Name="lstbox" ItemsSource="{Binding MyData}"  Grid.Column="1"  Grid.Row="1" SelectionChanged="lstbox_SelectionChanged">
            <ListBox.Triggers>
                <EventTrigger RoutedEvent="ListBox.SelectionChanged">
                    <BeginStoryboard Storyboard="{StaticResource temp1}"/>
                </EventTrigger>
            </ListBox.Triggers>
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="Background" Value="AliceBlue" />
                    <Setter Property="BorderBrush" Value="BlanchedAlmond" />
                    <Setter Property="BorderThickness" Value="2" />
                    <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Foreground" Value="DarkViolet" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>

当我将 SelectedIndex 设置为 -1 时,通过后面的代码来清除 selectedItem 的样式,但通过情节提要并没有清除样式。

请告诉我任何其他方式或指导我使其工作。

我只能通过xaml来实现。

谢谢,

纳加斯里。

【问题讨论】:

  • 这应该在视图模型中处理,当然不在标记中...
  • 我们的项目动态设置viewmodel。所以我在实施时无法决定
  • 那么你不使用 MVVM 吗?因为那时您肯定会在具有 ListBox 元素的视图的视图模型中实现这一点。为什么还要在 XAML 中实现这种逻辑?
  • 我已经使用附加行为实现了它,我不知道为什么对这个问题持否定态度。无论如何感谢大家的投入

标签: c# wpf


【解决方案1】:

根据您的示例,如果您像这样更改情节提要,它将起作用:

        <Storyboard x:Key="temp">
            <ObjectAnimationUsingKeyFrames
                Storyboard.TargetName="lstbox"
                Storyboard.TargetProperty="SelectedItem">
                <ObjectAnimationUsingKeyFrames.KeyFrames>
                    <DiscreteObjectKeyFrame
                        KeyTime="0:0:0"
                        Value="null" />
                </ObjectAnimationUsingKeyFrames.KeyFrames>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>

        <Storyboard x:Key="temp1">
            <ObjectAnimationUsingKeyFrames
                Storyboard.TargetName="listBox1"
                Storyboard.TargetProperty="SelectedItem">
                <ObjectAnimationUsingKeyFrames.KeyFrames>
                    <DiscreteObjectKeyFrame
                        KeyTime="0:0:0"
                        Value="null" />
                </ObjectAnimationUsingKeyFrames.KeyFrames>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>

但是,就像评论者提到的那样。如果您使用 MVVM 和数据绑定到 SelectedItem 等,这可能不起作用。

如果你的老板允许你使用 Behavior,你可以这样做:

<ListBox
    Name="ListBox1"
    ItemsSource="{Binding MyData1}"
    SelectedItem="{Binding SelectedMyData1, Mode=TwoWay}">
    <i:Interaction.Behaviors>
        <local:ListBoxSingleSelectionBehavior TargetListBox="{Binding ElementName=ListBox2}" />
    </i:Interaction.Behaviors>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Background" Value="AliceBlue" />
            <Setter Property="BorderBrush" Value="BlanchedAlmond" />
            <Setter Property="BorderThickness" Value="2" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>
<ListBox
    Name="ListBox2"
    ItemsSource="{Binding MyData2}"
    SelectedItem="{Binding SelectedMyData2, Mode=TwoWay}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Background" Value="AliceBlue" />
            <Setter Property="BorderBrush" Value="BlanchedAlmond" />
            <Setter Property="BorderThickness" Value="2" />
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="DarkViolet" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

这是行为:

using System.Windows;
using System.Windows.Controls;
using Microsoft.Xaml.Behaviors;

namespace SO
{
    public class ListBoxSingleSelectionBehavior : Behavior<ListBox>
    {
        private bool isSelectionChanging;

        public ListBoxSingleSelectionBehavior()
        {
        }

        #region TargetListBox (DependencyProperty)
        /// <summary>
        /// Identifies the TargetListBox property.
        /// </summary>
        public static readonly DependencyProperty TargetListBoxProperty =
            DependencyProperty.Register(
                "TargetListBox",
                typeof(ListBox),
                typeof(ListBoxSingleSelectionBehavior),
                new PropertyMetadata(null, OnTargetListBoxChanged));

        /// <summary>
        /// Gets or sets the target ListBox to monitor.
        /// </summary>
        public ListBox TargetListBox
        {
            get => (ListBox)GetValue(TargetListBoxProperty);
            set => SetValue(TargetListBoxProperty, value);
        }

        private static void OnTargetListBoxChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var behavior = (ListBoxSingleSelectionBehavior) d;

            var oldTargetListBox = (ListBox) e.OldValue;
            var newTargetListBox = (ListBox) e.NewValue;

            behavior.OnTargetListBoxChanged(oldTargetListBox, newTargetListBox);
        }

        private void OnTargetListBoxChanged(ListBox oldTargetListBox, ListBox newTargetListBox)
        {
            if (oldTargetListBox != null)
            {
                oldTargetListBox.SelectionChanged -= OnTargetSelectionChanged;
            }

            if (newTargetListBox != null)
            {
                newTargetListBox.SelectionChanged += OnTargetSelectionChanged;
            }
        }
        #endregion

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.SelectionChanged += OnSourceSelectionChanged;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            if (AssociatedObject != null)
            {
                AssociatedObject.SelectionChanged -= OnSourceSelectionChanged;
            }
        }

        private void OnSourceSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (isSelectionChanging) return;

            isSelectionChanging = true;

            if (TargetListBox != null)
            {
                TargetListBox.SelectedItem = null;
            }

            isSelectionChanging = false;
        }

        private void OnTargetSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (isSelectionChanging) return;

            isSelectionChanging = true;

            if (AssociatedObject != null)
            {
                AssociatedObject.SelectedItem = null;
            }

            isSelectionChanging = false;
        }
    }
}

【讨论】:

  • 感谢 Keithernet。所以如果我们使用故事板,我们将无法存储值
  • 正确。在这种情况下,你的老板要求的是不可能的事情。您可以编写一个附加的行为来处理这个问题。看起来它是在 XAML 中完成的,但它仍在执行行为中的代码。
  • 我用一个使用行为的例子更新了答案。
  • 感谢 Keithernet 我可以使用行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-30
  • 1970-01-01
  • 2015-08-07
  • 2014-02-21
  • 1970-01-01
  • 2014-03-08
  • 1970-01-01
相关资源
最近更新 更多