我想将按钮的背景颜色在其正常,moused-over和press状态下更改为各种绿色阴影。我被迫在我的按钮中添加以下怪异的Button.Template
,以便我可以修改RenderMouseOver
和RenderPressed
属性以使用Binding
代替TemplateBinding
,这样我的触发器(在Button.Style
中)实际上生效而不是由于TemplateBinding
的编译时性质而被忽略。无论如何,对于Aero主题,是否更干净地覆盖这两个属性,而不是完整地重复整个模板绑定? 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>
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>
重要提示:仅对Aero主题需要控制模板。对于其他主题,只需单独使用Button.Style即可完成任务。
答案 0 :(得分:1)
我能想到的最好的方法是添加一个附加行为,一旦Button加载,就会用反射来禁用它。我不知道你是否喜欢这个比重新模板更好,但你不必包括PresentationFramework.Aero及其可重复使用的
<Button behaviors:DisableButtonChromeBehavior.DisableButtonChrome="True"
...>
<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>
DisableButtonChromeBehavior
public static class DisableButtonChromeBehavior
{
public static readonly DependencyProperty DisableButtonChromeProperty =
DependencyProperty.RegisterAttached
(
"DisableButtonChrome",
typeof(bool),
typeof(DisableButtonChromeBehavior),
new UIPropertyMetadata(false, OnDisableButtonChromePropertyChanged)
);
public static bool GetDisableButtonChrome(DependencyObject obj)
{
return (bool)obj.GetValue(DisableButtonChromeProperty);
}
public static void SetDisableButtonChrome(DependencyObject obj, bool value)
{
obj.SetValue(DisableButtonChromeProperty, value);
}
private static void OnDisableButtonChromePropertyChanged(DependencyObject dpo,
DependencyPropertyChangedEventArgs e)
{
Button button = dpo as Button;
if (button != null)
{
if ((bool)e.NewValue == true)
{
button.Loaded += OnButtonLoaded;
}
else
{
button.Loaded -= OnButtonLoaded;
}
}
}
private static void OnButtonLoaded(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
Action action = () =>
{
object buttonChrome = VisualTreeHelper.GetChild(button, 0);
Type type = buttonChrome.GetType();
PropertyInfo propertyInfo = type.GetProperty("RenderMouseOver");
if (propertyInfo != null)
{
propertyInfo.SetValue(buttonChrome, false, null);
propertyInfo = type.GetProperty("RenderPressed");
propertyInfo.SetValue(buttonChrome, false, null);
propertyInfo = type.GetProperty("RenderDefaulted");
propertyInfo.SetValue(buttonChrome, false, null);
}
};
button.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
}
}
<强>更新强>
还有更短的不可重用方式,只需在后面的代码中执行此操作。
private void Button_Loaded(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
object buttonChrome = VisualTreeHelper.GetChild(button, 0);
PropertyInfo renderMouseOverInfo = buttonChrome.GetType().GetProperty("RenderMouseOver");
if (renderMouseOverInfo != null)
{
renderMouseOverInfo.SetValue(buttonChrome, false, null);
}
}
或(如果你不介意包括Aero)
<Button ...>
<Button.Resources>
<Style TargetType="Microsoft_Windows_Themes:ButtonChrome">
<EventSetter Event="Loaded" Handler="ButtonChrome_Loaded"/>
</Style>
</Button.Resources>
void ButtonChrome_Loaded(object sender, RoutedEventArgs e)
{
ButtonChrome buttonChrome = sender as ButtonChrome;
if (buttonChrome != null)
{
buttonChrome.RenderMouseOver = false;
buttonChrome.RenderPressed = false;
}
}
除此之外,我认为除了您自己指出的解决方案(重新模板化)之外,您没有任何其他方法。
答案 1 :(得分:0)
如果要使用样式切换背景,则无法像在此处那样显式设置Background属性:
<Button Background="LightGreen">
这将覆盖您设置的任何样式。试试这个:
<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>
这应该使你可以摆脱按钮模板,除非你想在其中做更多。
如果您想摆脱Aero废话,请更换模板:
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Border SnapsToDevicePixels="true" x:Name="Chrome" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Button.Template>
这里的缺点是如果你不想要Aero,你就不会得到任何Aero,你必须从头开始使用你的模板。