4

我有以下内容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>

有没有办法做到这一点?我已经查看了静态资源,但这些资源不能被覆盖。另外,我不能使用任何需要代码隐藏的东西,因为我没有!

4

1 回答 1

2

这是一个很好的问题,我也经历过这种事情。可能有某种仅适用于 XAML 的方法可以工作,但我有一种感觉,如果有的话,它会感觉很笨拙。关于如何实现你想要的,我有一些建议。

首先,快速观察。您说您“没有代码隐藏”并且您的视图是“仅 XAML”。好吧,我从来没有见过至少没有任何代码隐藏文件的 UserControl 视图,所以我假设您的意思是您只是不想在其中放置任何代码(除了强制性的InitializeComponent())。话虽如此,我将概述的方法不需要代码隐藏文件中的代码。

归根结底,听起来您真正想要的是定义一些自定义“变量”。这些建议就是这样做的,尽管可能不是您最初设想的那样。

解决您的问题的第一种方法是将您对样式感兴趣的控件子类化并向其添加任何自定义依赖项属性。例如,您可以将 子类Button化为类似ButtonWithMyVariables. 这些自定义依赖项属性之一将称为“HoverColor”,类型为Color,或者更恰当地说,称为“HoverBrush”类型Brush(如果您只想将其直接应用于背景或前景属性)。然后,您的基本 Style 可以将 HoverColor 设置为它想要的任何内容,并且您继承的 Style 可以覆盖它,或者您可以直接在 XAML 中的元素上覆盖它。我没有提供这种方法的代码示例(现在,除非要求),因为这是一种更常用的方法,我猜你已经熟悉了。

第二种方法是定义一个自定义附加属性。我还没有看到这种方法被广泛用于严格处理样式问题,可能是因为在这种情况下,为了让附加的“行为”充分发挥其作用,作者使用样式文件来做出反应(绑定)并应用基于视觉的更改在附加属性上,而不是附加属性中的代码更改回调在风格上做一些事情(但我想它仍然可以这样做)。但是,这种方法对许多人来说感觉“重量更轻”,因为您不需要对任何现有控件进行子类化。

第二种方法的示例可以在 MahApps.Metro 库中找到,特别是TextboxHelper 类(包含附加属性)和Controls.TextBox.xaml 样式文件(绑定到这些附加属性)。例如,我们在 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!"/>

使用任何一种方法,我们都可以定义我们想要的任何“变量”,并在样式设置器中轻松设置它们,在继承的样式中覆盖它们,TemplateBind在控件模板中或Trigger在它们之外。

于 2013-02-06T14:51:56.647 回答