一、ListBox中为什么选择同一项不能每次都触发SelectionChanged事件呢?

​ 当我需要每次点击ListBox的选中项,都触发事件。找到最符合的事件为SelectionChanged事件。但使用SelectionChanged事件时,并不能每次都触发。

​ 这是因为SelectionChanged事件是选中项发生变化时才会触发,如果上次选中与本次相同,则单击是不会触发SelectionChanged事件。

二、使用附加属性声明 ICommand

我们可以使用附加属性声明一个ICommand解决以上问题。具体步骤如下:

(1)声明一个附加属性。

    class AttachedLib
    {
        public static ICommand GetClick(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(ClickProperty);
        }

        public static void SetClick(DependencyObject obj, ICommand value)
        {
            obj.SetValue(ClickProperty, value);
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ClickProperty =
            DependencyProperty.RegisterAttached("Click", typeof(ICommand), typeof(AttachedLib), new PropertyMetadata(null));
    }

(2)将该附加属性添加到ListBox上,并绑定待实现的ICommand。

  <Grid>
        <ListBox Margin="10"
                 ItemsSource="{Binding StudentCollection}"
                 ItemTemplate="{StaticResource StudentTemplate}"
                 local:AttachedLib.Click="{Binding SelectCommand}"></ListBox>
    </Grid>
       public ICommand SelectCommand { get; set; }

        private void ExecuteSelectCommand(object obj)
        {
            if (obj is Student student)
            {
                MessageBox.Show($"{student.Id},{student.Name},{student.Age}","选中的学生信息");
            }
        }

        public MainWindowVM()
        {
            StudentCollection = new ObservableCollection<Student>()
            {
                new Student(){Id = 1,Name = "Dwayne", Age = 10,},
                new Student(){Id = 2,Name = "John", Age = 11,},
                new Student(){Id = 3,Name = "Aaron", Age = 12,},
            };
            SelectCommand=new RelayCommand(ExecuteSelectCommand);
        }

(3)在ListBox的ListBoxItem模板中,添加一个Button,Button的Command使用相对路径绑定该附加属性。

 <DataTemplate x:Key="StudentTemplate" DataType="{x:Type local:Student}">
            <Button BorderThickness="0"
                    Background="Transparent"
                    Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}, Path=(local:AttachedLib.Click)}"
                    CommandParameter="{Binding}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Margin="10,5" Width="100" Text="{Binding Id}"></TextBlock>
                    <TextBlock Margin="10,5" Width="200" Text="{Binding Name}"></TextBlock>
                    <TextBlock Margin="10,5" Width="100" Text="{Binding Age}"></TextBlock>
                </StackPanel>
            </Button>
        </DataTemplate>

三、总结

通过以上操作,由Button触发单击事件,就可以实现”每次点击ListBox的选中项,都触发事件“的预期目标。

05-26 14:30