【问题标题】:WPF,C# I don't understand, Ticker Moving From "From" to"To"WPF,C# 我不明白,Ticker 从“From”移动到“To”
【发布时间】:2020-04-03 09:30:37
【问题描述】:

在代码中

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>

我确实做了一个ticker,但是我不明白Canvas从“From”到“To”的移动原理。

【问题讨论】:

  • 我不明白这个问题。你对什么感到困惑?

标签: c# wpf ticker


【解决方案1】:

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

它不会为画布设置动画。它为文本块的 Right 属性设置动画。

Canvas.RightProperty 只是属性的标识符,而不是对具有该属性的对象的引用。对 BeginAnimation 的调用在 TextBoxMarquee 上,因此 TextBox 的 Right 属性将被动画化。

【讨论】:

    【解决方案2】:

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

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

    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 超出画布边界,则不会剪切其内容。

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

    然后从左到右为网格设置动画。

    故事板:

    <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 中的代码用于计算当前窗口的宽度。

        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;
        }
    

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

    我希望这很清楚。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2016-06-24
      • 1970-01-01
      • 2018-08-03
      • 2023-03-10
      • 2011-02-09
      • 1970-01-01
      相关资源
      最近更新 更多