基于 属性 的 WPF 动画开始时更改触发器
WPF animation based on property change triggers at start
当绑定到文本框文本 属性 的值发生变化时,我正在尝试为边框颜色设置动画:
<Border x:Name="border" BorderThickness="3" BorderBrush="Blue" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Background="White" TextAlignment="Center" FontSize="24"
Text="{Binding Value, NotifyOnTargetUpdated=True}">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Yellow"
Storyboard.TargetName="border"
AutoReverse="True"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
FillBehavior="Stop"
Duration="0:0:0.5"
RepeatBehavior="5x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Border>
问题是即使在应用程序启动时动画也会被触发并且值尚未设置一次。
有没有办法避免这种情况?
这是我建议的解决方法的工作演示。这使用 AgentOctal.WpfLib Nuget 包(免责声明:我是这个包的作者)用于 ViewModel
基础 class 和 ICommand
实现,但您应该能够轻松地替换您使用的任何系统。
如果我为您找到更好的选择,我会将其添加为附加答案。
MainWindow.xaml(注意:TextBlock
上的 EventTrigger
已更改为 Border
上的 DataTrigger
:
<Window
x:Class="BindingHelp.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:local="clr-namespace:BindingHelp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
mc:Ignorable="d">
<Window.DataContext>
<local:MainWindowVm />
</Window.DataContext>
<StackPanel Orientation="Vertical">
<Border
x:Name="border"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Blue"
BorderThickness="3">
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShouldAnimate}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
FillBehavior="Stop"
RepeatBehavior="5x"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="Yellow"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock
MinWidth="200"
Background="White"
FontSize="24"
Text="{Binding Value, NotifyOnTargetUpdated=True}"
TextAlignment="Center" />
</Border>
<Button Command="{Binding Path=SetValueCommand}" Content="Update Value" />
</StackPanel>
</Window>
MainWindowVm.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using AgentOctal.WpfLib;
using AgentOctal.WpfLib.Commands;
namespace BindingHelp
{
class MainWindowVm : ViewModel
{
private string _value;
public string Value
{
get { return _value; }
set
{
if (SetValue(ref _value, value))
{
ShouldAnimate = true;
}
}
}
private bool _shouldAnimate = false;
public bool ShouldAnimate
{
get { return _shouldAnimate; }
set { SetValue(ref _shouldAnimate, value); }
}
private ICommand _setValueCommand;
public ICommand SetValueCommand
{
get
{
return _setValueCommand ?? (_setValueCommand = new SimpleCommand((obj) =>
{
Value = "This is a test!";
}));
}
}
}
}
当绑定到文本框文本 属性 的值发生变化时,我正在尝试为边框颜色设置动画:
<Border x:Name="border" BorderThickness="3" BorderBrush="Blue" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Background="White" TextAlignment="Center" FontSize="24"
Text="{Binding Value, NotifyOnTargetUpdated=True}">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Yellow"
Storyboard.TargetName="border"
AutoReverse="True"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
FillBehavior="Stop"
Duration="0:0:0.5"
RepeatBehavior="5x" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</Border>
问题是即使在应用程序启动时动画也会被触发并且值尚未设置一次。 有没有办法避免这种情况?
这是我建议的解决方法的工作演示。这使用 AgentOctal.WpfLib Nuget 包(免责声明:我是这个包的作者)用于 ViewModel
基础 class 和 ICommand
实现,但您应该能够轻松地替换您使用的任何系统。
如果我为您找到更好的选择,我会将其添加为附加答案。
MainWindow.xaml(注意:TextBlock
上的 EventTrigger
已更改为 Border
上的 DataTrigger
:
<Window
x:Class="BindingHelp.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:local="clr-namespace:BindingHelp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
mc:Ignorable="d">
<Window.DataContext>
<local:MainWindowVm />
</Window.DataContext>
<StackPanel Orientation="Vertical">
<Border
x:Name="border"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Blue"
BorderThickness="3">
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShouldAnimate}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation
AutoReverse="True"
FillBehavior="Stop"
RepeatBehavior="5x"
Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)"
To="Yellow"
Duration="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock
MinWidth="200"
Background="White"
FontSize="24"
Text="{Binding Value, NotifyOnTargetUpdated=True}"
TextAlignment="Center" />
</Border>
<Button Command="{Binding Path=SetValueCommand}" Content="Update Value" />
</StackPanel>
</Window>
MainWindowVm.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using AgentOctal.WpfLib;
using AgentOctal.WpfLib.Commands;
namespace BindingHelp
{
class MainWindowVm : ViewModel
{
private string _value;
public string Value
{
get { return _value; }
set
{
if (SetValue(ref _value, value))
{
ShouldAnimate = true;
}
}
}
private bool _shouldAnimate = false;
public bool ShouldAnimate
{
get { return _shouldAnimate; }
set { SetValue(ref _shouldAnimate, value); }
}
private ICommand _setValueCommand;
public ICommand SetValueCommand
{
get
{
return _setValueCommand ?? (_setValueCommand = new SimpleCommand((obj) =>
{
Value = "This is a test!";
}));
}
}
}
}