I have some scrolling text animation modified from this post on MSDN. I'm having two issues with it, though.
The first is that I need to be able to update the text within at periodic intervals. However, when OnTick() fires, I get the following error, "The calling thread cannot access this object because a different thread owns it." I've tried a few different things, and have posted one method I've tried.
The second is that instead of scrolling back and forth, I really need the text to behave as a true marquee and travel one direction, with the content flowing constantly with no gaps, i.e. "a b c d e a b c d e ..." not "a b c d e". Will this require two storyboards running in tandem with the same text or is there another way to accomplish this?
Storyboard storyboard = new Storyboard();
Timer timer;
public void OnLoad(object sender, RoutedEventArgs e)
{
_presenter.OnViewReady();
StartMarquee();
}
public MyControl()
{
InitializeComponent();
Loaded += OnLoad;
timer = new Timer(OnTick, null, 10000, 10000);
}
private void OnTick(object state)
{
storyboard.Stop(marqueeText);
storyboard = new Storyboard();
marqueeText.Text =
"Fusce id massa sed tortor volutpat viverra. Mauris ut quam. Fusce iaculis magna at urna. In sed dui vitae quam faucibus ullamcorper. Donec hendrerit magna eget neque. Mauris sit amet risus dictum mauris ultricies ornare. Phasellus lectus leo, mattis eget, ultrices vel, suscipit eu, tellus. Integer ut enim. Suspendisse hendrerit mattis sem. Aenean interdum elementum libero. ";
StartMarquee();
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
marqueeText.Text =
"Is it possible to create a marquee or scrolling text in WPF? Is it possible to create a marquee or scrolling text in WPF? Is it possible to create a marquee or scrolling text in WPF? Is it possible to create a marquee or scrolling text in WPF? Is it possible to create a marquee or scrolling text in WPF? Is it possible to create a marquee or scrolling text in WPF?";
}
private void StartMarquee()
{
var canvas = CommonFunctions.FindVisualParent<Canvas>(marqueeText);
if (marqueeText.ActualWidth < canvas.ActualWidth) return;
var duration = new Duration(TimeSpan.FromSeconds(marqueeText.ActualWidth / 60));
var animation = new DoubleAnimation(-marqueeText.ActualWidth, canvas.ActualWidth, duration);
animation.RepeatBehavior = RepeatBehavior.Forever;
Storyboard.SetTargetName(animation, "rtTTransform");
animation.AutoReverse = false;
Storyboard.SetTargetProperty(animation, new PropertyPath(TranslateTransform.XProperty));
storyboard.Children.Add(animation);
storyboard.Begin(marqueeText);
}
In the view, the control is declared as
<Canvas Grid.Column="1" HorizontalAlignment="Stretch" ClipToBounds="True" Margin="10,0">
<TextBlock Canvas.Left="0" Canvas.Top="0" x:Name="marqueeText" TextWrapping="NoWrap" VerticalAlignment="Center"
Grid.Column="1" Foreground="{x:Static Brushes.White}" ClipToBounds="False" FontSize="16">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform x:Name="rtTTransform"/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Canvas>
Thanks in advance I'm still working on this one and will update with any changes I find.
[Edited] Removed AutoReverse to make things less confusing and more toward what I'm trying to accomplish.