How would you like your WPF application to have a Context Menu like this:
Well, It is not so hard. Here is how you do it:
This is the Context Menu that was defined for this example:
2:Â Â Â <TextBox.ContextMenu>
3:Â Â Â Â Â Â Â <ContextMenu Style=”{StaticResource ContextMenuStyle}”>
4:Â Â Â Â Â Â Â Â Â Â <MenuItem x:Name=”MenuItem1″ Header=”Cut” Command=”Cut”
5:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Style=”{StaticResource ContextMenuItem}”
6:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Tag=”pack://application:,,,/ContextMenu;Component/Cut.png”>
7:Â Â Â Â Â Â Â Â Â Â Â </MenuItem>
8:Â Â Â Â Â Â Â Â Â Â <MenuItem x:Name=”MenuItem2″ Header=”Copy” Command=”Copy”
9:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Style=”{StaticResource ContextMenuItem}”
10:Â Â Â Â Â Â Â Â Â Â Â Â Â Tag=”pack://application:,,,/ContextMenu;Component/Copy.png”>
11:Â Â Â Â Â Â Â Â Â </MenuItem>
12:Â Â Â Â Â Â Â Â Â Â <MenuItem x:Name=”MenuItem3″ Header=”Paste” Command=”Paste”
13:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Style=”{StaticResource ContextMenuItem}”
14:Â Â Â Â Â Â Â Â Â Â Â Â Tag=”pack://application:,,,/ContextMenu;Component/Paste.png”>
15:Â Â Â Â Â Â Â Â Â </MenuItem>
16:Â Â Â Â Â Â Â Â Â Â <MenuItem x:Name=”MenuItem4″ Header=”Delete” Command=”Delete”
17:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Style=”{StaticResource ContextMenuItem}”
18:Â Â Â Â Â Â Â Â Â Â Â Â Tag=”pack://application:,,,/ContextMenu;Component/Delete.png”>
19:Â Â Â Â Â Â Â Â Â Â </MenuItem>
20:Â Â Â Â </ContextMenu>
21:Â Â </TextBox.ContextMenu>
22: </TextBox>
As you can see both the Context Menu and The MenuItem have styles, and this is where all the magic happens :).
The context menu style is very simple:
2:Â Â Â Â Â <Setter Property=”BorderBrush”
3:Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource ContextMenuBorderColor}”>
4:Â Â Â Â Â </Setter>
5:Â Â Â Â Â <Setter Property=”BorderThickness”
6:Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”1″>
7:Â Â Â Â Â Â Â </Setter>
8:Â Â Â Â Â <Setter Property=”Background”
9:Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource ContextMenuBackgroundColor}”>
10:Â Â Â Â Â Â </Setter>
11:Â Â Â Â Â <Setter Property=”Padding”
12:Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”-1″>
13:Â Â Â Â Â Â Â </Setter>
14:Â Â Â Â Â Â <Setter Property=”FontSize”
15:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”13″>
16:Â Â Â Â Â Â </Setter>
17: </Style>
The real work is with the MenuItem Style. It is basically a ControlTemplate for the MenuItem where I use an Image and a TextBlock to design the Item.
-
To create the disable Item effect I used a Trigger that is Triggered by the IsEnabled property of the MenuItem (I initially did not believe it will work , but it did!)
-
The Disabled look is achieved by a Border with a Gray Background and some opacity, so it looked grayed out.
-
Another trick is passing the Image URI in the Tag property and then binding to it from the Image.Source property using a Converter.
Ok so here is the code. You can download the sample project to check it all out.
2:Â Â Â <Setter Property=”MenuItem.Template”>
3:Â Â Â Â Â Â <Setter.Value>
4:Â Â Â Â Â Â Â Â Â <ControlTemplate>
5:Â Â Â Â Â Â Â Â Â Â Â Â <Border HorizontalAlignment=”Stretch” x:Name=”Root” >
6:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Grid>
7:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Grid.ColumnDefinitions>
8:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <ColumnDefinition Width=”26″></ColumnDefinition>
9:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <ColumnDefinition Width=”130″></ColumnDefinition>
10:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Grid.ColumnDefinitions>
11:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Border HorizontalAlignment=”Stretch”
12:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â VerticalAlignment=”Stretch”
13:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â x:Name=”ImageWrapper”
14:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Background=”{StaticResource MenuItemImageColor}”
15:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Grid.Column=”0″>
16:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Image Width=”24″ Height=”24″ Margin=”1″
17:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Source=”{TemplateBinding Property=MenuItem.Tag,
18:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Converter={x:Static data:URI2ImageConverter.Instance}}”>
19:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Image>
20:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Border>
21:Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Border Grid.Column=”1″ x:Name=”NameWrapper”
22:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â HorizontalAlignment=”Stretch” Padding=”1,0,2,0″>
23:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <TextBlock Text=”{TemplateBinding MenuItem.Header}”
24:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â x:Name=”Name”
25:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Foreground=”{StaticResource MenuItemTextColor}”
26:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â VerticalAlignment=”Center”
27:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â HorizontalAlignment=”Stretch”
28:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Margin=”2,0,0,0″ ></TextBlock>
29:Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Border>
30:Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Border x:Name=”DisabledOverlay”
31:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â HorizontalAlignment=”Stretch”
32:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â VerticalAlignment=”Stretch”
33:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Grid.Column=”0″ Grid.ColumnSpan=”2″
34:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Background=”{StaticResource ContextMenuBorderColor}”
35:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Opacity=”0″ >
36:Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Border>
37:Â Â Â Â Â Â Â Â Â Â Â </Grid>
38:Â Â Â Â Â Â Â </Border>
39:Â Â Â Â Â <ControlTemplate.Triggers>
40:Â Â Â Â Â Â Â Â <Trigger Property=”IsMouseOver” Value=”true” SourceName=”Root”>
41:Â Â Â Â Â Â Â Â Â Â Â <Trigger.Setters>
42:Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Setter Property=”Background”
43:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TargetName=”NameWrapper”
44:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource MenuItemTextColor}” >
45:Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Setter>
46:Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Setter Property=”Background”
47:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TargetName=”Name”
48:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource MenuItemTextColor}” >
49:Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Setter>
50:Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Setter Property=”Foreground”
51:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TargetName=”Name”
52:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource MenuItemHoverTextColor}” >
53:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Setter>
54:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Setter Property=”Background”
55:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TargetName=”ImageWrapper”
56:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource MenuItemTextColor}” >
57:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Setter>
58:Â Â Â Â Â Â Â Â Â Â Â Â Â </Trigger.Setters>
59:Â Â Â Â Â Â Â Â Â Â </Trigger>
60:Â Â Â Â Â Â Â Â Â Â <Trigger Property=”IsEnabled” Value=”false” SourceName=”Root”>
61:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Trigger.Setters>
62:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Setter Property=”Opacity”
63:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TargetName=”DisabledOverlay”
64:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”0.7″ ></Setter>
65:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â <Setter Property=”Foreground”
66:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â TargetName=”Name”
67:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Value=”{StaticResource ContextMenuBorderColor}” >
68:Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Setter>
69:Â Â Â Â Â Â Â Â Â Â Â Â Â Â </Trigger.Setters>
70:Â Â Â Â Â Â Â Â Â Â </Trigger>
71:Â Â Â Â Â Â Â Â </ControlTemplate.Triggers>
72:Â Â Â Â Â Â Â </ControlTemplate>
73:Â Â Â Â Â </Setter.Value>
74:Â Â Â </Setter>
75: </Style>Â Â Â
Some of you will as why is the Converter a Singleton, There is a good reason for that and I will explain it in a post later on.
To download the Sample Project Subscribe to our feed and get access to our Freebies Page
If you have any questions please comment.
Enjoy
Amit
By Michael on Jun 20, 2008 | Reply
Good work, Amit.
I think that this post http://weblogs.asp.net/okloeten/archive/2007/11/14/5149692.aspx may complete the picture.