UWP: Sharing a storyboard
在WPF中,我可以创建一个故事板作为页面/控件资源,然后将其多次用于该页面中的控件(或父控件)...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <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程序包,然后尝试以与报文面板不与控件相关联的错误相同的方式将故事板与控件关联。 ..
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <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中找到做到这一点的唯一方法是拥有多个相同的情节提要板,每个情节提要板都引用了将影响的控件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <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> |
有没有一种我可以共享一个故事板的方式,以便可以将其用于多个控件(在此特定情况下,它是一个状态栏,并且当关联的视图模型属性具有特定值时,某些元素需要闪烁。无法相信我实际上必须创建多个重复的对象才能实现此目的。
谢谢。
在UWP中,
但是如果要同时为两个元素设置动画,该怎么办?然后这种方法将行不通。这就是为什么要为要设置动画的每个元素创建一个新的
这是一个使用附加属性而不是静态XAML的解决方案。这是写一些代码,但是一旦设置好,它就非常容易使用(即一行XAML代码)并且几乎可以与任何元素一起使用。
想法是创建一个名为
然后,只要将此属性设置为
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 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
1 2 3 4 5 6 7 8 | <Border local:Util.ShowFlashBackground="{Binding IsNetworkConnectivityOk}"> <TextBlock Text="LAN/WLAN" /> </Border> <Border local:Util.ShowFlashBackground="{Binding IsSynchronisingOk}" Grid.Column="1"> <TextBlock Text="SYNC" /> </Border> |
希望这会有所帮助!