Style Trigger 在直接 SetValue 后停止工作
Style Trigger stops to work after direct SetValue
设置 BackgroundProperty 直接破坏 IsMouseOver 样式触发器。如何有可能直接设置 BackgroundProperty 并在之后保留触发器工作?
XAML:
<Window x:Class="WpfTriggers.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="OriginalBackground" Color="Blue"/>
<SolidColorBrush x:Key="TemplateBackground" Color="Red"/>
<Style TargetType="Label" >
<Style.Setters>
<Setter Property="Background" Value="{StaticResource OriginalBackground}"/>
<Setter Property="Foreground" Value="White"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource TemplateBackground}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Label Focusable="True" x:Name="label">Hi!</Label>
<Button Click="Button_Click">Over</Button>
</StackPanel>
</Grid>
</Window>
后面的代码:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfTriggers
{
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
void Button_Click(object sender, RoutedEventArgs e) => label.SetValue(Control.BackgroundProperty, Brushes.Green);
}
}
您不能直接设置样式中使用的属性(结果是您的示例)。
您必须改用 Binding。
对您的代码添加一些内容:
public MainWindow()
{
DataContext = this;
InitializeComponent();
SetValue(BgBrushProperty, Resources["OriginalBackground"]);
}
void Button_Click(object sender, RoutedEventArgs e) => SetValue(BgBrushProperty, Brushes.Green);
// Using a DependencyProperty as the backing store for BgBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BgBrushProperty =
DependencyProperty.Register("BgBrush", typeof(Brush), typeof(MainWindow), new PropertyMetadata());
并在 XAML...
<Style.Setters>
<Setter Property="Background" Value="{Binding BgBrush}"/>
<Setter Property="Foreground" Value="White"/>
</Style.Setters>
你也可以这样使用 DynamicResource:
<Style.Setters>
<Setter Property="Background" Value="{DynamicResource OriginalBackground}"/>
<Setter Property="Foreground" Value="White"/>
</Style.Setters>
使用此代码:
public MainWindow() => InitializeComponent();
void Button_Click(object sender, RoutedEventArgs e) => Resources["OriginalBackground"] = Brushes.Green;
我们通过复制样式解决了问题,暂时用具有背景的克隆替换它 setter 并返回样式。这已作为使用完全自定义动态绑定模仿数据触发器的行为投入生产。
public static class extensions
{
/// <summary>
/// Shallow clone of style.
/// </summary>
/// <param name="original">Style to clone.</param>
/// <returns>Cloned style.</returns>
public static Style ShallowClone(this Style original)
{
var cloned = new Style(original.TargetType, original.BasedOn);
foreach (var s in original.Setters) cloned.Setters.Add(s);
foreach (var t in original.Triggers) cloned.Triggers.Add(t);
cloned.Resources = original.Resources;
return cloned;
}
}
Style old;
private void Button_MouseEnter_5(object sender, System.Windows.Input.MouseEventArgs e)
{
old = labelWithMofidiableStyle.Style;
Style style = old.ShallowClone();
style.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = this.FindResource("DynamicBackground") });
labelWithMofidiableStyle.Style = style;
}
private void Button_MouseLeave_5(object sender, System.Windows.Input.MouseEventArgs e)
{
labelWithMofidiableStyle.Style = old;
}
设置 BackgroundProperty 直接破坏 IsMouseOver 样式触发器。如何有可能直接设置 BackgroundProperty 并在之后保留触发器工作?
XAML:
<Window x:Class="WpfTriggers.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<SolidColorBrush x:Key="OriginalBackground" Color="Blue"/>
<SolidColorBrush x:Key="TemplateBackground" Color="Red"/>
<Style TargetType="Label" >
<Style.Setters>
<Setter Property="Background" Value="{StaticResource OriginalBackground}"/>
<Setter Property="Foreground" Value="White"/>
</Style.Setters>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource TemplateBackground}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<StackPanel>
<Label Focusable="True" x:Name="label">Hi!</Label>
<Button Click="Button_Click">Over</Button>
</StackPanel>
</Grid>
</Window>
后面的代码:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace WpfTriggers
{
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
void Button_Click(object sender, RoutedEventArgs e) => label.SetValue(Control.BackgroundProperty, Brushes.Green);
}
}
您不能直接设置样式中使用的属性(结果是您的示例)。 您必须改用 Binding。 对您的代码添加一些内容:
public MainWindow()
{
DataContext = this;
InitializeComponent();
SetValue(BgBrushProperty, Resources["OriginalBackground"]);
}
void Button_Click(object sender, RoutedEventArgs e) => SetValue(BgBrushProperty, Brushes.Green);
// Using a DependencyProperty as the backing store for BgBrush. This enables animation, styling, binding, etc...
public static readonly DependencyProperty BgBrushProperty =
DependencyProperty.Register("BgBrush", typeof(Brush), typeof(MainWindow), new PropertyMetadata());
并在 XAML...
<Style.Setters>
<Setter Property="Background" Value="{Binding BgBrush}"/>
<Setter Property="Foreground" Value="White"/>
</Style.Setters>
你也可以这样使用 DynamicResource:
<Style.Setters>
<Setter Property="Background" Value="{DynamicResource OriginalBackground}"/>
<Setter Property="Foreground" Value="White"/>
</Style.Setters>
使用此代码:
public MainWindow() => InitializeComponent();
void Button_Click(object sender, RoutedEventArgs e) => Resources["OriginalBackground"] = Brushes.Green;
我们通过复制样式解决了问题,暂时用具有背景的克隆替换它 setter 并返回样式。这已作为使用完全自定义动态绑定模仿数据触发器的行为投入生产。
public static class extensions
{
/// <summary>
/// Shallow clone of style.
/// </summary>
/// <param name="original">Style to clone.</param>
/// <returns>Cloned style.</returns>
public static Style ShallowClone(this Style original)
{
var cloned = new Style(original.TargetType, original.BasedOn);
foreach (var s in original.Setters) cloned.Setters.Add(s);
foreach (var t in original.Triggers) cloned.Triggers.Add(t);
cloned.Resources = original.Resources;
return cloned;
}
}
Style old;
private void Button_MouseEnter_5(object sender, System.Windows.Input.MouseEventArgs e)
{
old = labelWithMofidiableStyle.Style;
Style style = old.ShallowClone();
style.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = this.FindResource("DynamicBackground") });
labelWithMofidiableStyle.Style = style;
}
private void Button_MouseLeave_5(object sender, System.Windows.Input.MouseEventArgs e)
{
labelWithMofidiableStyle.Style = old;
}