In the previous month I have written an article about how to design a WPF custom context menu. I really liked that article because the outcome was very nice. Here comes the but :), as it turns out my implementation had a big disadvantage, it lacked the ability to show sub menus (an important trait in my opinion). So it was back to the drawing board for me.

After studying the WPF MenuItem Class and its Original Microsoft Template using blend. I learned some new things

  1. The MenuItem control has a property named Icon that allows you to add an Icon in front of it
  2. Both the Icon property and the Header properties are ContentControls so you can throw whatever you want it there and it will show which means, no need to template them.

Lets look at the code for one MenuItem object:

   1: <MenuItem>
   2:     <MenuItem.Header>
   3:         <TextBlock Text="Option 1" 
   4:                    VerticalAlignment="Center">
   5:         </TextBlock>
   6:     </MenuItem.Header>
   7:     <MenuItem.Icon>
   8:         <Border Background="LightGray" Padding="2" 
   9:                 x:Name="Wrapper">
  10:             <Image Source="Cancel.png" 
  11:                    Width="{StaticResource ImageSize}" 
  12:                    Height="{StaticResource ImageSize}">
  13:             </Image>
  14:         </Border>
  15:     </MenuItem.Icon>                        
  16: </MenuItem>

I have inserted a TextBlock inside the header so I can control better the Alignment, and into the Image I have inserted  a Border with an Image in it. The Border will provide the gray background to all the Images. Of course there is a style also here it is:

   1: <Style TargetType="{x:Type MenuItem}">
   2:     <Setter Property="Background" Value="Gray"></Setter>
   3:     <Setter Property="Foreground" Value="White"></Setter>
   4:     <Setter Property="FontSize" Value="13"></Setter>
   5:     <Setter Property="FontFamily" Value="Verdana"></Setter>
   6:     <Setter Property="Margin" Value="-5,0,0,0"></Setter>
   7:     <Style.Triggers>
   8:         <Trigger Property="IsHighlighted" Value="True">
   9:             <Setter Property="Background" Value="Black"></Setter>
  10:             <Setter Property="FontSize" Value="15"></Setter>
  11:         </Trigger>
  12:         <Trigger Property="IsEnabled" Value="False">
  13:             <Setter Property="Foreground" Value="LightGray"></Setter>
  14:         </Trigger>
  15:     </Style.Triggers>
  16: </Style>

Check out the Is Highlighted Trigger, that’s another thing I found out while researching the MenuItem Class.

The out come is this:

WPF Custom Context Menu

Pretty nice no? And the sub menus are back! And the most important thing: No DataTemplate or ControlTemplates used. All the natural behavior of the WPF Context Menu is preserved. To download a Full Code Example Just grab our feed to get the password to the Freebies page.

Amit

Tags :

10 Responses to “A Better WPF Custom Context Menu Design”


  1. Sarkastik

    Said on October 14, 2008 :

    Sorry but this doesn’t style so well compiled under Vista :(

  2. Amit

    Said on October 14, 2008 :

    What do you mean by that?

    It does not compile in VS? or it does not look right?

    Amit

  3. Sarkastik

    Said on October 15, 2008 :

    It compiles fine but looks different and styling isn’t applied throughout. Mainly because there’s a divider between icon and text, a background behind the icons and the Vista style blue hover.

    The solution is to include a ContextMenu Template and write your own template and style. Overriding the Aero styling that appears under Vista. :)

  4. Amit

    Said on October 15, 2008 :

    I am currently not working on Vista, I will have to check that. It sounds very interesting.

    Amit

  5. Paul

    Said on January 26, 2009 :

    Anyone have a simplistic ContextMenu template / style they’d care to share, as an example?

  6. Shimmy

    Said on March 22, 2009 :

    code??

  7. RightDrop

    Said on September 28, 2009 :

    I have a TreeView that allows moving around TreeViewItems with drag and drop. Once I added your code to do right-click context menus, I get an Exception in my MouseMove event. Is there a way to mix both? Sorry, I am a real WPF newbie (this is my first project), so I am trying to learn a lot.

    void MyTreeView_MouseMove( object sender , MouseEventArgs e )
    {
    if ( !this._isDragging && e.LeftButton == MouseButtonState.Pressed )
    {
    if ( ( (DataStuff)this.MyTreeView.SelectedValue ).Name == “TOPLEVEL” )
    {
    return;
    }
    this._isDragging = true;
    DragDrop.DoDragDrop( this.MyTreeView, this.MyTreeView.SelectedValue , DragDropEffects.Move );
    }
    }

    Thanks.

  8. Shimmy

    Said on October 1, 2009 :

    Is there a way to set the icon via a setter?

  9. Siyad

    Said on March 11, 2010 :

    Hi,
    Is there a way to have scroll buttons on top and bottom of the context menu. THis will be really useful when there are more items on the context menu which may be difficult to show in availble screen area.

  10. third party fire and theft

    Said on March 24, 2014 :

    It is difficult to prove risk based on driving ability between men
    and women, but the risk to the insurance company can be proved by
    the value of the claims made by the different genders.
    Only then do they discover that they never had any real auto insurance
    to speak of. Facing a car insurance fraud even if you’re the victim always
    means that you’ll still have to pay more insurance deductible.

Post a Comment