C# WPF MenuItem custom template

27,850

Solution 1

You could just use TemplateBinding on the Header property in the same way you've used it on the Background property:

<ControlTemplate TargetType="{x:Type MenuItem}">
    <Grid Background="{TemplateBinding Background}">
         <MenuItem Header="{TemplateBinding Header}" />
    </Grid>
</ControlTemplate>

Solution 2

You can make an individual style for every MenuItem using a StyleSelector.

public class MyStyleSelector : StyleSelector
{
    public override Style SelectStyle(object item, DependencyObject container)
    {
        var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
        var index = itemsControl.ItemContainerGenerator.IndexFromContainer(container);

        if (index == 0)
            return (Style)itemsControl.FindResource("FirstItemStyle");
        if (index == 1)
            return (Style)itemsControl.FindResource("SecondItemStyle");

        return base.SelectStyle(item, container);
    }
}

And in your XAML

<Window x:Class="Menus.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Menus"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:MyStyleSelector x:Key="MyStyleSelector" />

    <Style x:Key="FirstItemStyle"  TargetType="MenuItem">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Background" Value="#0a99f3" />
                <Setter Property="Foreground" Value="White"/>
            </Trigger>
        </Style.Triggers>
    </Style>

    <Style x:Key="SecondItemStyle"  TargetType="MenuItem">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Background" Value="Red" />
                <Setter Property="Foreground" Value="White"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid>
    <Menu ItemContainerStyleSelector="{StaticResource MyStyleSelector}">
        <MenuItem Header="Menu 1" />
        <MenuItem Header="Menu 2" />
        <MenuItem Header="Menu 3" />
    </Menu>
</Grid>

See StyleSelector here: StyleSelector

Share:
27,850
sparcopt
Author by

sparcopt

Informatics student

Updated on July 18, 2020

Comments

  • sparcopt
    sparcopt almost 4 years

    In Main.xaml I have these two menu items:

    • The first with the header = Disconnect from current
    • The second with the header = Quit
    • ...
    • More menu items with different header texts...

    In order to edit some colors of the first item I created a custom template in App.xaml:

    <!--Template for Menu Items-->
        <Style x:Key="MenuItemBaseStyle" TargetType="MenuItem">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Background" Value="#0a99f3" />
                    <Setter Property="Foreground" Value="White"/>
                </Trigger>
            </Style.Triggers>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type MenuItem}">
                        <Grid Background="{TemplateBinding Background}">
                            <MenuItem Header="DISCONNECT FROM CURRENT" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    And in Main.xaml:

    <MenuItem Header="CONNECTION">
        <MenuItem Style="{StaticResource MenuItemBaseStyle}" Header="DISCONNECT FROM CURRENT" />
        <MenuItem Header="QUIT"/>
    </MenuItem>
    

    Now I want to do the same for the second menu item. The problem is with the different header. If I delete the header from the template, it won't show any header even if the header text is still present in Main.xaml

    How can I use this template for many menu items where the only thing that changes is the header text?

  • AgentFire
    AgentFire over 8 years
    Codebehind is so undesirable.
  • Ketobomb
    Ketobomb over 8 years
    Where do you see a code behind? MyStyleSelector is a separate class.
  • nam
    nam almost 3 years
    I have a similar post here if you have any suggestions/comments etc.