WPF. Consider the following style with template, and how it affects padding on a MenuItem
. (These are padding-related lines extracted from a style in MaterialDesignTheme.Menu.xaml
of MaterialDesignThemes.Wpf
in github from http://materialdesigninxaml.net/.)
<Style TargetType="{x:Type MenuItem}" x:Key="MaterialDesignMenuItem" BasedOn="{x:Null}">
<Setter Property="Padding" Value="24 0"></Setter>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<ControlTemplate.Resources>
</ControlTemplate.Resources>
<Grid ClipToBounds="True">
</Grid>
<ControlTemplate.Triggers>
<!--#region Roles Triggers -->
<Trigger Property="Role" Value="TopLevelHeader">
<Setter Property="Padding" Value="16 0"/>
</Trigger>
<Trigger Property="Role" Value="TopLevelItem">
<Setter Property="Padding" Value="16 0"/>
</Trigger>
<!--#endregion-->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It is easy to override the default padding line
<Setter Property="Padding" Value="24 0"></Setter>
like so:
<Style TargetType="MenuItem" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="Padding" Value="4 0"></Setter>
</Style>
What I haven't been able to find, is how to define the two TopLevel... Triggers such that their common padding value "16 0"
can be overridden.
In the actual code, these triggers do more, so I don't want to totally override the triggers; I'd have to duplicate the rest of the trigger code.
I'd like to have the original style specify a default for these, which I can override. Something like:
<Style TargetType="{x:Type MenuItem}" x:Key="MaterialDesignMenuItem" BasedOn="{x:Null}">
<Setter Property="Padding" Value="24 0"></Setter>
<Setter Property="TopPadding" Value="16 0"></Setter>
...
Then override:
<Style TargetType="MenuItem" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="Padding" Value="4 0"></Setter>
<Setter TopPadding="Padding" Value="4 0"></Setter>
</Style>
But of course there is no "TopPadding" property on MenuItem, so this won't compile.
How do I create this new property within the original style, refer to it in the template - in the two triggers, and then override it in my customized style?
Possibly related answers:
Bind to resource keys on each item
Bind to attached property
Worst case, I could subclass MenuItem, and make a template that only applies to that subclass (to add "TopPadding" property). I'd prefer not to do that, as this is part of a complex library; I'd like to have a template that will work with any MenuItem. I think that means any attached property would have to be optional (a MenuItem might not have it.) I'm not sure how the template would refer to an attached property, nor how to set a default if it is missing.
IMPORTANT: I don't want a hack that uses Tag
property; I want a scaleable approach that somehow adds an appropriate property or resource.
UPDATE
I just found this answer; I did not realize that attached properties don't have to be defined in the original class - can define one without subclassing MenuItem.
I'm not clear whether I can set a default value in case this attached property is missing, but I am attempting to do so now.