WPF。考虑以下使用模板的样式,以及它如何影响MenuItem上的填充。(这些是从github的MaterialDesignTheme.Menu.xaml of MaterialDesignThemes.Wpf中的样式中从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>很容易覆盖默认的填充行。
<Setter Property="Padding" Value="24 0"></Setter>就像这样:
<Style TargetType="MenuItem" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="Padding" Value="4 0"></Setter>
</Style>我找不到的是如何定义两个TopLevel.触发器,以便可以覆盖它们的公共填充值"16 0"。
在实际代码中,这些触发器做得更多,所以我不想完全覆盖触发器;我必须复制其余的触发器代码。
我想让原始样式为这些指定一个默认值,我可以重写它。类似于:
<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>
...然后覆盖:
<Style TargetType="MenuItem" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="Padding" Value="4 0"></Setter>
<Setter TopPadding="Padding" Value="4 0"></Setter>
</Style>但是当然,在TopPadding上没有“MenuItem”属性,所以这不会编译。
如何在原始样式中创建这个新属性,在模板中引用它-在两个触发器中,然后在我的自定义样式中重写它?
可能相关的答案:
Bind to resource keys on each item
最坏的情况是,我可以子类MenuItem,并创建一个只适用于该子类的模板(添加"TopPadding“属性)。我不喜欢这样做,因为这是一个复杂库的一部分;我希望有一个模板可以与任何MenuItem一起工作。我认为这意味着任何附加的属性都必须是可选的( MenuItem可能没有它)。我不确定模板将如何引用附加属性,也不确定如果缺少默认属性,如何设置默认属性。
重要的是:我不希望黑客使用Tag属性;我想要一种可扩展的方法,以某种方式添加适当的属性或资源。
更新
我刚刚找到了this answer;我没有意识到附加属性不必在原始类中定义--可以在不对MenuItem进行子类分类的情况下定义一个属性。
我不清楚是否可以设置默认值,以防这个附加属性丢失,但我现在正尝试这样做。
发布于 2019-03-17 11:39:48
不工作尝试,使用this answer的思想
在库中的c#类中定义附加属性:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace MaterialDesignThemes.Wpf
{
public static class ThemeAssist
{
// ...
#region TopPadding AttachedProperty
public static DependencyProperty TopPaddingProperty =
DependencyProperty.RegisterAttached("TopPadding",
typeof(Thickness),
typeof(ThemeAssist),
new PropertyMetadata(new Thickness(12, 0, 12, 0)));
public static void SetTopPadding(DependencyObject obj, Thickness value)
{
obj.SetValue(TopPaddingProperty, value);
}
public static Brush GetTopPadding(DependencyObject obj)
{
return (Brush)obj.GetValue(TopPaddingProperty);
}
#endregion
}
}试图在模板中使用附加属性:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf"
xmlns:converters="clr-namespace:MaterialDesignThemes.Wpf.Converters">
<!-- ... -->
<Style TargetType="{x:Type MenuItem}" x:Key="MaterialDesignMenuItem" BasedOn="{x:Null}">
<Setter Property="Padding" Value="24 0"/>
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="wpf:ThemeAssist.TopPadding" Value="16 0 16 0"/>
<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"/> -->
<Setter Property="Padding" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ThemeAssist.TopPadding)}"/>
</Trigger>
<Trigger Property="Role" Value="TopLevelItem">
<!--<Setter Property="Padding" Value="16 0"/>-->
<Setter Property="Padding" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(wpf:ThemeAssist.TopPadding)}"/>
</Trigger>
<!--#endregion-->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>用法(在不同的程序集中):
<StackPanel DockPanel.Dock="Top">
<StackPanel.Resources>
<Style TargetType="MenuItem" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="Padding" Value="24 0 24 0"/>
<!--<Setter Property="wpf:ThemeAssist.TopPadding" Value="12 0 12 0"/>-->
<Setter Property="Background" Value="Aqua"></Setter>
</Style>
</StackPanel.Resources>
<Menu x:Name="MainMenu" IsMainMenu="True" Visibility="Collapsed">
<MenuItem Header="_File">错误结果: TopLevelHeader/TopLevelItem MenuItem填充总是(0,0,0,0)。附加属性定义(12, ..)的默认值和样式设置器<Setter Property="wpf:ThemeAssist.TopPadding" Value="16 0 16 0"/>上的值都没有任何效果。
重要的是,最终样式的<Setter Property="Padding" Value="24 0 24 0"/>确实被触发器覆盖;触发器似乎没有找到附加属性,因此重置填充为0。
如果我在触发器的填充中恢复原始的"16 0"值,那么菜单项就会得到这个填充。
我还尝试将TopPadding添加到最后的样式中,但是没有找到在视觉设计器中没有抱怨的语法。(无论如何,我运行了这个程序,但仍然没有效果。)我尝试的语法:
<UserControl x:Class="GISWPF.Dialogs"
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
...
>
...
<Style TargetType="MenuItem" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="wpf:ThemeAssist.TopPadding" Value="12 0 12 0"/>
</Style>给出了设计时工具提示:
'' is not a valid value for the 'MaterialDesignThemes.Wpf.ThemeAssist.TopPadding' property on a Setter.我说的Value="12 0 12 0"很奇怪,但是错误消息显示了一个空白值''。无法将字符串应用于厚度转换器?
https://stackoverflow.com/questions/55205833
复制相似问题