WPF 使用附加屬性宣告 ICommand

Dwaynerbing發表於2021-05-25

一、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的選中項,都觸發事件“的預期目標。

相關文章