从 XAML 到 C# 的 WPF 故事板

Posted

技术标签:

【中文标题】从 XAML 到 C# 的 WPF 故事板【英文标题】:WPF Storyboard from XAML to C# 【发布时间】:2021-02-16 03:47:43 【问题描述】:

我有一个自定义 Ticker 控件,它可以很好地处理静态值,但要让它处理动态值,我需要在代码中执行此操作,因为我必须延迟情节提要执行,直到 TextBlock 被渲染。 我需要将以下 XAML 转移到 C# 中,但它不起作用:

<Canvas x:Name="PART_TickerCanvas" Grid.Row="1" Width="128" ClipToBounds="True">
                        <TextBlock x:Name="PART_TickerTextBlock">
                            <TextBlock.Triggers>
                                <EventTrigger RoutedEvent="Loaded">
                                    <BeginStoryboard>
                                        <Storyboard>
                                            <DoubleAnimation
                        Storyboard.TargetName="TickerTranslateTransform"
                        Storyboard.TargetProperty="X"
                        From="Binding ElementName=TickerCanvas, Path=ActualWidth" To="Binding ElementName=PART_TickerTextBlock, Path=RenderSize.Width, Converter=StaticResource TextBlockWidthConverter" Duration="0:0:10"
                        RepeatBehavior="Forever"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </EventTrigger>
                            </TextBlock.Triggers>
                            <TextBlock.RenderTransform>
                                <TranslateTransform x:Name="TickerTranslateTransform" X="Binding ElementName=PART_TickerCanvas, Path=ActualWidth" Y="0" />
                            </TextBlock.RenderTransform>
                        </TextBlock>
                    </Canvas>

转换器简单地否定宽度。

这是我的 C# 方法:

public override void OnApplyTemplate()
    
        base.OnApplyTemplate();
        if (Template != null)
        
            _tickerTextBlock = Template.FindName("PART_TickerTextBlock", this) as TextBlock;
            _tickerCanvas = Template.FindName("PART_TickerCanvas", this) as Canvas;
            Dispatcher.BeginInvoke(new Action(() => if (_tickerCanvas != null && _tickerTextBlock != null) StartTickerAnimation(); ), DispatcherPriority.ContextIdle, null);                
        
    

private void StartTickerAnimation()
    
        var doubleAnimation = new DoubleAnimation
        
            From = _tickerCanvas.ActualWidth,
            To = -_tickerTextBlock.RenderSize.Width,
            RepeatBehavior = RepeatBehavior.Forever,
            Duration = new Duration(new TimeSpan(0, 0, 10))
        ;

        _tickerTextBlock.RenderTransform = new TranslateTransform(_tickerCanvas.ActualWidth, 0);
        RegisterName("TickerTranslateTransform", _tickerTextBlock.RenderTransform);          

        var storyBoard = new Storyboard();
        storyBoard.Children.Add(doubleAnimation);
        storyBoard.SetValue(Storyboard.TargetNameProperty, "TickerTranslateTransform");
        storyBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath(TranslateTransform.XProperty.Name));
        storyBoard.SetValue(Storyboard.TargetProperty, _tickerTextBlock.RenderTransform);
        _tickerTextBlock.BeginStoryboard(_storyBoard);
    

我很确定 DoubleAnimation 在 C# 中是正确的,但之后出现了问题。任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

您不需要故事板。

像这样直接启动X属性的动画:

_tickerTextBlock.RenderTransform.BeginAnimation(
    TranslateTransform.XProperty, doubleAnimation);

【讨论】:

我刚刚添加了 _tickerTextBlock.Dispatcher.Invoke(DispatcherPriority.Render, (Action)delegate () );在文本属性发生变化时更新 TextBox。

以上是关于从 XAML 到 C# 的 WPF 故事板的主要内容,如果未能解决你的问题,请参考以下文章

如何为 WPF 故事板中的静态对象设置动画

wpf故事板死亡

重新启动 WPF 故事板

什么是依赖项属性?(在练习使用StoryBoard故事板时,遇到的问题)

故事板找不到 ControlTemplate 元素

Silverlight:重复故事板的一部分