我正在尝试使用列表视图中的上下文菜单来运行一些代码,这些代码需要来自哪个项目的数据. 我最初只是这样做了: XAML: ListView x:Name="lvResources" ScrollViewer.VerticalScrollBarVisibility="Visibl
我最初只是这样做了:
XAML:
<ListView x:Name="lvResources" ScrollViewer.VerticalScrollBarVisibility="Visible"> <ListView.Resources> <ContextMenu x:Key="resourceContextMenu"> <MenuItem Header="Get Metadata" Name="cmMetadata" Click="cmMetadata_Click" /> </ContextMenu> </ListView.Resources> <ListView.ItemContainerStyle> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="ContextMenu" Value="{StaticResource resourceContextMenu}" /> </Style> </ListView.ItemContainerStyle> ...
C#:
private void cmMetadata_Click(object sender, RoutedEventArgs e) { // code that needs item data here }
但我发现原始listview项目无法通过这种方式访问.
我已经阅读了一些关于如何解决这个问题的策略,比如拦截MouseDown事件并将一个私有字段设置为被点击的listviewitem,但这并不适合我,因为它似乎有点hacky传递数据办法. WPF应该很容易,对吧? :)我已经阅读了这个SO question和这个MSDN forum question,但我仍然不确定如何真正做到这一点,因为这些文章似乎都不适用于我的情况.有没有更好的方法将点击的项目传递到上下文菜单?
谢谢!
在cmMetadata_Click处理程序中,您可以只查询lvResources.SelectedItem属性,因为lvResources可以从单击处理程序所在的代码隐藏文件中访问.它不优雅,但它可以工作.如果您想要更优雅,可以更改设置ContextMenu的位置.例如,您可以尝试这样的事情:
<ListView x:Name="lvResources" ScrollViewer.VerticalScrollBarVisibility="Visible"> <ListView.Style> <Style TargetType="ListView"> <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="{x:Type ListViewItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListViewItem}"> <TextBlock Text="{TemplateBinding Content}"> <TextBlock.ContextMenu> <ContextMenu> <MenuItem Header="Get Metadata" Name="cmMetadata" Click="cmMetadata_Click" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"/> </ContextMenu> </TextBlock.ContextMenu> </TextBlock> </ControlTemplate> </Setter.Value> </Setter> </Style> </Setter.Value> </Setter> </Style> </ListView.Style> <ListViewItem>One Item</ListViewItem> <ListViewItem>Another item</ListViewItem> </ListView>
这样做是插入ListViewItem的模板,然后您可以使用方便的TemplatedParent快捷方式将ListViewItem分配给菜单项的DataContext.
现在你的代码隐藏看起来像这样:
private void cmMetadata_Click(object sender, RoutedEventArgs e) { MenuItem menu = sender as MenuItem; ListViewItem item = menu.DataContext as ListViewItem; }
显然缺点是你现在需要完成ListViewItem的模板,但我相信你可以很快找到一个适合你需求的模板.