【问题标题】:Variables in XAML StyleXAML 样式的变量
【发布时间】:2013-02-07 00:25:11
【问题描述】:

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

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

【问题讨论】:

  • 你说的“我没有”是什么意思 - 你的逻辑在哪里?
  • 这是 MVVM 应用程序中的仅 xaml 视图。
  • 好的,对于这个 MVVM 视图,您没有 ViewModel 吗?
  • 我有一个 ViewModel,但 XAML 来自外部源,在运行时加载。它无法访问 ViewModel 在编译时公开的属性。

标签: c# wpf xaml


【解决方案1】:

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

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

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

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

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

可以在 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!"/>

无论采用哪种方法,我们都可以定义我们想要的任何“变量”,并在样式设置器中轻松设置它们,在继承的样式中覆盖它们,在控件模板中将它们TemplateBindTrigger 关闭它们。

【讨论】:

  • 这两种方法的唯一问题是它需要引入一个外部命名空间。我希望避免这种情况(我有点纯粹主义者),但这可能是唯一的方法......谢谢,无论哪种方式都很好。
  • 很高兴它有帮助。关于命名空间问题,如果您只是希望能够使用这些方法而不必引用 XAML 命名空间前缀(即上面的“控件”前缀),那么您可以使用一种技术来避免必须使用前缀.见this
  • 这种方法看起来不错,但纯粹是审美。从本质上讲,在理想的世界中,我根本不希望我的 View 必须引用一个“ViewHelper”程序集。
猜你喜欢
  • 2014-07-27
  • 2021-01-24
  • 1970-01-01
  • 2015-10-23
  • 2016-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多