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上不是行的任何内容,它将返回当前所选项
为什么我的代码不起作用? 我究竟做错了什么?
附加行为模式
我认为你应该使用附加行为,因为
- MVVM♥附加行为
- 它是可重用的:一旦你创建了附加的行为和双击的命令,你可以将它附加到任何其他控件类型(所以你可以使用相同的代码双击图像等)
- 抽象脏实现,因此xaml和视图模型都更清晰
- 他们的工作方式很棒,我喜欢使用聪明的代码。
你做的是什么:
创建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 }