如何同步ListBox的SelectedItem

本文关键字:ListBox SelectedItem 同步 何同步 | 更新日期: 2023-09-27 17:48:49

我有这个ListBox,它绑定到一个ObservableCollection。列表中的每个对象都实现了一个名为ISelectable 的接口

public interface ISelectable : INotifyPropertyChanged
{
    event EventHandler IsSelected;
    bool Selected { get; set; }
    string DisplayText { get; }
}

我想跟踪选择了哪个对象,而不管它是如何选择的。用户可以单击ListBox中对象的表示形式,但也可以通过代码选择对象。如果用户通过ListBox选择对象,我会将所选项目强制转换为ISelectable,并将selected属性设置为true。

ISelectable selectable = (ISelectable)e.AddedItems[0];
selectable.Selected = true;

我的问题是,当我使用代码选择对象时,我无法获得ListBox来更改所选项目。我使用DataTemplate以不同的颜色显示所选对象,这意味着所有内容都显示正确。但是ListBox将用户单击的最后一个对象作为SelectedItem,这意味着如果不首先在列表中选择另一个对象,就无法单击该项目。

有人知道怎么解决这个问题吗?我很确定我可以通过编写一些自定义代码来处理鼠标和键盘事件来实现我想要的,但我宁愿不这样做。我尝试将SelectedItem属性添加到集合中,并将其绑定到ListBox的SelectItemProperty,但没有成功。

如何同步ListBox的SelectedItem

您还可以通过将ListBoxItem.IsSelected数据绑定到Selected属性来实现这一点。其想法是在创建每个ListBoxItems时为其设置绑定。这可以使用针对为ListBox生成的每个ListBoxItems的样式来完成。

这样,当ListBox中的项目被选中/取消选中时,相应的selected属性将被更新。同样,在代码中设置Selected属性将反映在ListBox 中

为此,Selected属性必须引发PropertyChanged事件。

<List.Resources>
    <Style TargetType="ListBoxItem">
        <Setter 
            Property="IsSelected" 
            Value="{Binding 
                        Path=DataContext.Selected, 
                        RelativeSource={RelativeSource Self}}" 
            />
    </Style>
</List.Resources>

您查看过列表框的SelectedItemChanged和SelectedIndexChanged事件吗?

无论选择是如何选择的,只要选择发生更改,都应触发这些事件。

我认为应该在选择发生更改时激发propertyChanged事件。将此代码添加到实现ISelectable的对象中。你最终会得到这样的东西:

private bool _Selected;
        public bool Selected
        {
            get
            {
                return _Selected;
            }
            set
            {
                if (PropertyChanged != null)                
                    PropertyChanged(this, new PropertyChangedEventArgs("Selected"));
                _Selected = value;
            }
        }

我试过以下代码:

public ObservableCollection<testClass> tests = new ObservableCollection<testClass>();
        public Window1()
        {
            InitializeComponent();
            tests.Add(new testClass("Row 1"));
            tests.Add(new testClass("Row 2"));
            tests.Add(new testClass("Row 3"));
            tests.Add(new testClass("Row 4"));
            tests.Add(new testClass("Row 5"));
            tests.Add(new testClass("Row 6"));
            TheList.ItemsSource = tests;
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            tests[3].Selected = true;
            TheList.SelectedItem = tests[3];
        }

其中testClass实现ISelectable。

这是一个xaml,没有什么花哨的:

<ListBox Grid.Row="0" x:Name="TheList"></ListBox>        
<Button Grid.Row="1" Click="Button_Click">Select 4th</Button>

我希望这能有所帮助。