Listview MouseDoubleClickEvent在后面的代码中创建

当我有:

          ... etc 

代码背后

  protected void HandleDoubleClick(object sender, MouseButtonEventArgs e) { T item = (T)(((ListViewItem)sender).Content); // item is the row item that was double clicked on } 

一切都很好。


现在我需要在代码背后做同样的事情。 这就是我的成果:

  public Constructor(){ listview.AddHandler( ListViewItem.MouseDoubleClickEvent, new MouseButtonEventHandler(HandleDoubleClick) ); } protected void HandleDoubleClick(object sender, MouseButtonEventArgs e) { T item = (T)(((ListViewItem)sender).Content); // error cause the sender is the listview } 

当我双击listview的任何部分而不仅仅是listviewItem时,该事件将触发。 此外,我希望发件人是ListViewItem,它不是。 发件人实际上是列表视图。 我尝试过的事情:

1)因为发件人是listview,所以我尝试将事件创建为:

  listview.AddHandler( // I use PreviewMouseDoubleClickEvent instead of MouseDoubleClickEvent because of the way the events bubles ListViewItem.PreviewMouseDoubleClickEvent, new MouseButtonEventHandler(HandleDoubleClick) ); 

我得到同样的错误,发件人是listview

2)而不是做:

  T item = (T)((ListViewItem)sender).Content; 

我做:

  T item = (T)(listview.selectedItem); 

这个问题是,如果用户双击listview上不是行的任何内容,它将返回当前所选项

为什么我的代码不起作用? 我究竟做错了什么?

附加行为模式


我认为你应该使用附加行为,因为

  1. MVVM♥附加行为
  2. 它是可重用的:一旦你创建了附加的行为和双击的命令,你可以将它附加到任何其他控件类型(所以你可以使用相同的代码双击图像等)
  3. 抽象脏实现,因此xaml和视图模型都更清晰
  4. 他们的工作方式很棒,我喜欢使用聪明的代码。

你做的是什么:

在此处输入图像描述


创建ListViewItemDoubleClickCommandBehavior

从上图中可以看出,此CommandBehavior类将命令链接到控件。

  • 在上面用于按钮库的情况下,我们将创建一个ListViewItem

  • 你将需要prism这个,因为它inheritance的CommandBehaviorBase是该库的一部分。 你可以在这里得到它(但是对于这个例子你只需要Prism.Commands dll)

  • 命名约定说你应该以这种格式命名这个CommandBehavior

      [X][Y]CommandBehavior 

    X – 我们绑定命令的控件的名称(在本例中为ListViewItem)
    Y – 用户执行的将导致命令发生的操作(在本例中为DoubleClick)

inheritance人代码:

  public class ListViewItemDoubleClickCommandBehaviour : CommandBehaviorBase { public ListViewItemDoubleClickCommandBehaviour(ListViewItem controlToWhomWeBind) : base(controlToWhomWeBind) { controlToWhomWeBind.MouseDoubleClick += OnDoubleClick; } private void OnDoubleClick(object sender, System.Windows.RoutedEventArgs e) { ExecuteCommand(); } } 

创建DoubleClick Static类

这个类将包含所有双击命令的东西。

  • 它被称为doubleclick,因为它代表双击的实际行为。 其他类型的操作(比如你想要一个文本框中的按钮命令)将拥有自己的类及其命令,命令参数和行为然后我们可以访问。

  • 这些命令是ICommand类型的依赖属性(我假设你已经实现了这个接口,因为你需要它用于MVVM)

  • 命令本身的一个依赖属性和一个命令需要的参数(在这种情况下,您可能会使用所选项作为参数)

  • 此类具有ListViewItemDoubleClickCommandBehavior的实例作为依赖项属性。 这是在绑定到控件的命令和ListViewItemDoubleClickCommandBehaviour中的双击事件之间创建链接的方式。 我们使用一些CommandBehaviorBase的魔术方法来创建行为并将命令传递给它来执行。

  • OnSetCommand和OnSetCommandParameter回调用于将Behavior连接到命令。 每次命令更改时,我们都会将其设置为要运行的行为的新命令。 这些回调被注册到构造函数的PropertyMetadata部分中的DependencyProperties。 每当依赖属性更改时,都会触发它们。

这是该类的代码:

 public static class DoubleClick { public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached( "Command", typeof(ICommand), typeof(DoubleClick), new PropertyMetadata(OnSetCommandCallback)); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached( "CommandParameter", typeof(object), typeof(DoubleClick), new PropertyMetadata(OnSetCommandParameterCallback)); private static readonly DependencyProperty DoubleClickCommandBehaviorProperty = DependencyProperty.RegisterAttached( "DoubleClickCommandBehavior", typeof(ListViewItemDoubleClickCommandBehaviour), typeof(DoubleClick), null); public static void SetCommand(ListViewItem controlToWhomWeBind, ICommand value) { controlToWhomWeBind.SetValue(CommandProperty, value); } public static ICommand GetCommand(ListViewItem controlToWhomWeBind) { return (ICommand)controlToWhomWeBind.GetValue(CommandProperty); } public static void SetCommandParameter(ListViewItem controlToWhomWeBind, ICommand value) { controlToWhomWeBind.SetValue(CommandParameterProperty, value); } public static ICommand GetCommandParameter(ListViewItem controlToWhomWeBind) { return (ICommand)controlToWhomWeBind.GetValue(CommandParameterProperty); } private static void OnSetCommandCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { ListViewItem controlToWhomWeBind= dependencyObject as ListViewItem; if (controlToWhomWeBind!= null) { ListViewItemDoubleClickCommandBehaviour behavior = GetOrCreateBehavior(controlToWhomWeBind); behavior.Command = e.NewValue as ICommand; } } private static void OnSetCommandParameterCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { ListViewItem controlToWhomWeBind= dependencyObject as ListViewItem; if (controlToWhomWeBind!= null) { ListViewItemDoubleClickCommandBehaviour behavior = GetOrCreateBehavior(controlToWhomWeBind); behavior.CommandParameter = e.NewValue; } } private static ListViewItemDoubleClickCommandBehaviour GetOrCreateBehavior( ListViewItem controlToWhomWeBind) { ListViewItemDoubleClickCommandBehaviour behavior = controlToWhomWeBind.GetValue(DoubleClickCommandBehaviorProperty) as ListViewItemDoubleClickCommandBehaviour; if (behavior == null) { behavior = new ListViewItemDoubleClickCommandBehaviour (controlToWhomWeBind); controlToWhomWeBind.SetValue(DoubleClickCommandBehaviorProperty, behavior); } return behavior; } } 

注意:

我知道这看起来很像复杂的代码,但是一旦你经常使用它就会有一个简单的模式,并且它会从视图模型中抽象出所有复杂性,因此命令与控件的绑定看起来非常简单。


在viewmodel中创建命令并在xaml中绑定它

既然咕噜咕噜的工作结束了,我们就做了简单的工作。

创建命令

我假设您熟悉命令,您可以像以往一样创建命令:

  public ICommand DisplaySelectedItemCmd { get; protected set; } //This method goes in your constructor private void InitializeCommands() { //Initializes the command this.DisplaySelectedItemCmd = new RelayCommand( (param) => { this.DisplaySelectedItem((object)param); }, (param) => { return this.CanDisplaySelectedItem; } ); } //The parameter should be your listview's selected item. I have no idea what type it is so I made it an object public void DisplaySelectedPolicy(object selectedListViewItem) { //Code to perform when item is double clicked } private bool CanDisplaySelectedPolicy { get { return true; //Change this bool if you have any reason to disable the double clicking, as this bool basically is linked to the double click command firing. } } 

在xaml中创建绑定

而现在是美丽的一部分。 首先添加xml命名空间:

  xmlns:commands="clr-namespace:CommandHandling" 

然后绑定到ListViewItem上

   

并做了。

如果这不起作用,请告诉我。 (如果你愿意的话,任何读这篇文章的人都可以请你帮忙)

u_u

在xaml中,您将事件处理程序附加到ListViewItem,而在后面的代码中将它附加到ListView本身。 这就是为什么你会有不同的行为。 如果您想在后面的代码中执行相同操作,则必须在项集合中循环al项,并将每个项的DoubleClick事件绑定到您的处理程序。

如果没有真正的理由在后面的代码中执行此操作,我会选择适合MVVM模式的xaml方法,以便在后面的代码中尽可能少地保留代码。

除非您想要在UserControl中使用命名内容,否则不要理解为什么要在代码中执行此操作,以便将其更改为自定义控件。 尝试在后面的代码中重复你的xaml代码,即为ListViewItem创建一个样式并将其设置为listview的ItemContainerStyle。

想办法!! 我确信它应该与双击一样……

在xaml我有:

      ... etc 

我可以用c#在后面的代码上创建相同的东西:

  EventSetter ev = new EventSetter(); ev.Event = ListViewItem.PreviewMouseUpEvent; ev.Handler = new MouseButtonEventHandler(itemClicked); Style myStyle = new Style(); myStyle.TargetType = typeof(ListViewItem); myStyle.Setters.Add(ev); listView.ItemContainerStyle = myStyle; 

….

 void itemClicked(object sender, MouseButtonEventArgs e) { // item was licked in listview implement behavior in here }