2017-09-20 52 views
1

在WPF中,我可以在网页(或父控件)中创建一个故事板作为页/控制资源,然后将其用于控制​​多次...UWP:共享一个故事板

<Grid Background="{DynamicResource CorporateLogoBackgroundBrush}" views:MainWindowHelper.DragWindowOnMouseDown="True"> 

     <Grid.Resources> 

      <Storyboard x:Key="FlashRedBackgroundStoryboard"> 
       <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Duration="0:0:1" RepeatBehavior="Forever"> 
        <ObjectAnimationUsingKeyFrames.KeyFrames> 
         <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
          <DiscreteObjectKeyFrame.Value> 
           <SolidColorBrush Color="Red" /> 
          </DiscreteObjectKeyFrame.Value> 
         </DiscreteObjectKeyFrame> 
        </ObjectAnimationUsingKeyFrames.KeyFrames> 
       </ObjectAnimationUsingKeyFrames> 
      </Storyboard> 

     </Grid.Resources> 

     <Border Grid.Column="4" BorderThickness="0"> 

      <Border.Style> 
       <Style TargetType="{x:Type Border}"> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding Path=IsNetworkConnectivityOk}" Value="false"> 
          <DataTrigger.EnterActions> 
           <BeginStoryboard Name="FlashRedBackgroundStoryboard"> 
            <StaticResource ResourceKey="FlashRedBackgroundStoryboard" /> 
           </BeginStoryboard> 
          </DataTrigger.EnterActions> 
          <DataTrigger.ExitActions> 
           <StopStoryboard BeginStoryboardName="FlashRedBackgroundStoryboard"></StopStoryboard> 
          </DataTrigger.ExitActions> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </Border.Style> 

      <TextBlock Text="LAN/WLAN" /> 

     </Border> 

     <Border Grid.Column="5" BorderThickness="0"> 

      <Border.Style> 
       <Style TargetType="{x:Type Border}"> 
        <Setter Property="Background" Value="{DynamicResource CorporateLogoBackgroundBrush}" /> 
        <Style.Triggers> 
         <DataTrigger Binding="{Binding Path=SynchronisationClientService.IsActive}" Value="true"> 
          <Setter Property="Background" Value="Green" /> 
         </DataTrigger> 
         <DataTrigger Binding="{Binding Path=SynchronisationClientService.IsRunning}" Value="false"> 
          <DataTrigger.EnterActions> 
           <BeginStoryboard Name="FlashRedBackgroundStoryboard"> 
            <StaticResource ResourceKey="FlashRedBackgroundStoryboard" /> 
           </BeginStoryboard> 
          </DataTrigger.EnterActions> 
          <DataTrigger.ExitActions> 
           <StopStoryboard BeginStoryboardName="FlashRedBackgroundStoryboard"></StopStoryboard> 
          </DataTrigger.ExitActions> 
         </DataTrigger> 
        </Style.Triggers> 
       </Style> 
      </Border.Style> 

      <TextBlock Text="SYNC" /> 

     </Border> 

    </Grid> 

然而,我无法在UWP中找到同样的方法。在WPF中使用DataTrigger和BeginStoryboard自动似乎与Storyboard.TargetName关联,但在UWP中,我必须使用Interactions包,然后尝试将故事板与控件关联起来,方法与故事板不与控件关联的错误相同。 ..

<Grid Background="{StaticResource CorporateBackgroundBrush}"> 

    <Grid.Resources> 

     <Storyboard x:Key="FlashRedBackgroundStoryboard"> 
      <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Duration="0:0:1" RepeatBehavior="Forever"> 
       <ObjectAnimationUsingKeyFrames.KeyFrames> 
        <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
         <DiscreteObjectKeyFrame.Value> 
          <SolidColorBrush Color="Red" /> 
         </DiscreteObjectKeyFrame.Value> 
        </DiscreteObjectKeyFrame> 
       </ObjectAnimationUsingKeyFrames.KeyFrames> 
      </ObjectAnimationUsingKeyFrames> 
     </Storyboard> 


    </Grid.Resources> 


    <Border Grid.Column="4" BorderThickness="0"> 

     <interactivity:Interaction.Behaviors> 
      <interactionsCore:DataTriggerBehavior Binding="{Binding IsNetworkConnectivityOk}" ComparisonCondition="Equal" Value="false"> 
       <media:ControlStoryboardAction Storyboard="{StaticResource FlashRedBackgroundStoryboard}" /> 
      </interactionsCore:DataTriggerBehavior> 
     </interactivity:Interaction.Behaviors> 

     <TextBlock Text="LAN/WLAN" /> 

    </Border> 

    <Border Grid.Column="5" BorderThickness="0"> 

     <interactivity:Interaction.Behaviors> 
      <interactionsCore:DataTriggerBehavior Binding="{Binding IsNetworkConnectivityOk}" ComparisonCondition="Equal" Value="false"> 
       <media:ControlStoryboardAction Storyboard="{StaticResource FlashRedBackgroundStoryboard}" /> 
      </interactionsCore:DataTriggerBehavior> 
     </interactivity:Interaction.Behaviors> 

     <TextBlock Text="SYNC" /> 

    </Border> 

</Grid> 

我能找到这样做的UWP的唯一方法就是与每一个具有控制它会影响一个参考多个相同的故事板。

<Grid Background="{StaticResource CorporateBackgroundBrush}"> 

    <Grid.Resources> 

     <Storyboard x:Name="NetworkConnectivityStoryboard"> 
      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="NetworkConnectivityBorder" Storyboard.TargetProperty="Background" Duration="0:0:1" RepeatBehavior="Forever"> 
       <ObjectAnimationUsingKeyFrames.KeyFrames> 
        <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
         <DiscreteObjectKeyFrame.Value> 
          <SolidColorBrush Color="Red" /> 
         </DiscreteObjectKeyFrame.Value> 
        </DiscreteObjectKeyFrame> 
       </ObjectAnimationUsingKeyFrames.KeyFrames> 
      </ObjectAnimationUsingKeyFrames> 
     </Storyboard> 

     <Storyboard x:Name="SynchronisationStatusStoryboard"> 
      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SynchronisationStatusBorder" Storyboard.TargetProperty="Background" Duration="0:0:1" RepeatBehavior="Forever"> 
       <ObjectAnimationUsingKeyFrames.KeyFrames> 
        <DiscreteObjectKeyFrame KeyTime="0:0:0.5"> 
         <DiscreteObjectKeyFrame.Value> 
          <SolidColorBrush Color="Red" /> 
         </DiscreteObjectKeyFrame.Value> 
        </DiscreteObjectKeyFrame> 
       </ObjectAnimationUsingKeyFrames.KeyFrames> 
      </ObjectAnimationUsingKeyFrames> 
     </Storyboard> 

    </Grid.Resources> 


    <Border x:Name="NetworkConnectivityBorder" Grid.Column="4" BorderThickness="0"> 

     <interactivity:Interaction.Behaviors> 
      <interactionsCore:DataTriggerBehavior Binding="{Binding IsNetworkConnectivityOk}" ComparisonCondition="Equal" Value="false"> 
       <media:ControlStoryboardAction Storyboard="{StaticResource NetworkConnectivityStoryboard}" /> 
      </interactionsCore:DataTriggerBehavior> 
     </interactivity:Interaction.Behaviors> 

     <TextBlock Text="LAN/WLAN" /> 

    </Border> 

    <Border x:Name="SynchronisationStatusBorder" Grid.Column="5" BorderThickness="0"> 

     <interactivity:Interaction.Behaviors> 
      <interactionsCore:DataTriggerBehavior Binding="{Binding IsSynchronisingk}" ComparisonCondition="Equal" Value="false"> 
       <media:ControlStoryboardAction Storyboard="{StaticResource SynchronisationStatusStoryboard}" /> 
      </interactionsCore:DataTriggerBehavior> 
     </interactivity:Interaction.Behaviors> 

     <TextBlock Text="SYNC" /> 

    </Border> 

</Grid> 

有没有办法,我可以分享一个故事板,以便它可以对多个控件使用(在这种特定情况下的一种方式,它是一个状态栏和某些元素需要刷新的时候相关的视图模型属性都有一个特定的值。我不敢相信,我居然要创建多个重复的对象来实现这一目标。

感谢。

回答

3

在UWP,一个Storyboard只能在一个时间动画一个Target。那么从技术上讲,你可以手动停止(即Storyboard.Stop),改变其Target属性并开始动画(即, Storyboard.Begin)。

但是如果你想同时动画两个元素呢?那么这种方法将无法工作。这就是为每个要制作动画的元素创建新的Storyboard的原因。


下面是使用附加属性,而不是静态的XAML的解决方案。这是一些编写的代码,但是一旦安装完成,它就非常容易使用(即一行XAML代码),并且几乎可以与任何元素一起使用。

的想法是创建一个bool属性称为ShowFlashBackground,其可附接至具有Background性的元素,如BorderGrid或任何Control

然后,只要此属性设置为true(例如由IsNetworkConnectivityOk触发),请调用扩展方法FlashElementBackground来启动彩色动画。

守则

public static class Util 
{ 
    public static void SetShowFlashBackground(DependencyObject element, bool value) 
    { 
     element.SetValue(ShowFlashBackgroundProperty, value); 
    } 
    public static bool GetShowFlashBackground(DependencyObject element) 
    { 
     return (bool)element.GetValue(ShowFlashBackgroundProperty); 
    } 
    public static readonly DependencyProperty ShowFlashBackgroundProperty = DependencyProperty.RegisterAttached(
     "ShowFlashBackground", typeof(bool), typeof(Util), new PropertyMetadata(true, (s, e) => 
     { 
      if ((bool)e.NewValue) 
      { 
       var self = (FrameworkElement)s; 
       self.FlashElementBackground(); 

       // Rest the value back to false so the callback can be triggered again. 
       SetShowFlashBackground(self, false); 
      } 
     })); 

    public static void FlashElementBackground(this FrameworkElement element) 
    { 
     string elementTypeName; 

     switch (element) 
     { 
      case Border border: 
       elementTypeName = "Border"; 
       if (border.Background == null) border.Background = new SolidColorBrush(Colors.Transparent); 
       break; 
      case Panel panel: 
       elementTypeName = "Panel"; 
       if (panel.Background == null) panel.Background = new SolidColorBrush(Colors.Transparent); 
       break; 
      case Control control: 
       elementTypeName = "Control"; 
       if (control.Background == null) control.Background = new SolidColorBrush(Colors.Transparent); 
       break; 
      // More case statements can be added here to cover more scenarios... 
      default: 
       return; 
     } 

     var colorAnimation = new ColorAnimationUsingKeyFrames(); 
     var keyFrame1 = new LinearColorKeyFrame { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)), Value = Colors.Transparent }; 
     var keyFrame2 = new LinearColorKeyFrame { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(500)), Value = Colors.Red }; 
     colorAnimation.KeyFrames.Add(keyFrame1); 
     colorAnimation.KeyFrames.Add(keyFrame2); 

     Storyboard.SetTarget(colorAnimation, element); 
     Storyboard.SetTargetProperty(colorAnimation, $"({elementTypeName}.Background).(SolidColorBrush.Color)"); 

     var storyboard = new Storyboard 
     { 
      RepeatBehavior = RepeatBehavior.Forever, 
      AutoReverse = true 
     }; 
     storyboard.Children.Add(colorAnimation); 
     storyboard.Begin(); 
    } 
} 

的XAML

<Border local:Util.ShowFlashBackground="{Binding IsNetworkConnectivityOk}"> 
    <TextBlock Text="LAN/WLAN" /> 
</Border> 

<Border local:Util.ShowFlashBackground="{Binding IsSynchronisingOk}" 
     Grid.Column="1"> 
    <TextBlock Text="SYNC" /> 
</Border> 

希望这有助于!

相关问题