2009-04-22 3 views
0

У меня есть анимация с прокруткой текста, измененная с this post on MSDN. Однако у меня есть две проблемы.Проблемы с обновлением текста прокрутки

Первое, что я должен иметь возможность обновлять текст внутри с периодическими интервалами. Однако, когда запускается OnTick(), я получаю следующую ошибку: «Вызывающий поток не может получить доступ к этому объекту, потому что ему принадлежит другой поток». Я пробовал несколько разных вещей и опубликовал один метод, который я пробовал.

Во-вторых, вместо прокрутки вперед и назад мне действительно нужен текст, который будет вести себя как настоящая шатер и двигаться в одном направлении, при этом содержимое постоянно течет без пробелов, то есть «abcdeabcde ...» не «abcde ». Будет ли это требовать двух раскадровки, работающих в тандеме с одним и тем же текстом или есть ли другой способ сделать это?

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

По мнению, контроль объявлен как

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

Заранее спасибо я все еще работаю на этом и будет обновлять любые изменения, которые я найти.

Отредактировано Удалено AutoReverse, чтобы сделать вещи менее запутанными и больше к тому, чего я пытаюсь выполнить.

ответ

2

Я решил решить проблему, создав поток, который работает в фоновом режиме, обновляя текст с интервалами, и когда текст заканчивает прокрутку, потянув за любой последний текст.

Полный пример включен в случае, если он поможет кому-либо еще в будущем.

public Thread Updater; 
    public MyControl() 
    { 
     InitializeComponent(); 
     Loaded += OnLoad; 
     Updater = new Thread(ExecuteMarqueeUpdate); 
     Updater.Name = "MARQUEEUPDATE"; 
     Updater.IsBackground = true; 

     UpdateMarqueeInfo(); 
     marqueeText.Text = currentMarqueeText; 
     StartMarquee(); 
    } 
    public void ExecuteMarqueeUpdate() 
    { 
     while (true) 
     { 
      UpdateMarqueeInfo(); 
      Thread.Sleep(60000); 
     } 


    private string currentMarqueeText; 

    public void UpdateMarqueeInfo() 
    { 
     Random r = new Random(); 
     int i = r.Next(5, 8); 
     string s = ""; 
     for(int x = 0; x < i; x++) 
     { 
      s += "Is it possible to create a marquee or scrolling text in WPF? "; 
     } 
     currentMarqueeText = s; 
    } 

    public void StartMarquee() 
    { 
     var canvas = (Canvas)marqueeText.Parent; 
     if (marqueeText.ActualWidth < canvas.ActualWidth) return; 
     var duration = new Duration(TimeSpan.FromSeconds(marqueeText.ActualWidth/60)); 
     var animation = new DoubleAnimation(canvas.ActualWidth, -marqueeText.ActualWidth, duration); 
     Storyboard.SetTargetName(animation, "rtTTransform"); 
     Storyboard.SetTargetProperty(animation, new PropertyPath(TranslateTransform.XProperty)); 
     animation.Completed += OnMarqueeScrollComplete; 

     storyboard.Children.Clear(); 
     storyboard.Children.Add(animation); 
     storyboard.Begin(marqueeText); 
    } 

    private void OnMarqueeScrollComplete(object sender, EventArgs e) 
    { 
     if (!Updater.IsAlive) 
     { 
      Updater.Start(); 
     } 

     // Stop the running animation then reset the text. 
     // The data updates via the background thread, so just pull as available. 
     storyboard.Stop(); 
     marqueeText.Text = currentMarqueeText; 

     // Restart the marquee animation. 
     StartMarquee(); 
    } 
0

Не знаю много о анимации раскадровки, но я могу помочь с тем, что «вызывающий поток не может получить доступ к этому объекту».

Ваша проблема заключается в том, что событие таймера срабатывает в потоке таймера, и для обновления пользовательского интерфейса вы должны работать в потоке пользовательского интерфейса. Самый простой способ исправить это - использовать DispatcherTimer.

Смежные вопросы