Если предполагается, что это анимация выделения, я бы использовал два текстовых блока.
Вы найдете рабочий образец, связанный со статьей, здесь:
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
В образце есть сетка, которая будет расширяться до ширины любого контейнера, в котором она находится.
Там это холст в этом.
Канва не обрезает свое содержимое, если оно находится за пределами границ холста.
Этот холст позволяет одному текстовому блоку располагаться вне экрана справа от панели, а другой - другому. слева от панели.
Сетка затем анимируется слева направо.
Раскадровка:
<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;
}
Анимация останавливается и перезаписывается - начал с того, чтобы сказать, чтобы начать снова. Это самый простой способ избежать странностей при изменении размера пользователя.
Надеюсь, это понятно.