【问题标题】:WPF: K.O. Can't Synchronize StoryBoards animations + Can't change application theme ????WPF:K.O.无法同步 StoryBoards 动画 + 无法更改应用程序主题 ????
【发布时间】:2020-10-12 17:38:12
【问题描述】:

所以我有一个 StackPanel 菜单,其中有很多按钮,每个按钮必须有一个网格和内部 2 个标签,第一个用于图标,第二个用于指示此按钮是否处于活动状态的小矩形。此外,每个按钮都链接到一个页面,当用户点击时,程序会显示相应的页面。

当程序想要引起用户对特定页面(例如通知页面)的注意时,会启动一个动画,其中我们会将图标标签(链接到该特定页面)以红色闪烁 2 次短时间,每 10 秒重复一次,直到用户点击此按钮才能看到通知。

问题 N:1

可能会出现多个通知同时从不同页面到达的情况,在这种情况下我们需要同步StoryBoards,以便按钮每隔10秒一起闪烁一次,否则您会看到每个按钮的结果都不愉快将在其他人身上单独闪烁。我的第一个想法是在StoryBoardBeginTime 上绑定一些东西,并让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 的应用主题,尤其是在没有机会使用BindingDynamic 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


【解决方案1】:

您无法单独使用XAML 解决您面临的问题。这是因为XAML 中的Storyboards 已冻结,您无法以任何方式更改它们。

我处理此问题的方式是将任何需要动态功能(如数据绑定或主题切换)的动画移动到代码中,并将它们作为 XAML/附加行为提供。

【讨论】:

  • 我从来没有听说过这种附加行为技术,你能给我一个小演示吗?根据您的经验,这可以解决我的第二个问题吗?我可以轻松更改主题颜色吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
相关资源
最近更新 更多