【发布时间】:2020-10-12 17:38:12
【问题描述】:
所以我有一个 StackPanel 菜单,其中有很多按钮,每个按钮必须有一个网格和内部 2 个标签,第一个用于图标,第二个用于指示此按钮是否处于活动状态的小矩形。此外,每个按钮都链接到一个页面,当用户点击时,程序会显示相应的页面。
当程序想要引起用户对特定页面(例如通知页面)的注意时,会启动一个动画,其中我们会将图标标签(链接到该特定页面)以红色闪烁 2 次短时间,每 10 秒重复一次,直到用户点击此按钮才能看到通知。
问题 N:1
可能会出现多个通知同时从不同页面到达的情况,在这种情况下我们需要同步StoryBoards,以便按钮每隔10秒一起闪烁一次,否则您会看到每个按钮的结果都不愉快将在其他人身上单独闪烁。我的第一个想法是在StoryBoard 的BeginTime 上绑定一些东西,并让StoryBoard 在开始之前等待正在运行的动画。所以,我跳到代码中,当我编写这个绑定时,会弹出一个很棒的异常:无法冻结这个 Storyboard 时间线树以用于提要,我用谷歌搜索它,我发现我不允许在StoryBoard ControlTemplate 中使用任何绑定或动态资源,所以,我实现了一个小的DependencyProperty 来同步动画,这就是你会注意到这条小线的原因这里:
<Condition Binding="{Binding Synchronizer}" Value="1"/>
C#代码
public partial class Layout : Window {
public double Synchronizer { get; set; } = 0;
public static readonly DependencyProperty DependencyProperty = DependencyProperty.Register("Synchronizer", typeof(double), typeof(Layout), new PropertyMetadata());
public Layout(){
{
InitializeComponent(); DataContext = this;
}
}
}
由于此 XAML 代码而触发了此同步器:
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard>
<Storyboard RepeatBehavior="Forever" Duration="0:0:10">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="DataContext.Synchronizer" Duration="0:0:0.6">
<DiscreteDoubleKeyFrame Value="1" KeyTime="0:0:0.0"/>
<DiscreteDoubleKeyFrame Value="0" KeyTime="0:0:0.6"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
问题 N:1 在是/否的答案中,是否有任何解决此异常的方法?
问题 N:2有更好的解决方案吗?
问题 N:2
该应用程序有几种样式,主要是 Dark.Xaml 和 Light.Xaml,正如我们在第一期中已经看到的,动画用于向用户指示特定页面需要注意。在深色模式下,我们将用红色闪烁图标,在浅色模式下,我们将用蓝色闪烁,所以让我专注于这部分代码:
<ColorAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetProperty="(Label.Foreground).(SolidColorBrush.Color)">
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.2"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.3"/>
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.4"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.6"/>
</ColorAnimationUsingKeyFrames>
一般来说,我使用这个 C# 代码更改应用程序的主题:
Resources.MergedDictionaries.Clear();
Resources.MergedDictionaries.Add(Global.Themes[i]);
它适用于具有DynamicResource 绑定的元素,但对于StaticResource 否!!
问题:如何更改此
StoryBoardControlTemplate的应用主题,尤其是在没有机会使用Binding或Dynamic Resource的情况下。
<ControlTemplate x:Key="Menu.Button" TargetType="Button">
<Grid>
<Label Content="{TemplateBinding Content}">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Width" Value="35"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Tag, Converter={StaticResource Check}, ConverterParameter=1|1}" Value="True"/>
<Condition Binding="{Binding Synchronizer}" Value="1"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard Name="Storyboard">
<Storyboard>
<ColorAnimationUsingKeyFrames Duration="0:0:0.6" Storyboard.TargetProperty="(Label.Foreground).(SolidColorBrush.Color)">
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.2"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.3"/>
<LinearColorKeyFrame Value="#8B0000" KeyTime="0:0:0.4"/>
<LinearColorKeyFrame Value="#272725" KeyTime="0:0:0.6"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<RemoveStoryboard BeginStoryboardName="Storyboard"/>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
<Label>
<Label.Style>
<Style TargetType="Label">
<Setter Property="Width" Value="2"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}, Path=Tag, Converter={StaticResource Check}, ConverterParameter=0|0}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed"></Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
</ControlTemplate>
<StackPanel Name="Menu" DockPanel.Dock="Left" Width="35" Orientation="Vertical" VerticalAlignment="Bottom">
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
<Button Template="{StaticResource Menu.Button}"/>
</StackPanel>
【问题讨论】:
-
刷机的方式是一动画一刷。在所有适当的按钮上使用那个刷子。这可能来自父窗口的资源或标签。也许使用数据触发器应用。在这种情况下,如果方便的话,您可以使用转换器生成画笔。转换器可以很容易地成为单例,并且可以从 applicaton.current.resources 中找到用于其画笔的颜色。
标签: c# wpf visual-studio