【问题标题】:How to combine DataTrigger and EventTrigger?如何结合 DataTrigger 和 EventTrigger?
【发布时间】:2010-12-13 08:35:02
【问题描述】:

注意我已经提出了相关问题(答案已被接受):How to combine DataTrigger and Trigger?

我认为我需要结合 EventTriggerDataTrigger 来实现我所追求的:

  • 当一个项目出现在我的 ListBox 中时,它应该会闪烁片刻
  • 如果项目为“关键”,则应保持突出显示

目前我有一个如下所示的 DataTemplate:

<DataTemplate DataType="{x:Type Notifications:NotificationViewModel}">
    <Grid HorizontalAlignment="Stretch">
        <Border Name="Background" CornerRadius="8" Background="#80c0c0c0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        <Border Name="Highlight"  CornerRadius="8" Background="Red"       HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        <!-- snip actual visual stuff -->
        <Grid.Triggers>
            <EventTrigger RoutedEvent="Grid.Loaded">
                <EventTrigger.Actions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation x:Name="LoadedAnimation" 
                                             Storyboard.TargetName="Highlight" 
                                             Storyboard.TargetProperty="Opacity" 
                                             From="0" To="1" 
                                             RepeatBehavior="5x" 
                                             Duration="0:00:0.2" 
                                             AutoReverse="True" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
        </Grid.Triggers>
    </Grid>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=IsCritical}" Value="True">
            <Setter TargetName="LoadedAnimation" Property="RepeatBehavior" Value="5.5x" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

这个想法是,EventTrigger 将 Highlight 边框的不透明度设置为 0 和 1 之间的动画,并在项目首次加载时重复返回,从而吸引用户的注意力。 DataTrigger 确定动画的次数。如果视图模型报告项目 IsCritical 则动画发生 5.5 次(以不透明度 1 结束),否则发生 5 次(以不透明度 0 结束。)

但是上面的 XAML 不起作用,因为 DataTrigger 的设置器失败:

在 VisualTree 中找不到名为“LoadedAnimation”的子项。

很公平。那么,对于使用自定义值转换器或将动画计数放在视图模型上并绑定到它,我的选择是什么?

【问题讨论】:

标签: .net wpf xaml triggers datatrigger


【解决方案1】:

在这种情况下,我会使用行为而不是触发器。您可以编写一个行为,将事件处理程序附加到关联对象的加载事件,然后应用动画。该行为可能会公开一些属性,我会公开一个 AnimationCount (int) 属性,该属性告诉行为在与其关联的元素上重复动画多少次。然后,您可以将此属性绑定到视图模型中的 IsCritical 属性,并使用值转换器将 false 转换为 5,将 true 转换为 5.5

希望对你有帮助

【讨论】:

    【解决方案2】:

    如果您可以访问 Blend SDK(如果您使用的是 VS2012+,则应该可以访问),您应该能够完全在 XAML 中完成此操作,类似以下内容(免责声明:未经测试):

    <Grid HorizontalAlignment="Stretch">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="NotificationStates">
                <VisualState x:Name="Flashing">
                    <Storyboard>
                        <DoubleAnimation x:Name="LoadedAnimation" 
                                         Storyboard.TargetName="Highlight" 
                                         Storyboard.TargetProperty="Opacity" 
                                         From="0" To="1" 
                                         RepeatBehavior="5x" 
                                         Duration="0:00:0.2" 
                                         AutoReverse="True" />
                    </Storyboard>
                </VisualState>
                <VisualState x:Name="Normal" />
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <Border Name="Background" CornerRadius="8" Background="#80c0c0c0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        <Border Name="Highlight"  CornerRadius="8" Background="Red"       HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        <!-- snip actual visual stuff -->
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <ic:GoToStateAction StateName="Flashing"/>
            </i:EventTrigger>
            <ie:DataTrigger Binding="{Binding Path=IsCritical}" Value="True">
                <ic:GoToStateAction StateName="Flashing"/>
            </ie:DataTrigger>
        </i:Interaction.Triggers>
    </Grid>
    

    将 Storyboard 提取到 VisualState,然后使用表达式库在 XAML 中切换状态。您将需要 Microsoft.Expression.Interactions 库,另请参阅 WPF/Silverlight States - Activate from XAML?

    【讨论】:

      【解决方案3】:

      我知道您说过您并不热衷于转换器的想法,但看起来 Blend 解决方案需要安装一个库。转换器的工作量并不大,并且表明该速率直接取决于 IsCritical 属性:

      public class CriticalAnimationRateConverter : IValueConverter
      {
          public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
          {
              // Error handling omitted for brevity.
              if ((bool)value)
                  return new System.Windows.Media.Animation.RepeatBehavior(5.5);
              else
                  return new System.Windows.Media.Animation.RepeatBehavior(5.0);
          }
      
          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
          {
              throw new NotImplementedException();
          }
      }
      

      然后更新你的动画:

      <DoubleAnimation Storyboard.TargetName="Highlight"
                       Storyboard.TargetProperty="Opacity"
                       From="0"
                       To="1"
                       RepeatBehavior="{Binding IsCritical, Converter={StaticResource CriticalAnimationRateConverter}}"
                       Duration="0:00:0.2"
                       AutoReverse="True" />
      

      然后可以删除DataTrigger

      【讨论】:

        【解决方案4】:

        试试这样的:

        <Style x:Key="EventTriggerStyleKey">
          <Style.Triggers>
            <EventTrigger RoutedEvent="some event here">
              <!-- your animation here -->
            </EventTrigger>
          <Style.Triggers>
        </Style>
        
        <Style x:Key="myStyleKey">
          <Style.Triggers>
            <DataTrigger Binding="....." Value="......">
              <Setter Property="........." Value="......."/>
              <Setter Property="Style" Value="{StaticResource EventTriggerStyleKey}"/>
            </DataTrigger>
          <Style.Triggers>
        </Style>
        

        【讨论】:

        • 你试过了吗?根据我的经验,你不能有一种风格来设定风格。
        • 不能在样式中设置样式
        猜你喜欢
        • 2012-07-11
        • 2010-10-10
        • 2021-08-07
        • 2016-03-19
        • 2023-04-05
        • 2017-12-01
        • 1970-01-01
        • 2012-03-19
        • 1970-01-01
        相关资源
        最近更新 更多