确定在执行ContextMenu MenuItem时在ListView中单击了哪个ListViewItem

我正在尝试使用列表视图中的上下文菜单来运行一些代码,这些代码需要来自哪个项目的数据。

我最初只是这样做:

XAML:

           ... 

C#:

  private void cmMetadata_Click(object sender, RoutedEventArgs e) { // code that needs item data here } 

但我发现原始listview项目无法通过这种方式访问​​。

我已经阅读了一些关于如何解决这个问题的策略,比如拦截MouseDown事件并将一个私有字段设置为被点击的listviewitem,但这并不适合我,因为它似乎有点hacky传递数据办法。 WPF应该很容易,对吧? :)我已经阅读了这个问题和这个MSDN论坛问题 ,但我仍然不确定如何真正做到这一点,因为这些文章似乎都不适合我的情况。 有没有更好的方法将点击的项目传递到上下文菜单?

谢谢!

在cmMetadata_Click处理程序中,您只需查询lvResources.SelectedItem属性,因为lvResources可以从单击处理程序所在的代码隐藏文件中访问。它不优雅,但它可以工作。

如果您想要更优雅,可以更改设置ContextMenu的位置。 例如,您可以尝试这样的事情:

        One Item Another item  

这样做是插入ListViewItem的模板,然后您可以使用方便的TemplatedParent快捷方式将ListViewItem分配给菜单项的DataContext。

现在你的代码隐藏看起来像这样:

 private void cmMetadata_Click(object sender, RoutedEventArgs e) { MenuItem menu = sender as MenuItem; ListViewItem item = menu.DataContext as ListViewItem; } 

显然缺点是你现在需要完成ListViewItem的模板,但我相信你可以很快找到一个适合你需求的模板。

类似于查理的答案,但不应该要求XAML更改。

 private void cmMetadata_Click(object sender, RoutedEventArgs e) { MenuItem menu = sender as MenuItem; ListViewItem lvi = lvResources.ItemContainerGenerator.ContainerFromItem(menu.DataContext) as ListViewItem; } 

所以我决定尝试实现一个命令解决方案。 我对它现在如何工作非常满意。

首先,创建我的命令:

 public static class CustomCommands { public static RoutedCommand DisplayMetadata = new RoutedCommand(); } 

接下来在我的自定义列表视图控件中,我添加了一个绑定到构造函数的新命令:

 public SortableListView() { CommandBindings.Add(new CommandBinding(CustomCommands.DisplayMetadata, DisplayMetadataExecuted, DisplayMetadataCanExecute)); } 

还有,添加了事件处理程序:

 public void DisplayMetadataExecuted(object sender, ExecutedRoutedEventArgs e) { var nbSelectedItem = (MyItem)e.Parameter; // do stuff with selected item } public void DisplayMetadataCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } 

我已经使用样式选择器动态地将样式分配给listview项,因此我不必在xaml中执行此操作,而是必须在代码隐藏中设置绑定。 你也可以在xaml中做到这一点:

 public override Style SelectStyle(object item, DependencyObject container) { ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(container); MyItem selectedItem = (MyItem)item; Style s = new Style(); var listMenuItems = new List(); var mi = new MenuItem(); mi.Header= "Get Metadata"; mi.Name= "cmMetadata"; mi.Command = CustomCommands.DisplayMetadata; mi.CommandParameter = selectedItem; listMenuItems.Add(mi); ContextMenu cm = new ContextMenu(); cm.ItemsSource = listMenuItems; // Global styles s.Setters.Add(new Setter(Control.ContextMenuProperty, cm)); // other style selection code return s; } 

我喜欢这种解决方案的感觉比尝试在鼠标点击上设置字段并尝试访问那样点击的内容要好得多。