从 ContextMenu 中的 MenuItem 访问 ListViewItem 信息

Access ListViewItem information from MenuItem in ContextMenu

我有一个包含多个项目的 ListView。我想在系统剪贴板中复制与给定行关联的信息(例如,该行中项目的 ID)。

我创建了一个右键单击一行时打开的 ContextMenu,它显示一个用于复制 ID 的 MenuItem:

<ListView x:Name="MyListView" MouseDoubleClick="MyListView_MouseDoubleClick">
    <ListView.Columns>
        <GridViewColumn Header="Id" DisplayMemberBinding="{Binding MyItem.Id}"/>
    </ListView.Columns>
    <ListView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type mynamespace:MyItemDefinition}" ItemsSource="{Binding MyGroupOfItems, Mode=OneWay}" />
    </ListView.ItemTemplate>
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem x:Name="MenuItemCopyId" Header="Copy ID" Click="MenuItemCopyId_Click"/>
        </ContextMenu>
    </ListView.ContextMenu>
</ListView>

private void MenuItemCopyId_Click(object sender, RoutedEventArgs e)
{
     var menu_item = ((System.Windows.Controls.MenuItem)sender);
}

对于我阅读的内容 (ListViewItem Context Menu Get Data from ListViewItem),它需要访问项目的 DataContext。这可以通过 ContextMenu 的 PlacementTarget 来实现,但我无法做到。有什么建议吗?

提前致谢

您通常可以使用 PlacementTarget 执行一些相对绑定并提供 ContextMenu 通常不会有的信息,因为它在可视化树之外。鉴于您在此处进行设置的方式,我不确定这对您来说效果如何。看起来您想要一个属于 ListView 但在右键单击的行上有效的上下文菜单。您可以通过在 ContextOpening 事件中手动附加 DataContext 来实现。例如,我大致按照您的要求设置了 ListView

<ListView ItemsSource="{Binding MyGroupOfItems}">
    <ListView.Resources>
        <Style TargetType="ListViewItem">
            <EventSetter Event="ContextMenuOpening" Handler="ListViewItem_ContextMenuOpening" />
        </Style>
    </ListView.Resources>
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Id}" />
        </GridView>
    </ListView.View>
    <ListView.ContextMenu>
        <ContextMenu Name="menu">
            <MenuItem Header="Copy ID" Click="MenuItem_Click" />
        </ContextMenu>
    </ListView.ContextMenu>
</ListView>

我为 ListViewItem 添加了一个样式来处理 ContextMenuOpening events.This 将允许您在上下文菜单打开时知道您在哪一行。在后面的代码中,您可以为该行附加 DataContext

private void ListViewItem_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
    ListViewItem listItem = sender as ListViewItem;
    menu.DataContext = listItem.DataContext;
}

在本例中,菜单是 ContextMenu 的名称。我只是从 ListItemView 中获取 DataContext 并将其附加到 ContextMenu.

现在,当您处理菜单单击事件时,您可以获取该数据并使用它来执行您需要执行的任何操作。

private void MenuItem_Click(object sender, RoutedEventArgs e)
{
    MyItem item = (MyItem)(sender as MenuItem).DataContext;
    //Now you can do stuff with MyItem
}

请注意:我省略了您使用 HierarchicalDataTemplate 所做的事情,因为我不理解其意图,而且对我而言,它不会导致任何渲染。无论如何,这种在打开 ContextMenu 时附加 DataContext 的策略应该转移到其他用例。