WPF,C# 我不明白,Ticker 从 "From" 移动到 "To"

WPF,C# I don't understand, Ticker Moving From "From" to"To"

在代码中

private void TickerGrid_Loaded(object sender, RoutedEventArgs e)
{
    double height = TickerCanvas.ActualHeight - TextBoxMarquee.ActualHeight;
    TextBoxMarquee.Margin = new Thickness(0, height / 2, 0, 0);
    DoubleAnimation doubleAnimation = new DoubleAnimation();
    doubleAnimation.From = -TextBoxMarquee.ActualWidth; // -277
    doubleAnimation.To = TickerCanvas.ActualWidth; //524
    doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
    doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
    TextBoxMarquee.BeginAnimation(Canvas.RightProperty, doubleAnimation);
}

在Xaml

<Grid x:Name="TickerGrid" Grid.Row="2" Loaded="TickerGrid_Loaded" Background="#2B2F3B" >
    <Canvas ClipToBounds="True" Name="TickerCanvas" Background="Transparent">
        <TextBlock ClipToBounds="True" Name="TextBoxMarquee" Background="#2B2F3B">
            <TextBlock.Inlines>
                <Run FontWeight="Bold" Foreground="#55CFE3" FontSize="14" Text="This is WPF Ticker Title." />
                <Run FontSize="13" Foreground="#FFFFFF" Text="This is Content text." />
            </TextBlock.Inlines>
        </TextBlock>
    </Canvas>
</Grid>

我做了一个行情,但是我不明白Canvas从"From"移动到"To"的原理。

如果这应该是选取框动画,那么我会使用两个文本块。

您将在此处找到文章链接的工作示例:

https://social.technet.microsoft.com/wiki/contents/articles/31416.wpf-mvvm-friendly-user-notification.aspx#Marquee

https://gallery.technet.microsoft.com/WPF-User-Notification-MVVM-98940828

样本有一个网格,它会扩展以适应它所在容器的宽度。

这里面有个canvas

如果内容超出 canvas 范围,Canvas 不会剪辑它的内容。

canvas 允许将一个文本块放置在面板右侧和面板左侧的屏幕外。

然后网格从左到右动画化。

故事板:

<Window.Resources>
    <!-- "To" of this is set in code because of the window resizing -->
    <Storyboard x:Key="SBmarquee">
        <DoubleAnimation From="0"  
                         Duration="00:00:8"
                         Storyboard.TargetProperty="X"
                         Storyboard.TargetName="Xmarquee" 
                         RepeatBehavior="3"/>
        <DoubleAnimation Storyboard.TargetProperty="Opacity" 
                         Storyboard.TargetName="MarqueeContainer" 
                         To="1"/>
        <DoubleAnimation Storyboard.TargetProperty="Opacity" 
                         Storyboard.TargetName="MarqueeContainer" 
                         BeginTime="0:0:20"
                         Duration="0:0:4" To="0"/>
    </Storyboard>
</Window.Resources>

网格:

    <Grid x:Name="MarqueeContainer" VerticalAlignment="Bottom">
        <Grid.RenderTransform>
            <TranslateTransform x:Name="Xmarquee" X="0"/>
        </Grid.RenderTransform>
        <Canvas Height="24" 
            TextBlock.Foreground="Red">
            <TextBlock Text="{Binding MarqueeMessage, NotifyOnTargetUpdated=True}" Canvas.Left="0">
                <TextBlock.Triggers>
                    <EventTrigger RoutedEvent="Binding.TargetUpdated">
                        <BeginStoryboard Storyboard="{StaticResource SBmarquee}" />
                    </EventTrigger>
                </TextBlock.Triggers>
            </TextBlock>
            <TextBlock Text="{Binding MarqueeMessage}"
                   Foreground="Red"
                   Canvas.Left="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type Canvas}}}"/>
        </Canvas>
    </Grid>

随着最左边的文本块移出显示屏,最右边的文本块出现。

Window_ContentRendered和Window_SizeChanged中的代码用于计算window的当前宽度。

    private Storyboard SBMarquee;
    private DoubleAnimation XAnimation;
    private void Window_ContentRendered(object sender, EventArgs e)
    {
        SBMarquee = this.Resources["SBmarquee"] as Storyboard;
        XAnimation = SBMarquee.Children[0] as DoubleAnimation;
        XAnimation.To = MarqueeContainer.ActualWidth * -1;
        this.SizeChanged += Window_SizeChanged;
    }

    private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        XAnimation.To = MarqueeContainer.ActualWidth * -1;
        MarqueeContainer.Visibility = Visibility.Hidden;
        SBMarquee.Begin();
        MarqueeContainer.Visibility = Visibility.Visible;
    }

动画停止并通过告诉它重新开始重新开始。这是在用户调整大小时避免异常的最简单方法。

我希望你明白了。

TextBoxMarquee.BeginAnimation(Canvas.RightProperty, doubleAnimation); 是令人困惑的部分。

它不会为 Canvas 设置动画。它为文本块的右侧 属性 设置动画。

Canvas.RightProperty 只是 属性 的标识符,而不是对具有 属性 的对象的引用。对 BeginAnimation 的调用是在 TextBoxMarquee 上进行的,因此将对 TextBox 的右侧 属性 进行动画处理。