最近做一个工具,突然发现ListBox和ListView等列表控件的MouseDoubleClick事件有时候是获取不到当前双击的行对象数据的,比如这样写:
private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListBox listBox = sender as ListBox; if (listBox == null || listBox.SelectedItem == null) { MessageBox.Show("ListBox1双击对象为空..."); } else { var model = listBox.SelectedItem as ListBoxModel; MessageBox.Show("当前对象为" + model.Name + " " + model.Age); } }
双击行就会出现双击的对象为空。
上一篇文章中已经说明怎么解决这个问题:
使用Style中的EventSetter Handler这里就不在更多介绍。
但是今天想要解决的问题是怎么把EventSetter Handler使用Command绑定的方式把Handler事件进行解耦
要使用第三方类库CommandBehavior(AttachedCommandBehavior acb)进行解耦
代码如下:
引用 xmlns:localCommand="clr-namespace:AttachedCommandBehavior"
<Style x:Key="listBox2Item" TargetType="ListBoxItem">
<Style.Setters> <Setter Property="localCommand:CommandBehavior.Event" Value="MouseDoubleClick"></Setter> <Setter Property="localCommand:CommandBehavior.Command" Value="{Binding DataContext.DoubleCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:WinTest}}}"></Setter> <Setter Property="localCommand:CommandBehavior.CommandParameter" Value="{Binding RelativeSource={RelativeSource Self}}"></Setter> </Style.Setters> </Style>ViewModel代码如下
public class ViewModel : INotifyPropertyChanged { public ViewModel() { for (int i = 0; i < 5; i++) { DataList.Add(new ListBoxModel() { Name = "张三" + i.ToString(), Age = 1000 + i }); DataList2.Add(new ListBoxModel() { Name = "李四" + i.ToString(), Age = 100 + i }); } doubleCommand = new SimpleCommand(obj => { ListBoxItem listBoxItem = obj as ListBoxItem; if (listBoxItem != null) { ListBoxModel model = listBoxItem.Content as ListBoxModel; if (model != null) { CurrentSelectItem2 = model; MessageBox.Show("Command Banding" + model.Name + " " + model.Age); } } //wpftest.ViewModel MessageBox.Show("Cmd..."); }, o => true); } public SimpleCommand DoubleCommand { get { return doubleCommand; } set { doubleCommand = value; //OnPropertyChanged(new PropertyChangedEventArgs("DoubleCommand")); } } private ObservableCollectiondataList = new ObservableCollection (); private ObservableCollection _dataList2 = new ObservableCollection (); private ListBoxModel _CurrentSelectItem; private ListBoxModel _CurrentSelectItem2; private SimpleCommand doubleCommand; public ObservableCollection DataList { get { return dataList; } set { dataList = value; } } /// /// 当前双击的对象 /// public ListBoxModel CurrentSelectItem { get { return _CurrentSelectItem; } set { _CurrentSelectItem = value; OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem")); } } ////// ListBox2双击的对象 /// public ListBoxModel CurrentSelectItem2 { get { return _CurrentSelectItem2; } set { _CurrentSelectItem2 = value; OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem2")); } } public ObservableCollectionDataList2 { get { return _dataList2; } set { _dataList2 = value; } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) { PropertyChanged(this, e); } } }
完整Xaml和CS代码如下:
using AttachedCommandBehavior;using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.Linq;using System.Text;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes;namespace WpfTest{ ////// WinTest.xaml 的交互逻辑 /// public partial class WinTest : Window { ViewModel VModel = new ViewModel(); public WinTest() { InitializeComponent(); this.DataContext = VModel; } private void ListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListBox listBox = sender as ListBox; if (listBox == null || listBox.SelectedItem == null) { MessageBox.Show("ListBox1双击对象为空..."); } else { var model = listBox.SelectedItem as ListBoxModel; MessageBox.Show("当前对象为" + model.Name + " " + model.Age); } } private void ListBox2_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListBoxItem listBoxItem = sender as ListBoxItem; if (listBoxItem == null) { MessageBox.Show("ListBox2双击对象为空..."); } else { ListBoxModel model = listBoxItem.Content as ListBoxModel; if (model != null) { VModel.CurrentSelectItem2 = listBoxItem.Content as ListBoxModel; MessageBox.Show(model.Name + " " + model.Age); } } } } public class ViewModel : INotifyPropertyChanged { public ViewModel() { for (int i = 0; i < 5; i++) { DataList.Add(new ListBoxModel() { Name = "张三" + i.ToString(), Age = 1000 + i }); DataList2.Add(new ListBoxModel() { Name = "李四" + i.ToString(), Age = 100 + i }); } doubleCommand = new SimpleCommand(obj => { ListBoxItem listBoxItem = obj as ListBoxItem; if (listBoxItem != null) { ListBoxModel model = listBoxItem.Content as ListBoxModel; if (model != null) { CurrentSelectItem2 = model; MessageBox.Show("Command Banding" + model.Name + " " + model.Age); } } //wpftest.ViewModel MessageBox.Show("Cmd..."); }, o => true); } public SimpleCommand DoubleCommand { get { return doubleCommand; } set { doubleCommand = value; //OnPropertyChanged(new PropertyChangedEventArgs("DoubleCommand")); } } private ObservableCollectiondataList = new ObservableCollection (); private ObservableCollection _dataList2 = new ObservableCollection (); private ListBoxModel _CurrentSelectItem; private ListBoxModel _CurrentSelectItem2; private SimpleCommand doubleCommand; public ObservableCollection DataList { get { return dataList; } set { dataList = value; } } /// /// 当前双击的对象 /// public ListBoxModel CurrentSelectItem { get { return _CurrentSelectItem; } set { _CurrentSelectItem = value; OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem")); } } ////// ListBox2双击的对象 /// public ListBoxModel CurrentSelectItem2 { get { return _CurrentSelectItem2; } set { _CurrentSelectItem2 = value; OnPropertyChanged(new PropertyChangedEventArgs("CurrentSelectItem2")); } } public ObservableCollectionDataList2 { get { return _dataList2; } set { _dataList2 = value; } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) { PropertyChanged(this, e); } } } public class ListBoxModel : INotifyPropertyChanged { /// /// 姓名 /// private string _Name; ////// 年龄 /// private int _Age; public string Name { get { return _Name; } set { _Name = value; OnPropertyChanged(new PropertyChangedEventArgs("Name")); } } public int Age { get { return _Age; } set { _Age = value; OnPropertyChanged(new PropertyChangedEventArgs("Age")); } } public void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) { PropertyChanged(this, e); } } public event PropertyChangedEventHandler PropertyChanged; }}
<Setter Property="localCommand:CommandBehavior.Command" Value="{Binding DataContext.DoubleCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type local:WinTest}}}"></Setter>
关于这个Command的Value绑定要使用FindAncestor进行查找才能解决,不然是绑定不到ViewModel中的DoubleCommand
发个图看看:
关于CommandBehavior代码可以在
下载使用
国外博客
对于SimpleCommad.cs的源文件我增加了两个参数的构造函数:
public SimpleCommand(Action