【问题标题】:Using events and Commands within ItemsControl in WPF在 WPF 的 ItemsControl 中使用事件和命令
【发布时间】:2013-05-31 19:27:46
【问题描述】:

假设我有一个标准 WPF ItemsControl 绑定到“狗”对象的 ObservableCollection,如下所示:

<ItemsControl ItemsSource="{Binding Dogs}">
<ItemsControl.ItemTemplate>
    <DataTemplate>
         <StackPanel Orientation="Horizontal">
             <TextBlock Text="{Binding Name}"/>
             <TextBlock Text="{Binding Breed}"/>
             <TextBlock Text="{Binding Weight}"/>
         </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

我希望用户能够删除集合中的任何狗。过去,我一直在使用 ListBox 控件并将 ViewModel 绑定到 SelectedItem 属性。然后,我创建一个按钮,其中包含一个从 ObservableCollection 中删除所选对象的事件。

这工作正常,但我想把它布置好,这样每一行都可以有自己的删除按钮。

<ItemsControl ItemsSource="{Binding Dogs}">
<ItemsControl.ItemTemplate>
    <DataTemplate>
         <StackPanel Orientation="Horizontal">
             <TextBlock Text="{Binding Name}"/>
             <TextBlock Text="{Binding Breed}"/>
             <TextBlock Text="{Binding Weight}"/>
             <Button Click="Click_EventHandler"/>
         </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

还有一个看起来像这样的事件:

private void ListBox_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
          //Delete this Dog Object from Observable Collection
    }

将一个按钮推入 ItemTemplate 并给它一个事件会使 WPF 崩溃,并将命令绑​​定到 ItemTemplate 中的按钮根本没有任何作用,因此我以前的方法将不起作用。

我能想到的唯一方法是向 ItemTemplate 添加一个 ToggleButton 并绑定到 View Model,然后在 Setter 中触发一个事件。不完全是一个优雅的解决方案。

有人对如何解决这个问题有更好的想法吗?

【问题讨论】:

    标签: .net wpf data-binding wpf-controls


    【解决方案1】:

    您可以像其他任何东西一样绑定命令,但首先您需要实现ICommand 接口,如下所示:

    public class RelayCommand: ICommand
    {
      private Action<object> _execute;
      private Predicate<object> _canExecute;
    
      public RelayCommand(Action<object> execute, Predicate<object> canExecute)
      {
          _execute = execute;
          _canExecute = canExecute;
      }
    
      public RelayCommand(Action<object> execute) : this(execute, null) { }
    
      public event EventHandler CanExecuteChanged;
    
      public bool CanExecute(object parameter)
      {
          return _canExecute != null ? _canExecute(parameter) : true;
      }
    
      public void Execute(object parameter)
      {
          if (CanExecute(parameter) && _execute != null) _execute(parameter);
      }
    }
    

    然后您的Dog 类需要公开例如ICommand DeleteCmd 属性:

    class Dog
    {
       ...
       private RelayCommand _deleteCmd;
    
       private void DoDelete(object parameter)
       {
          //put delete action here
       }
    
       public ICommand DeleteCmd
       {
          get
          {
             if (_deleteCmd == null) _deleteCmd = new RelayCommand(o => DoDelete(o));
             return _deleteCmd;
          }
       }
    }
    

    然后你像这样绑定它:

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}"/>
        <TextBlock Text="{Binding Breed}"/>
        <TextBlock Text="{Binding Weight}"/>
        <Button Command="{Binding DeleteCmd}"/>
    </StackPanel>
    

    【讨论】:

      猜你喜欢
      • 2020-05-31
      • 1970-01-01
      • 2018-11-20
      • 1970-01-01
      • 2021-11-05
      • 2010-11-06
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      相关资源
      最近更新 更多