WPF 使用附加属性声明 ICommand
一、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的选中项,都触发事件“的预期目标。