WPF - 使动画的执行以绑定(bind)数据项的属性为条件

标签 wpf xaml animation datatemplate coloranimation

我有一个数据对象——一个名为 Notification 的自定义类-- 暴露一个 IsCritical属性(property)。这个想法是,如果通知将过期,它有一个有效期,并且应该引起用户的注意。

想象一下这个测试数据的场景:

_source = new[] {
    new Notification { Text = "Just thought you should know" },
    new Notification { Text = "Quick, run!", IsCritical = true },
  };

第二项应出现在 ItemsControl 中具有脉动的背景。这是一个简单的数据模板摘录,显示了我考虑在灰色和黄色之间设置动画背景的方法。
<DataTemplate DataType="Notification">
  <Border CornerRadius="5" Background="#DDD">
    <Border.Triggers>
      <EventTrigger RoutedEvent="Border.Loaded">
        <BeginStoryboard>
          <Storyboard>
            <ColorAnimation 
              Storyboard.TargetProperty="Background.Color"
              From="#DDD" To="#FF0" Duration="0:0:0.7" 
              AutoReverse="True" RepeatBehavior="Forever" />
          </Storyboard>
        </BeginStoryboard>
      </EventTrigger>
    </Border.Triggers>
    <ContentPresenter Content="{TemplateBinding Content}" />
  </Border>
</DataTemplate>

我不确定的是如何使这个动画以 IsCritical 的值为条件。 .如果边界值为false ,则默认背景颜色为#DDD应该保持。

最佳答案

这个谜题的最后一部分是... DataTriggers .您所要做的就是将一个 DataTrigger 添加到您的 DataTemplate,将其绑定(bind)到 IsCritical 属性,并且只要它为真,您就可以在 EnterAction/ExitAction 中启动和停止突出显示 Storyboard 。这是带有一些硬编码快捷方式的完全有效的解决方案(您绝对可以做得更好):

Xaml :

<Window x:Class="WpfTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Notification Sample" Height="300" Width="300">
  <Window.Resources>
    <DataTemplate x:Key="NotificationTemplate">
      <Border Name="brd" Background="Transparent">
        <TextBlock Text="{Binding Text}"/>
      </Border>
      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding IsCritical}" Value="True">
          <DataTrigger.EnterActions>
            <BeginStoryboard Name="highlight">
              <Storyboard>
                <ColorAnimation 
                  Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)"
                  Storyboard.TargetName="brd"
                  From="#DDD" To="#FF0" Duration="0:0:0.5" 
                  AutoReverse="True" RepeatBehavior="Forever" />
              </Storyboard>
            </BeginStoryboard>
          </DataTrigger.EnterActions>
          <DataTrigger.ExitActions>
            <StopStoryboard BeginStoryboardName="highlight"/>
          </DataTrigger.ExitActions>
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </Window.Resources>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="*"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <ItemsControl ItemsSource="{Binding Notifications}"
                  ItemTemplate="{StaticResource NotificationTemplate}"/>
    <Button Grid.Row="1"
            Click="ToggleImportance_Click"
            Content="Toggle importance"/>
  </Grid>
</Window>

后面的代码:
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;

namespace WpfTest
{
  public partial class Window1 : Window
  {
    public Window1()
    {
      InitializeComponent();
      DataContext = new NotificationViewModel();
    }

    private void ToggleImportance_Click(object sender, RoutedEventArgs e)
    {
      ((NotificationViewModel)DataContext).ToggleImportance();
    }
  }

  public class NotificationViewModel
  {
    public IList<Notification> Notifications
    {
      get;
      private set;
    }

    public NotificationViewModel()
    {
      Notifications = new List<Notification>
                        {
                          new Notification
                            {
                              Text = "Just thought you should know"
                            },
                          new Notification
                            {
                              Text = "Quick, run!",
                              IsCritical = true
                            },
                        };
    }

    public void ToggleImportance()
    {
      if (Notifications[0].IsCritical)
      {
        Notifications[0].IsCritical = false;
        Notifications[1].IsCritical = true;
      }
      else
      {
        Notifications[0].IsCritical = true;
        Notifications[1].IsCritical = false;
      }
    }
  }

  public class Notification : INotifyPropertyChanged
  {
    private bool _isCritical;

    public string Text { get; set; }

    public bool IsCritical
    {
      get { return _isCritical; }
      set
      {
        _isCritical = value;
        InvokePropertyChanged("IsCritical");
      }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void InvokePropertyChanged(string name)
    {
      var handler = PropertyChanged;
      if (handler != null)
      {
        handler(this, new PropertyChangedEventArgs(name));
      }
    }
  }
}

希望这可以帮助 :)。

关于WPF - 使动画的执行以绑定(bind)数据项的属性为条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1294353/

相关文章:

c# - C#、WPF项目的自动化测试和持续集成

WPF - 当 ListView 为空时不显示上下文菜单

javascript - 如何在动画完成之前停止按下导航按钮?

python - matplotlib 动画的内存使用

c# - 如何在文本框中重用自动换行算法?

c# - MVVM 解决方案结构

wpf - 我可以将数据绑定(bind)到 DataGridRow.DetailsVisibility 吗?

c# - 文本字符串代码后面的粗体部分

javascript - 这是一个好的 React 实践吗?

wpf - 如何处理MVVM中的多个窗口和对话框?