Reputation: 1264
I have a two-part-question, I hope it's ok to ask them both at once.
I have a WPF ListView
with a GridView
as it's view.
A while ago I was looking for a way to have a ContextMenu
in the ListView
that is only popping up when the user right clicks an actual item of the ListView
.
All the solutions I found online suggested to put this ContextMenu
inside the ItemContainerStyle
, so I did this and it works.
1. question, the general one
But now it got me thinking... if my ListView
contains thousands of items, does that mean I created thousands of identical ContextMenu
s in memory as well? And if I did, isn't there a better way to get one item ContextMenu
?
2. question, the specific one (obsolete, see the EDIT below)
Now I try to get another ContextMenu
to pop up, when the user right clicks on the GridView
s header, and again all the solutions suggest to put it inside the GridViewColumnHeader
.
I have two problems with that. First, it again creates identical ContextMenu
s for each of the columns, and second, the ContextMenu
only pops up, when the user right clicks on one of the column headers. When there is free space inside the header area (because all the columns don't need all the space available), the ContextMenu
won't pop up when right clicking on the free space of the header area.
Is there a way to pop up one ContextMenu
, when right clicking the header area of a GridView
?
I'd prefer the solution to be in XAML only, if that is possible.
Thank you for your help.
EDIT:
Please forget the second part of the question. I found the ColumnHeaderContextMenu
property of the GridView
that is exactly doing what I was looking for.
Upvotes: 0
Views: 580
Reputation: 169320
if my
ListView
contains thousands of items, does that mean I created thousands of identicalContextMenus
in memory as well?
No.
You can confirm this by creating your own custom ContextMenu
type, set a breakpoint in its constructor and debug your application:
Public Class MyContextMenu
Inherits ContextMenu
Public Sub New()
Items.Add(New MenuItem() With {.Header = "1"})
Items.Add(New MenuItem() With {.Header = "2"})
Items.Add(New MenuItem() With {.Header = "3"})
End Sub
End Class
<ListView x:Name="listView1">
<ListView.Resources>
<local:MyContextMenu x:Key="cm" />
</ListView.Resources>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="ContextMenu" Value="{StaticResource cm}" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
The breakpoint won't be hit once for each item that you add to the Items
collection of the ListView
so don't worry about this.
And it doesn't matter whether the property is set using a StaticResource
:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="ContextMenu">
<Setter.Value>
<local:MyContextMenu />
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
Setting the ContextMenu
property of the ItemContainerStyle
is the correct way of associating a context menu with a ListViewItem
container.
Upvotes: 1
Reputation: 3631
Assume the following custom controls:
public class MTextBlock : TextBlock
{
public MTextBlock ()
{// breakpoint
}
}
public class MContextMenu : ContextMenu
{
public MContextMenu()
{// breakpoint
}
}
And the following ItemsControl in Xaml:
<ItemsControl Name="ic" ItemTemplate="{StaticResource res}"/>
in which the ItemsSource will be set in code behind.
If you use the following setup
<DataTemplate x:Key="res">
<TextBlock Text="A a a a a ">
<TextBlock.ContextMenu>
<local:MContextMenu>
<MenuItem Header="Item1">
<local:MTextBlock Text="u" />
</MenuItem>
</local:MContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
multiple instances of MContextMenu and MTextBox will be generated. You can check this by setting breakpoints on the constructors.
However, if you declare the control as a static resource, such as:
<Window.Resources>
<local:MContextMenu x:Key="cm">
<MenuItem Header="Item1">
<local:MTextBox Text="u" />
</MenuItem>
</local:MContextMenu>
<DataTemplate x:Key="res">
<TextBlock Text="{Binding Path=Name}" Background="Transparent" Width="100" ContextMenu="{StaticResource cm}">
</TextBlock>
</DataTemplate>
</Window.Resources>
only one instance of them will be generated. Again check it by setting the proper breakpoints. Note that in this case, if you change the Text property of the MTextBox, if affects all _MTextBox_es in different _ContextMenu_s.
Upvotes: 1