2
votes

I ran through one issue, need to apply conditional styling on Menu Item, here is a bit from my Code-Snippet:

<Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="0,10,0,0">
    <Menu HorizontalAlignment="Left" KeyboardNavigation.TabNavigation="Once" Background="Transparent" d:LayoutOverrides="Height">
        <MenuItem Header="Menu1" Style="{DynamicResource M_Left}"  />
        <MenuItem Header="Menu2" Style="{DynamicResource M_Middle}" />
        <MenuItem Header="Menu3" Style="{DynamicResource M_Right}" Visibility="{Binding IsEligibleToDisplay, Converter={StaticResource MyVisibilityConverter}}" />
    </Menu>
</Grid>

In above, IsEligibleToDisplay a bool property and MyVisibilityConverter sets Visibility either to Visible or Hidden on the basis of True or false.

What is expected?

If Visibility of "Menu3" is Hidden i.e. IsEligibleToDisplay = false then Style of "Menu2" should be Style="{DynamicResource M_Right}" otherwise Style="{DynamicResource M_Middle}"

Something like (its just hypothetic, please do not check syntax - its wrong:)):

<MenuItem Header="Menu2" Style="IsEligibleToDisplay ? {DynamicResource M_Middle} : {DynamicResource M_Right}" />  

Any help will be highly appreciated!

3

3 Answers

4
votes

If your requirement is to use just XAML, I guess you can use DataTriggers.

You cannot set your "condition" directly in the Style property, but you have to move it inside the Style declaration.

Probably this small sample can help you in resolving your task:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="400">

    <Window.Resources>

        <Style x:Key="ConditionalStyle" TargetType="MenuItem">
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=Menu3, Path=Visibility}" Value="Visible">
                    <Setter Property="Foreground" Value="Red" />
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=Menu3, Path=Visibility}" Value="Hidden">
                    <Setter Property="Foreground" Value="Green" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>


    <StackPanel>
        <Menu HorizontalAlignment="Left" KeyboardNavigation.TabNavigation="Once" Background="Transparent">
            <MenuItem Header="Menu1" />
            <MenuItem Header="Menu2" Style="{DynamicResource ConditionalStyle}" />
            <MenuItem Name="Menu3" Header="Menu3" Visibility="Visible" />
        </Menu>

        <Button Content="ClickMe" Margin="10" Click="Button_Click" />
    </StackPanel>
</Window>

I used the button just to switch Menu3 from Visible to Hidden and viceversa. I used a simple handler:

private void Button_Click(object sender, RoutedEventArgs e)
{
    if(Menu3.Visibility == System.Windows.Visibility.Visible)
    {
        Menu3.Visibility = System.Windows.Visibility.Hidden;
        return;
    }
    Menu3.Visibility = System.Windows.Visibility.Visible;
}

I hope this solution is suitable for you.

2
votes

One approach you might want to consider, is using a style selector on your Menu control using the ItemContainerStyleSelector property.

ItemContainerStyleSelector Property

This will allow you to create custom logic to set the styles you need on your individual MenuItems.

1
votes

Maybe you can try to use a datatrigger based on IsEligibleToDisplay property and use a common template.

Put this exemple in ResourceDictionary :

        <!-- The visibility converter -->
        <BooleanToVisibilityConverter x:Key="MyVisibilityConverter" />

        <!-- Common template -->
        <ControlTemplate x:Key="myContent">
            <Label Content="{Binding Header, RelativeSource={RelativeSource TemplatedParent}}" 
                       HorizontalAlignment="Center"
                       HorizontalContentAlignment="Center"
                      Padding="0"
                       Height="20" 
                       Width="80" 
                       Background="Green"/>

        </ControlTemplate>

        <!-- M_Left style -->
        <Style x:Key="M_Left"
               TargetType="MenuItem">
            <Setter Property="Background"
                    Value="Yellow" />
        </Style>

        <Style x:Key="M_Middle"
               TargetType="MenuItem">
            <Setter Property="Background"
                    Value="Red" />
            <Style.Triggers>
                <!-- trigger based on IsEligibleToDisplay property -->
                <DataTrigger Binding="{Binding IsEligibleToDisplay}"
                             Value="false">
                    <!-- If false then apply common template to middle menu item. -->
                    <Setter Property="Template"
                            Value="{DynamicResource myContent}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="M_Right"
               TargetType="MenuItem">
            <Setter Property="Template"
                    Value="{DynamicResource myContent}" />
        </Style>