2013-02-06 53 views
2

我有以下Style变量在XAML样式

<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

你是什么意思_“我没有一个”_ - 你的逻辑在哪里? – Blachshma

+0

这是MVVM应用程序中仅用于xaml的视图。 – acron

+0

好的,对于这个MVVM视图,你没有ViewModel? – Blachshma

回答

2

这是一个很好的问题,我也通过这种事情进行了斗争。可能有某种仅用于XAML的方法可行,但我有一种感觉,如果存在,它会感觉很糟糕。我有几个关于如何实现你想要的建议。

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

在一天结束时,听起来像你真正想要的是定义一些自定义的“变量”。这些建议可以做到这一点,尽管可能不像您最初设想的那样。

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

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

第二种方法的例子可以在MahApps.Metro库中找到,特别是TextboxHelper class(其中包含附属属性)和Controls.TextBox.xaml style file(包含那些附属属性)。例如,我们看到了对TextBox控件模板,这条线,它利用了水印附加属性:

<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"/> 

现在你可以想像,你可以设置水印值在基本风格的东西:

<Setter Property="Controls:TextboxHelper.Watermark" 
     Value="My helpful watermark for all!"/> 

,然后覆盖它继承的风格:

<Setter Property="Controls:TextboxHelper.Watermark" 
     Value="A more specific watermark!"/> 

不管采用哪种方法,我们可以定义任何“变量”我们希望,轻松地将它们放置在风格二传手,OVE使用继承的样式,TemplateBind在控制模板内,或Trigger关闭。

+0

这两种方法的唯一问题是需要引入外部名称空间。我希望避免这种情况(我有点纯粹主义者),但它可能是唯一的方法......谢谢你,无论哪种方式。 – acron

+0

很高兴帮助。关于命名空间问题,如果您只是希望能够使用这些方法而无需引用XAML命名空间前缀(即上面的“Controls”前缀),则可以使用一种技术来避免必须使用前缀。请参阅[** this **](http://stackoverflow.com/a/14611738/718325)。 –

+0

这种方法看起来不错,但纯粹是审美。实质上,在理想的世界中,我不希望我的View必须根本引用'ViewHelper'程序集。 – acron