2010-12-12 53 views
9

因此,愿望很简单,将鼠标光标悬停在按钮上的按钮背景变为LightGreen,将按钮背景变为绿色,按下时变为深绿色。以下XAML是我的第一次尝试:在Aero上重写WPF中的按钮背景

<Window x:Class="ButtonMouseOver.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
    <Button Background="LightGreen"> 
     Hello 
     <Button.Style> 
     <Style TargetType="Button"> 
      <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="true"> 
       <Setter Property = "Background" Value="Green"/> 
      </Trigger> 
      <Trigger Property="IsPressed" Value="true"> 
       <Setter Property = "Foreground" Value="DarkGreen"/> 
      </Trigger> 
      </Style.Triggers> 
     </Style> 
     </Button.Style> 
    </Button> 
    </Grid> 
</Window> 

但是,唉,这是行不通的。我们只是实现目标的三分之一。是的,按钮变成浅绿色,但只要您将鼠标悬停在按钮上或按下按钮,即可获得相应按钮状态的标准Aero Chrome。不想放弃,我尝试以下放荡:

... 
    <Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" 
      Background="LightGreen"> 
     Hello 
     <Button.Template> 
     <ControlTemplate TargetType="{x:Type Button}"> 
      <Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" 
      x:Name="Chrome" Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" 
      RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" 
      > 
      <ContentPresenter Margin="{TemplateBinding Padding}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              RecognizesAccessKey="True" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
      </Microsoft_Windows_Themes:ButtonChrome> 
     </ControlTemplate> 
     </Button.Template> 
     <Button.Style> 
     <Style TargetType="Button"> 
      <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="true"> 
       <Setter Property = "Background" Value="Green"/> 
      </Trigger> 
      <Trigger Property="IsPressed" Value="true"> 
       <Setter Property = "Foreground" Value="DarkGreen"/> 
      </Trigger> 
      </Style.Triggers> 
     </Style> 
     </Button.Style> 
    </Button> 
... 

现在,我们已经有了在那里扔整个受诅咒的控制模板从Aero.NormalColor.xaml解除。唉,这没什么变化。然后我从Microsoft_Windows_Themes:ButtonChrome元素中删除两个属性(RenderPressedRenderMouseOver)。但是,没有改变。然后我删除按钮的Background属性的设置,只留下空间声明中的PresentationFramework.Aero装配:

... 
<Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"> 
    Hello 
... 

最后,我们有进步。我们已经从1/3的要求转变为2/3的方式,IsMouseOver和IsPressed可以工作,但是在按钮的正常状态(没有被模糊或者按下)期间没有淡绿色的背景,因为我已经移除了从该按钮的背景属性,以获得其他两个状态应用和可见。现在,经过这疯狂的XAML未能得到我们的正常按钮状态的浅绿的背景下,我修改样式扔背景颜色在那里还有:

<Button xmlns... 
    <ControlTemplate... 
    ... 
    </ControlTemplate> 
    <Button.Style> 
     <Style TargetType="Button"> 
     <!-- ##### Normal state button background added ##### --> 
     <Setter Property="Background" Value="LightGreen" /> 
     <!-- ################################################ --> 
     <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="true"> 
      <Setter Property = "Background" Value="Green"/> 
      </Trigger> 
      <Trigger Property="IsPressed" Value="true"> 
      <Setter Property = "Background" Value="DarkGreen"/> 
      </Trigger> 
     </Style.Triggers> 
     </Style> 
    </Button.Style> 
    </Button> 

最后,按预期工作。

我是疯了么,还是这些(以及更多)你必须通过一个Aero主题来改变一个按钮的背景颜色在其各种状态(正常,悬停,按下)?也许,如果我不需要在那里包括整个dang ButtonTemplate,生活就不会那么糟糕,只是为了从中删除两个属性(RenderMouseOverRenderPressed)。

谢谢你的帮助 - 我在智慧的结尾。

更新:但是等待还有更多。

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ... 
    RenderMouseOver="{TemplateBinding IsMouseOver}" 
    RenderPressed="{TemplateBinding IsPressed}" ... 

到:

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ... 
    RenderMouseOver="{Binding IsMouseOver}" 
    RenderPressed="{Binding IsPressed}" ... 

...,还解决了问题(忽略按钮的样式触发的),而不是删除RenderMouseOver和RenderPressed从控制模板属性,只需对其进行更改。我认为问题的根源在于模板绑定在编译时应用(出于性能原因),而常规绑定则在运行时应用。因此,如果属性使用模板绑定(即改为使用来自原始模板的IsMouseOver和IsPressed),则不使用来自各个按钮的样式触发器的绑定。

说了以上的,这里是Aero的改变按钮的背景,同时保持其原有的控制模板中的典型的例子:

<Window x:Class="ButtonMouseOver.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
    <Button> 
     Hello 
     <Button.Template> 
     <ControlTemplate TargetType="{x:Type Button}"> 
      <Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" 
      x:Name="Chrome" Background="{TemplateBinding Background}" 
      BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" 
      RenderMouseOver="{Binding IsMouseOver}" RenderPressed="{Binding IsPressed}" 
      > 
      <ContentPresenter Margin="{TemplateBinding Padding}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              RecognizesAccessKey="True" 
              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
      </Microsoft_Windows_Themes:ButtonChrome> 
     </ControlTemplate> 
     </Button.Template> 
     <Button.Style> 
     <Style TargetType="Button"> 
      <Setter Property="Background" Value="LightGreen"/> 
      <Style.Triggers> 
      <Trigger Property="IsMouseOver" Value="true"> 
       <Setter Property = "Background" Value="Green"/> 
      </Trigger> 
      <Trigger Property="IsPressed" Value="true"> 
       <Setter Property = "Foreground" Value="DarkGreen"/> 
      </Trigger> 
      </Style.Triggers> 
     </Style> 
     </Button.Style> 
    </Button> 
    </Grid> 
</Window> 

当然,这是假设只有一个按钮,这样风格的,否则可以将模板和样式移出到某个资源部分。此外,没有触发按钮的默认状态,但它很容易添加到上面的示例中(不要忘记更改控件模板中的RenderDefaulted属性以使用Binding而不是TemplateBinding)。

如果任何人有关于如何覆盖用结合只在需要改变控制模板中的两个属性的TemplateBinding,而不从航空XAML批发重复整个镀铬的定义,我所有的耳朵的任何建议。

回答

2

Button的默认模板使用ButtonChrome,它执行自己的绘图。如果你想完全摆脱默认外观,你需要定义你自己的模板,而不需要ButtonChrome。我知道这听起来很乏味,但你只需要做一次:你可以把你的自定义样式放在资源字典中,只需要用StaticResource来引用它。请注意,您还可以使用{x:Type Button}作为样式的关键点(x:Key属性)将应用样式应用于应用中的所有按钮

+0

问题是我只想更改按钮的背景。 Aero chrome使用按钮正常状态的背景按钮属性正确处理此问题。但是,这种处理是错误的,因为背景会在鼠标悬停和按钮被按下时发生变化。在这两种状态下,改变按钮的背景似乎并不容易。这违背了Button中的背景属性(也许还有其他视觉效果)的全部目的。 – 2010-12-13 01:37:55

+0

Background属性对所有控件都是通用的,所以无论如何它都会在那里,但没有任何保证模板会考虑到它。我可以用Aero主题重现您的问题,以及与Luna主题相似的问题。看来ButtonChrome并没有考虑到某些州的背景......无论如何,我不认为标准按钮铬的设计是为了定制它的颜色。如果你想这样做,只是不要使用铬...无论如何创建自己的按钮模板是非常容易的。 – 2010-12-13 09:30:34

+0

从MSDN(Control.Background属性):Background属性仅适用于控件的静止状态。控件的默认样式在控件状态更改时指定其外观。例如,如果在Button上设置Background属性,则该按钮只有在未按下或禁用时才具有该值。如果要创建具有更高级自定义背景的控件,则必须定义控件的样式。 – 2010-12-13 09:32:52