在Aero上覆盖WPF中的按钮背景

Mic*_*eyn 9 c# wpf wpf-controls wpf-4.0 c#-4.0

因此,希望很简单,将按钮的背景更改为LightGreen,当鼠标光标悬停在其上时为绿色,按下时将DarkGreen更改为DarkGreen.以下XAML是我的第一次尝试:

<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>
Run Code Online (Sandbox Code Playgroud)

但是,唉,这不起作用.我们只是实现目标的1/3.是的,按钮变为浅绿色,但只要将鼠标悬停在按钮上或按下它,您就可以获得相应按钮状态的标准Aero镀铬.不想放弃,我尝试以下放荡:

...
    <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>
...
Run Code Online (Sandbox Code Playgroud)

现在我们已经从Aero.NormalColor.xaml中获得了整个friggin'控制模板.唉,这没什么改变.然后我去从元素中删除两个属性(RenderPressedRenderMouseOver)Microsoft_Windows_Themes:ButtonChrome.不过,没有变化.然后我删除Button Background属性的设置,只留下PresentationFramework.Aero程序集的名称空间声明:

...
<Button xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
  Hello
...
Run Code Online (Sandbox Code Playgroud)

最后,我们取得了进展.我们已经从1/3的要求变为2/3,IsMouseOver和IsPressed工作,但在按钮的正常状态(没有被碾过或按下)时没有浅绿色背景,因为我已经删除了按钮的Background属性,以使其他两个状态应用并可见.现在,在这个疯狂的XAML无法获得正常按钮状态的LightGreen背景后,我修改了样式以在其中抛出背景颜色:

  <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>
Run Code Online (Sandbox Code Playgroud)

最后,它按预期工作.

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

谢谢你的帮助 - 我结束了.

更新:但等待还有更多.而不是从控件模板中删除RenderMouseOver和RenderPressed属性,只需从以下位置更改它们:

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ...
  RenderMouseOver="{TemplateBinding IsMouseOver}"  
  RenderPressed="{TemplateBinding IsPressed}" ...
Run Code Online (Sandbox Code Playgroud)

至:

<Microsoft_Windows_Themes:ButtonChrome SnapsToDevicePixels="true" ...
  RenderMouseOver="{Binding IsMouseOver}"  
  RenderPressed="{Binding IsPressed}" ...
Run Code Online (Sandbox Code Playgroud)

...,还解决了问题(忽略按钮的样式触发器).我认为问题的根源是模板绑定在编译时应用(出于性能原因),而常规绑定在运行时应用.因此,如果属性使用模板绑定(即,使用原始模板中的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>
Run Code Online (Sandbox Code Playgroud)

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

如果有人对如何使用Binding 覆盖 TemplateBinding只有控件模板中需要更改的两个属性的任何建议,而不重复aero xaml批发的整个chrome定义,我很满意.

Tho*_*que 2

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