我有以下Style
:
<Style x:Key="ButtonBase" TargetType="Button">
<Setter Property="Background" Value="#FF007BFF"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value=">
<Setter Property="Background" Value="Yellow" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsPressed" Value="False">
<Setter Property="Background" Value="#FF007BFF" />
<Setter Property="Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Setter.Value>
</Setter>
</Style>
和继承的Style
:
<Style x:Key="ElementButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}">
<Setter Property="Margin" Value="10"/>
<Setter Property="Height" Value="200"/>
</Style>
我想做的是能够在基本样式中设置任意变量:
<Setter Variable="HoverColor" Value="Pink"/>
然后我就可以使用我的触发器了:
<Trigger Property="IsPressed" Value=">
<Setter Property="Background" Value="{TemplateBinding HoverColor}" />
<Setter Property="Foreground" Value="Black" />
</Trigger>
最后,我可以用我继承的风格覆盖它:
<Style x:Key="ElementButton" TargetType="Button" BasedOn="{StaticResource ButtonBase}">
<Setter Property="Margin" Value="10"/>
<Setter Property="Height" Value="200"/>
<Setter Variable="HoverColor" Value="Red"/>
</Style>
有没有办法实现这个目标?我已经查看了静态资源,但这些资源无法覆盖。另外,我不能使用任何需要代码隐藏的东西,因为我没有代码!
答案 0 :(得分:2)
这是一个很好的问题,我也经历过这样的事情。可能有某种XAML方法可以工作,但我有一种感觉,如果有的话,它会觉得非常笨拙。我有几个关于如何实现你想要的建议。
首先,快速观察。你说你“没有代码隐藏”,你的观点是“仅限XAML”。好吧,我从未见过至少没有任何代码隐藏文件的UserControl视图,所以我假设你的意思是你只是不想要在那里放置任何代码(强制性InitializeComponent()
除外)。话虽如此,我将概述的方法不需要代码隐藏文件中的代码。
在一天结束时,听起来你真正想要的是定义一些自定义的“变量”。这些建议就是这样做的,尽管可能不是你最初想象的那样。
解决问题的第一种方法是对您感兴趣的控件进行样式化,并为其添加任何自定义依赖项属性。例如,您可以将Button
子类化为ButtonWithMyVariables
之类的内容。其中一个自定义依赖项属性称为“HoverColor”,类型为Color
,或者更合适的是“HoverBrush”类型为Brush
(如果您只想将其直接应用于后台)或前景属性)。然后你的基本样式可以将HoverColor设置为它想要的任何东西,你继承的样式可以覆盖它,或者你可以直接在XAML中的元素上覆盖它。我没有为这种方法提供代码示例(现在,除非请求),因为这是一种更常用的方法,我猜你已经熟悉了。
第二种方法将定义自定义附加属性。我没有看到这种方法用于严格处理样式问题,也许是因为在这种情况下附加的“行为”完全发挥作用,作者使用Style文件作出反应(绑定)并应用基于视觉的变化在附加属性上,而不是附加属性中的代码更改回调做一些风格(但我想它仍然可以这样做)。但是,这种方法对许多人来说感觉“重量轻”,因为您不需要对任何现有控件进行子类化。
第二种方法的一个例子可以在MahApps.Metro库中找到,特别是TextboxHelper class(包含附加属性)和Controls.TextBox.xaml style file(绑定到那些附加属性)。例如,我们在控件模板中看到TextBox,这一行使用了Watermark附加属性:
<TextBlock x:Name="Message"
Text="{TemplateBinding Controls:TextboxHelper.Watermark}" Visibility="Collapsed"
Foreground="{TemplateBinding Foreground}" IsHitTestVisible="False" Opacity="0.6" HorizontalAlignment="Left" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="6,0,0,0"/>
现在您可以想象您可以将基本样式中的Watermark值设置为:
<Setter Property="Controls:TextboxHelper.Watermark"
Value="My helpful watermark for all!"/>
然后以继承的方式覆盖它:
<Setter Property="Controls:TextboxHelper.Watermark"
Value="A more specific watermark!"/>
使用任何一种方法,我们都可以定义我们想要的任何“变量”,并在Style setter中轻松设置它们,在继承的样式中覆盖它们,在控件模板中将它们TemplateBind
覆盖,或者Trigger
off它们。