非常抱歉问这么基础的问题,我是WPF新手,一直在找几乎符合我需求的博客...
我有一个绑定了属性并且可以很好更新屏幕的标签,现在我想要一个小动画,每当该值被更新时就会闪烁标签的背景颜色。理想情况下,我希望有一个纯XAML的解决方案。
我看过DataTriggers,但似乎它们需要满足相等条件,而EventTriggers似乎无法附加到与数据显示相关的任何事件上。
谢谢 奥斯卡
你是否应该使用事件触发器?在绑定中需要设置NotifyOnTargetUpdated=True
,但是这在我的代码中有效。
<DataTemplate>
<Border Name="templateBorder">
<TextBlock Text="{Binding Path=Name, NotifyOnTargetUpdated=True}" />
</Border>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard AutoReverse="True">
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To=".1" Duration="0:0:.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</DataTemplate.Triggers>
</DataTemplate>
public class TestConverter : IValueConverter
{
private string _originalValue = String.Empty;
private bool _previousValue = false;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
_originalValue = (string)value;
_previousValue = !_previousValue;
return _previousValue.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return _originalValue;
}
}
数据上下文初始化:
label1.DataContext = new Test() { Name = DateTime.Now.ToString() };
xaml:
<Window.Resources>
<local:TestConverter x:Key="TestConverter" />
</Window.Resources>
<Grid>
<Label
Height="28"
HorizontalAlignment="Left"
Margin="132,96,0,0"
Name="label1" VerticalAlignment="Top" Width="120">
<Label.Content>
<Binding Path="Name"/>
</Label.Content>
<Label.Tag>
<Binding Path="Name" Converter="{StaticResource TestConverter}"/>
</Label.Tag>
<Label.Background>
<SolidColorBrush x:Name="animatedBrush1" Color="Yellow" />
</Label.Background>
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<Trigger Property="Tag" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard AutoReverse="True">
<!--<DoubleAnimation
Storyboard.TargetProperty="FontSize" To="20"/>-->
<DoubleAnimation
Storyboard.TargetProperty="Opacity" To="0.0" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="Tag" Value="False">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard AutoReverse="True">
<DoubleAnimation
Storyboard.TargetProperty="FontSize" To="20"/>
<!--"<DoubleAnimation
Storyboard.TargetProperty="Opacity" To="0.0" AutoReverse="True"/>-->
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
<Label.Triggers>
<EventTrigger RoutedEvent="Label.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="animatedBrush1"
Storyboard.TargetProperty="Color"
To="Blue" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Label.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="animatedBrush1"
Storyboard.TargetProperty="Color"
To="Yellow" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Label.Triggers>
</Label>
</Grid>
我喜欢serge_gubenko的答案,但是我想提到另一种我有时使用的技术。Serge的答案更接近您的“纯XAML”理想,因为它只有一个转换器,但这个答案的代码更少,可能更易读。 这是它:
在“Name”属性中添加一个PropertyChangedCallback,并从那里开始storyboard:
DependencyProperty NameProperty = DependencyProperty.Register( ..., new UIElementMetadata
{
PropertyChangedCallback = (obj, e) =>
{
storyBoard.Begin();
}
});
如果你不想在窗口首次加载时出现闪光,你可以添加一个标志:
...
PropertyChangedCallback = (obj, e) =>
{
if(_initialized)
storyBoard.Begin();
}
...
protected override void OnInitialized(...)
{
_initialized = true;
}