Reputation: 584
I have a ListView with several items. I would like to copy in the system clipboard, information associated to a given row (e.g. id of the item in that row).
I have created a ContextMenu that opens when right clicking a row, and it displays a MenuItem to copy the id:
<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>
and
private void MenuItemCopyId_Click(object sender, RoutedEventArgs e)
{
var menu_item = ((System.Windows.Controls.MenuItem)sender);
}
For what I read (ListViewItem Context Menu Get Data from ListViewItem) it needs to access the DataContext of the item. Which can be achieved through the PlacementTarget of the ContextMenu, but I cannot manage to do it. Any suggestions?
Thanks in advance
Upvotes: 1
Views: 677
Reputation: 1389
You can often use the PlacementTarget
to perform some relative binding and give ContextMenu
information it wouldn't normally have because it's outside the visual tree. Given the way you have things setup here, I'm not sure that would work out too well for you. It looks like you want a context menu that belongs to the ListView
but works on the row that is right clicked on. You can do that by manually attaching the DataContext
in the ContextOpening
event. For example, I loosely followed what you had to set up a 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>
I added a style for the ListViewItem
that handles ContextMenuOpening
events.This will allow you to know which row you're over when the context menu is opening. In the code behind, you can attach the DataContext
for that row.
private void ListViewItem_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
ListViewItem listItem = sender as ListViewItem;
menu.DataContext = listItem.DataContext;
}
In this case, menu is the name of the ContextMenu
. I simply grab the DataContext
from the ListItemView
and attach it to the ContextMenu
.
Now when you handle the menu click event, you can fetch that data and use it to do whatever you need to do.
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MyItem item = (MyItem)(sender as MenuItem).DataContext;
//Now you can do stuff with MyItem
}
Just a note: I omitted the stuff you were doing with the HierarchicalDataTemplate
because I didn't understand the intent, and for me it was causing nothing to render. Regardless, this strategy for attaching the DataContext
when opening the ContextMenu
should transfer to other use cases.
Upvotes: 2