2
votes

I'm using the ExpressionDark theme for my WPF app, it has a custom style for MenuItems. When a MenuItem is disabled it should use a gray style to reflect this, and it works for MenuItems inside the Menu control:

Working menu state

It does however not work for MenuItems that are in a ContextMenu (Copy is disabled)

Copy should look like disabled

I have tracked down the problem to the TextBlock style, if I remove this style it works for the ContextMenu, but other styles break with it removed

<Style TargetType="{x:Type TextBlock}">
    <Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
</Style>

EDIT: It doesn't matter if I use a MenuItem or my custom GestureMenuItem, but what do matter is if i use a _ char or not (For key shortcuts) If I remove _ then the style wont work in MainMenu either.

The relevant style for the MenuItem:

<Trigger Property="IsEnabled" Value="false">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>

Source code found here. The relevant ContextMenu XAML:

<TextBox x:Name="Text"
    Height="Auto"
    TextWrapping="Wrap"
    VerticalScrollBarVisibility="Visible"
    AcceptsReturn="True"
    IsReadOnly="true">
    <TextBox.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Copy" Command="Copy">
                <MenuItem.Icon>
                    <Image Source="{StaticResource IconCopy}"/>
                </MenuItem.Icon>
            </MenuItem>
            <Separator></Separator>
            <MenuItem cal:Message.Attach="Clear()" Header="Clear All">
                <MenuItem.Icon>
                    <Image Source="{StaticResource IconDelete}"/>
                </MenuItem.Icon>
            </MenuItem>
        </ContextMenu>
    </TextBox.ContextMenu>
</TextBox>

MenuItems in working main menu (GestureMenuItem inherits MenuItem and uses same style):

<Menu IsMainMenu="True">
    <Menu.Resources>
        <Image x:Key="ViewIcon" x:Shared="false"
            Source="{Binding Path=Icon}" />
    </Menu.Resources>
    <!-- Items here removed to shorten XAML -->
    <MenuItem Header="_Script">
        <common:GestureMenuItem x:Name="RunScript" Header="_Run script" Key="F5">
            <MenuItem.Icon>
                <Image Source="{StaticResource IconPlay}"/>
            </MenuItem.Icon>
        </common:GestureMenuItem>
      <common:GestureMenuItem x:Name="StopScript" Header="_Stop script" Key="F5" Modifiers="Shift">
            <MenuItem.Icon>
                <Image Source="{StaticResource IconStop}"/>
            </MenuItem.Icon>
        </common:GestureMenuItem>
    </MenuItem>
    <!-- Items here removed to shorten XAML -->
</Menu>

Gesture item style:

<Style TargetType="{x:Type Caliburn:GestureMenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
</Style>

I came up with a work around, it wont give the exact same style, but it works, should I go for it?

<Trigger Property="IsEnabled" Value="False">
    <Setter Property="Opacity" Value="0.5"/>
</Trigger>

Both gesture text and icon is gray with this solution so maybe it a actually a better solution than just setting Forecolor to gray:

Opacity solution

2
How are the context menu items defined? It might be that you just need to create a second style that targets the right type.ChrisF
Thanks for tuning in! Please see editAnders
How are the menu items in the main menu defined? You are using the Header property to display the text rather than a TextBox. This will be why the code doesn't work.ChrisF
Please see edit, there is no difference in how the menu items are definedAnders
There is. The main menu uses common:GestureMenuItem while the context menu uses MenuItem. These are different. How does the former display the text?ChrisF

2 Answers

4
votes

I solved it by replacing the Forecolor property setter with a Opacity property setter, this will also effect gesture text and icon which is also the default style's way of doing it

Opacity solution

<Trigger Property="IsEnabled" Value="False">
    <Setter Property="Opacity" Value="0.3"/>
</Trigger>
0
votes

I found targeting the ContentPresenters for the InputGestureText and Header individually is more efficient. Targeting the whole MenuItem in my case resulted in see-through MenuItems. I have shown how you can get around that below:

<Trigger Property="IsEnabled" Value="False">
    <Setter TargetName="HeaderHost" Property="Opacity" Value="0.3"/>
    <Setter TargetName="IGTHost" Property="Opacity" Value="0.3"/>
</Trigger>