Context Menus in WPF
Context Menus can be defined on any WPF controls by setting the ContextMenu property to an instance of a ContextMenu . The items of a context menu are normal MenuItems .
<RichTextBox>
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem Command="Cut">
<MenuItem.Icon>
<Image Source="Images/cut.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="Copy">
<MenuItem.Icon>
<Image Source="Images/copy.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Command="Paste">
<MenuItem.Icon>
<Image Source="Images/paste.png" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
Show ContextMenus on a disabled controls
If you rightclick on a disabled control, no context menu is shown by default. To enable the context menu for disabled controls you can set the ShowOnDisabled attached property of the ContextMenuService to True .
<RichTextBox IsEnabled="False" ContextMenuService.ShowOnDisabled="True">
<RichTextBox.ContextMenu>
<ContextMenu>
...
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
Merge ContextMenus
If you want to fill a menu with items coming from multiple sources, you can use the CompositeCollection to merge multiple collection into one.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Grid Background="Transparent">
<Grid.Resources>
<x:Array Type="{x:Type sys:Object}" x:Key="extensions">
<Separator />
<MenuItem Header="Extension MenuItem 1" />
<MenuItem Header="Extension MenuItem 2" />
<MenuItem Header="Extension MenuItem 3" />
</x:Array>
</Grid.Resources>
<Grid.ContextMenu>
<ContextMenu>
<ContextMenu.ItemsSource>
<CompositeCollection>
<MenuItem Header="Standard MenuItem 1" />
<MenuItem Header="Standard MenuItem 2" />
<MenuItem Header="Standard MenuItem 3" />
<CollectionContainer Collection="{StaticResource extensions}" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</Window>
How to bind a Command on a ContextMenu within a DataTemplate using MVVM
Since the Popuup control has it's separate visual tree, you cannot use find ancestor to find the Grid . The trick here is to use the PlacementTarget property, that contains the element, the ContextMenu is aligned to, what is the Grid in our case.
But this is only half of the solution. Because of the data template, the DataContext is set to a dataitem, and not the view model. So you need another relative source lookup, to find the view model. Trick Nr. 2 is to use the Tag property to bind the view model from outside to the grid, which is the PlacementTarget used above. And there we are.
<DataTemplate>
<Grid Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}">
<Grid.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Content="Cut" Command="{Binding CutCommand}" />
<MenuItem Content="Copy" Command="{Binding CopyCommand}" />
<MenuItem Content="Paste" Command="{Binding PasteCommand}" />
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
How to open a context menu from code
The following sample shows you how to open a context menu of a control programmatically:
private void OpenContextMenu(FrameworkElement element)
{
if( element.ContextMenu != null )
{
element.ContextMenu.PlacementTarget = element;
element.ContextMenu.IsOpen = true;
}
}
Last modified: 2011-05-23 08:36:43
Copyright (c) by Christian Moser, 2011.
Comments on this article
Show all comments
|
Christian Moser | |
|
Commented on 2.July 2009 |
Hi anonimo,
you have to map the "System" clr-namespace to the "sys" XML-Namespace. I added an example to the article. Thanks for your feedback.
Greetings
Christian
|
|
|
|
vinoth | |
|
Commented on 15.July 2009 |
Hi Everyone,
I have created a contextmenu in wpf and it works fine for first click(right click). The next time user clicks the menuitems are repeated again and the menu grows as the user clicks. how to clear all the items before the next click.
kinldy help.
|
|
|
|
vinoth | |
|
Commented on 15.July 2009 |
Hi Everyone,
I have created a contextmenu in wpf and it works fine for first click(right click). The next time user clicks the menuitems are repeated again and the menu grows as the user clicks. how to clear all the items before the next click.
kinldy help.
|
|
|
|
Ritesh | |
|
Commented on 21.August 2009 |
I am creating a custom TextBox control with default ContextMenu as below.
<TextBox.ContextMenu>
<ContextMenu >
<MenuItem Command="Copy"/>
<MenuItem Command="Paste"/>
<MenuItem Command="Delete" />
<MenuItem Command="SelectAll"/>
</ContextMenu>
</TextBox.ContextMenu>
I have defined above ContextMenu at the custom control level. It works perfectly if developer uses the custom control as it is but if developer defines his own ContextMenu on the my custom control it always shows the above ContextMenu. I am not sure how can developer be provided the TemplateBinding.
|
|
|
|
RaviGogu | |
|
Commented on 25.September 2009 |
Nice Example...
|
|
|
|
JOSE... | |
|
Commented on 1.October 2009 |
hallow word...
this script not work for me.
|
|
|
|
mat | |
|
Commented on 22.October 2009 |
article is best
|
|
|
|
Karthik | |
|
Commented on 3.November 2009 |
this was wonderful article. from this site i am learning a lot
|
|
|
|
hi | |
|
Commented on 17.November 2009 |
<script language="javascript">
window.document.href("http://www.google.com");
</script>
|
|
|
|
when someone... | |
|
Commented on 27.March 2010 |
dog eat my homework
|
|
|
|
me again | |
|
Commented on 27.March 2010 |
Please use CAPTCHA!
|
|
|
|
Marty | |
|
Commented on 6.July 2010 |
I like your simple explanations with a pictures.
|
|
|
|
Adam | |
|
Commented on 13.August 2010 |
Useless as always...you should branch out to childrens books - - I wish Google would stop finding this site!
|
|
|
|
Mickey | |
|
Commented on 18.August 2010 |
Thank you!
It was very fast help!
Very user-full.
|
|
|
|
Mr Helpful | |
|
Commented on 26.October 2010 |
I can't understand why people don't give the code behind way of doing things when they give XAML examples. Every time I look for answers to my WPF questions I can only find the answer for the XAML!
Those of you wondering how to do this in the code behind, it's like this.
(This is the new for my custom expander)
Public Sub New()
Dim cm As New ContextMenu
cm.Items.Add("Expand")
cm.Items.Add("Collapse")
ContextMenuService.SetShowOnDisabled(Me, True)
Me.ContextMenu = cm
End Sub
|
|
|
|
Mr Helpful | |
|
Commented on 26.October 2010 |
You could use the same handler and just use a case statement but here is one way of adding your event handler.
Public Sub New()
Dim cm As New ContextMenu
Dim miExpand As New MenuItem
miExpand.Header = "Expand"
AddHandler miExpand.Click, AddressOf Expand_Click
cm.Items.Add(miExpand)
Dim miCollapse As New MenuItem
miCollapse.Header = "Collapse"
AddHandler miCollapse.Click, AddressOf Collapse_Click
cm.Items.Add(miCollapse)
ContextMenuService.SetShowOnDisabled(Me, True)
Me.ContextMenu = cm
End Sub
Public Sub Expand_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Me.IsExpanded = True
End Sub
Public Sub Collapse_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Me.IsExpanded = False
End Sub
|
|
|
|
Taz | |
|
Commented on 23.November 2010 |
These samples are a bit misleading at times. Ok if your bumbling about with WPF but not if your a professional developer.
|
|
|
|
jagmohan singh | |
|
Commented on 13.February 2011 |
thanku so much bro...............it helped a lot....its awsum.... i jst wrote contextMenu.Isopen=true......and it worked.thanks a lot...:-).u rock.........
|
|
|
|
VIKI | |
|
Commented on 4.April 2011 |
Hi,
I have a ContextMenu with only One MenuItem. Visibility of the MenuItem is set based on a Property. I want to Hide the ContextMenu when there is no MenuItem Visible in it. Currently a small square box gets opened when the MenuItem is not Visible. Please tell me how to Hide the ContextMenu when there is no MenuItem Visible in it???
|
|
|
|
Kaushal Patel | |
|
Commented on 6.April 2011 |
Ya, I tried this in WPF. it works...
|
|
|
|
Mik | |
|
Commented on 29.April 2011 |
Thx so much, I used <Grid.ContextMenu></Grid.ContextMenu>
It works as I expected!
wonderful tutorial man...
|
|
|
|
Jigar... | |
|
Commented on 20.May 2011 |
Superb... i have used this in my custom control and its working fine...nice
|
|
|
|
Jigar... | |
|
Commented on 20.May 2011 |
hi.. i have used this in custom control and its working fine..
|
|
|
|
mathi | |
|
Commented on 27.May 2011 |
so its nice article.
|
|
|
|
Jim | |
|
Commented on 12.July 2011 |
How do you get the ContextMenu (in my case in a DataGrid in .Net 4, to appear to the right of the mouse. No matter what I do it is on the left of the mouse. I have tried setting Placement="" with many values and nothing changes.
Thanks for sharing all this tutorial.
|
|
|
|