如何在鼠标悬停时更改按钮样式并使用多重绑定?
How to change button style on mouseover and use multibinding?
我在 Button.Style 中使用 MultiBinding 来根据布尔值 (IsScenSelBtnEnabled) 设置样式值。
<Button.Style>
<MultiBinding Converter="{StaticResource StyleConverter}">
<Binding Path="IsScenSelBtnEnabled" />
<Binding Source="{StaticResource BlueButton2}" />
<Binding Source="{StaticResource DisabledButton2}" />
</MultiBinding>
</Button.Style>
当按钮上发生鼠标悬停事件时,我还需要将 Style 值更改为名为 BlueButton3 的样式。 过去几个小时我一直在谷歌上搜索并尝试自己弄清楚,但我没有运气。我看到可以使用 Style.Triggers 以便在触发发生时设置样式 属性(例如 IsMouseOver),但我无法让它与我当前的 MultiBinding 一起使用。
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers>
如有任何帮助,我们将不胜感激。谢谢!
这个问题我觉得最好反过来回答。您对 IsMouseOver 的样式触发器有正确的想法。但是,由于 WPF 对 DependencyProperty 的评估顺序,它不起作用:
https://msdn.microsoft.com/en-us/library/vstudio/ms743230(v=vs.100).aspx#listing
如您所见,首先评估样式触发器,然后评估模板触发器。因此,您的样式触发器永远不会在视觉上出现,因为按钮的默认模板已经具有 IsMouseOver 的触发器。
为了让按钮背景变成绿色,需要覆盖ControlTemplate:
<Button.Template>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsDefaulted" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="LightGreen"/>
<Setter Property="BorderBrush" TargetName="border" Value="LightGreen"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
请注意 "IsMouseOver" 触发器将背景设置为浅绿色。
关于您问题的第一部分...我个人认为有一种更简单的方法可以解决您的问题,而无需使用 convert 和 multibinding。由于您已经必须覆盖按钮的控件模板,因此您不妨将按钮的默认属性设置为任何您想要的,然后添加到新控件模板的 "IsEnabled" 触发器部分以设置您想要的属性该按钮被禁用。您的最终 xaml 将如下所示:
<Button Background="Blue" IsEnabled="{Binding IsScenSelBtnEnabled}">A Button!
<Button.Template>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsDefaulted" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="LightGreen"/>
<Setter Property="BorderBrush" TargetName="border" Value="LightGreen"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
<!--Insert any other setters for your disabled style here!-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
我在 Button.Style 中使用 MultiBinding 来根据布尔值 (IsScenSelBtnEnabled) 设置样式值。
<Button.Style>
<MultiBinding Converter="{StaticResource StyleConverter}">
<Binding Path="IsScenSelBtnEnabled" />
<Binding Source="{StaticResource BlueButton2}" />
<Binding Source="{StaticResource DisabledButton2}" />
</MultiBinding>
</Button.Style>
当按钮上发生鼠标悬停事件时,我还需要将 Style 值更改为名为 BlueButton3 的样式。 过去几个小时我一直在谷歌上搜索并尝试自己弄清楚,但我没有运气。我看到可以使用 Style.Triggers 以便在触发发生时设置样式 属性(例如 IsMouseOver),但我无法让它与我当前的 MultiBinding 一起使用。
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers>
如有任何帮助,我们将不胜感激。谢谢!
这个问题我觉得最好反过来回答。您对 IsMouseOver 的样式触发器有正确的想法。但是,由于 WPF 对 DependencyProperty 的评估顺序,它不起作用:
https://msdn.microsoft.com/en-us/library/vstudio/ms743230(v=vs.100).aspx#listing
如您所见,首先评估样式触发器,然后评估模板触发器。因此,您的样式触发器永远不会在视觉上出现,因为按钮的默认模板已经具有 IsMouseOver 的触发器。
为了让按钮背景变成绿色,需要覆盖ControlTemplate:
<Button.Template>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsDefaulted" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="LightGreen"/>
<Setter Property="BorderBrush" TargetName="border" Value="LightGreen"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
请注意 "IsMouseOver" 触发器将背景设置为浅绿色。
关于您问题的第一部分...我个人认为有一种更简单的方法可以解决您的问题,而无需使用 convert 和 multibinding。由于您已经必须覆盖按钮的控件模板,因此您不妨将按钮的默认属性设置为任何您想要的,然后添加到新控件模板的 "IsEnabled" 触发器部分以设置您想要的属性该按钮被禁用。您的最终 xaml 将如下所示:
<Button Background="Blue" IsEnabled="{Binding IsScenSelBtnEnabled}">A Button!
<Button.Template>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsDefaulted" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="LightGreen"/>
<Setter Property="BorderBrush" TargetName="border" Value="LightGreen"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
<!--Insert any other setters for your disabled style here!-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>