Проблемы с прокруткой текстового обновления - PullRequest
0 голосов
/ 22 апреля 2009

У меня есть некоторая анимация прокрутки текста, измененная с этого поста на 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 ]

2 голосов
/ 24 апреля 2009

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

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

    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 голосов
/ 23 апреля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...