views:

2725

answers:

5

I am trying to modify the default style of the ContextMenu in WPF.

Normally you can creat a copy of the default in Expression Blend using the Edit Control Parts (Template) > Edit a Copy menu option. However I can't work out how to do this with a ContextMenu. Any idea how I can get the default style to modify?

I am trying to disable the left side of the context menu where the icons are normally shown.

Thanks!

Update: Maybe I wasn't clear about removing the icons. For example, if you have a context menu with no icons then the whole left side of the menu is wasted space. I would like to modify the default style of the context menu background to remove this. Simply I don't know how to access this default style.

+1  A: 
Jobi Joy
Well that gets me the default style for the MenuItem, however it doesn't get me the ContextMenu style. Expression Blend won't let me add a ContextMenu to the Window.
Luke
It shows an error, "ContextMenu cannot have logical or visual parent" if I add the ContextMenu to the window.
Luke
Yes, there is also styles within the ContextMenu for the left side menu that need to be removed. It is the ContextMenu styles that I can't access using the Expression interface. I have posted a solution below to extract the template using code.
Luke
A: 

The extra space on the left is due to the little check mark that appears when you set IsCheckable and IsChecked to true on MenuItem.

The check mark is in the template for MenuItem so if you edit that you can take it out.

Robert Macnee
+3  A: 

For templates and styles that are not accessible through the Expression Interface (such as the ContextMenu template) you can use the following code to extract the template:

Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder
Using Writer As TextWriter = New StringWriter(sb)
    System.Windows.Markup.XamlWriter.Save(ContextMenu.Template, Writer)
End Using
Debug.Write(sb.ToString)

Or in C#

var str = new StringBuilder();
using (var writer = new StringWriter(str))
    XamlWriter.Save(ContextMenu.Template, writer);
Debug.Write(str);
Luke
Please note than in order to get a template in a ContextMenu you have to at least add one MenuItem to its Items collection. Otherwise the ContextMenu.Template is null.
Julio Garcia
I love Stack Overflow. Thanks so much for these responses, exactly what I needed too.
Scott Bilas
+1  A: 

Here is link to article which contains information about replacing template of context menu.

(www).dev102.com/2008/06/20/how-to-create-a-wpf-custom-context-menu/

A: 

I found the easy way to get the ContextMenu template in Blend:

  1. I added a ContextMenu to a button with some menuitems.
  2. Under "miscellaneous" in the properties pane, there's a grouped item for ContextMenu.
  3. Open this. You'll find the usual Style and Template properties.
  4. Click the square for the popup menu, and select Convert to New Resource...

That's it. Pick where you want the template/style to be put, and you're done.

Here's the markup I had:

<StackPanel x:Name="LayoutRoot">
    <Button Content="Click for ContextMenu" Width="30" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button.ContextMenu>
            <ContextMenu Template="{DynamicResource ContextMenuControlTemplate1}" Style="{DynamicResource ContextMenuStyle1}">
                <MenuItem Header="File"/>
                <MenuItem Header="Edit"/>
                <MenuItem Header="View"/>
                <MenuItem Header="Recent Files"/>
                    <MenuItem Header="file1.txt"/>
                    <MenuItem Header="file2.txt"/>
            </ContextMenu>
        </Button.ContextMenu>
    </Button>
</StackPanel>

And the style/template I got:

<Style x:Key="ContextMenuStyle1" TargetType="{x:Type ContextMenu}">
    <Setter Property="Background" Value="{DynamicResource MenuBackgroundBrush}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="BorderBrush" Value="{DynamicResource WindowBorderBrush}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ContextMenu}">
                <Border Uid="Border_93">
                    <Border.Style>
                        <Style TargetType="{x:Type Border}">
                            <Setter Property="Tag" Value="{DynamicResource {x:Static SystemParameters.DropShadowKey}}"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="True">
                                    <Setter Property="Background" Value="Transparent"/>
                                    <Setter Property="Padding" Value="0,0,5,5"/>
                                    <Setter Property="Effect">
                                        <Setter.Value>
                                            <DropShadowEffect BlurRadius="4" Opacity="0.8" ShadowDepth="1"/>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Border.Style>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Hope this helps. In usual MS thoroughness, the brushes in the default style aren't found. :)

dex3703