Простая анимация в приложении MVVM WPF - PullRequest
0 голосов
/ 14 апреля 2011

У меня есть приложение MVVM, у которого есть ползунок, и когда пользователь меняет ползунок, он обновляет изображение на экране и обновляет некоторые графики.Это все работает, когда пользователь меняет положение ползунка, я хотел бы добавить кнопку «Play», которая автоматически перемещает ползунок, и все обновляется.Я попробовал следующий код, чтобы сделать это, и когда я пытаюсь это сделать, ничего не меняется на экране.Я подтвердил, что он действительно запускает код и изменяет переменную SliderPos.Чего мне не хватает?

private void VSMPlayer()
    {
        SliderPos = 0;
        const int speed = 1;

        while (SliderPos < SliderLength)
        {
            Thread.Sleep(100 / speed);

            SliderPos = SliderPos + 20;
        }

        // todo finish this function
    }

Для ясности вот свойство SliderPos

public double SliderPos {get {return this.sliderPos;}

        set
        {
            this.sliderPos = value;
            SetCursorLocation();
            SetParameters();
            this.RaisePropertyChanged("SliderPos");
        }
    }

Ответы [ 2 ]

1 голос
/ 14 апреля 2011

Класс, владеющий SliderPos, должен реализовать INotifyPropertyChanged.(Если ваш Slider.Value связан с этим свойством)

Редактировать: Это само по себе не работает, так как Уилл правильно заметил, что поток пользовательского интерфейса спит.

Выможно попробовать что-то вроде этого, это работает:

SliderPosition = 0;
DispatcherTimer timer = null;
timer = new DispatcherTimer(TimeSpan.FromSeconds(0.1), DispatcherPriority.Render, delegate
{
    SliderPosition += 20;
    if (SliderPosition > 100) timer.Stop();
},
Dispatcher.CurrentDispatcher);
timer.Start();

Edit2: Если вы не изменяете какие-либо элементы управления, принадлежащие пользовательскому интерфейсу, вы можете просто использовать любой потоккроме UI-Thread, например:

SliderPosition = 0;
new Thread(new ThreadStart(delegate
{
    while (SliderPosition < 100)
    {
        Thread.Sleep(100);
        SliderPosition += 20;
    }
})).Start();
0 голосов
/ 14 апреля 2011

Посмотрите на подобное решение:

ViewModel:

public class MainVM : INotifyPropertyChanged
{
    public int SliderLength
    {
        get
        {
            return Names.Count - 1;
        }
    }
    private void VSMPlayer()
    {
        SliderPos = 0;
        const int speed = 1;
        while (SliderPos < SliderLength)
        {
            Thread.Sleep(100 / speed);

            SliderPos = SliderPos + 1;
        }
        // todo finish this function
    }
    private bool CanVSMPlayer()
    {
        return Names.Count > 0;
    }
    public ICommand Play
    {
        get
        {
            return new RelayCommand(() =>
            {
                IAsyncResult result = new Action(VSMPlayer).BeginInvoke((c =>
                {
                    //operation completed
                }), null);

            }, CanVSMPlayer);
        }
    }
    public ObservableCollection<string> Names
    {
        get
        {
            return new ObservableCollection<string>() { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
        }

    }

    int _sliderPos = 0;
    public int SliderPos
    {
        get { return _sliderPos; }
        set
        {
            _sliderPos = value;
            RaisePropertyChanged("SliderPos");
            RaisePropertyChanged("ActiveName");
        }
    }

    public string ActiveName
    {
        get
        {
            if (SliderPos < Names.Count)
            {
                return Names[SliderPos];
            }
            else
            {
                return Names[0];
            }
        }
    }

    void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged == null)
            return;
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

View:

<StackPanel>
    <TextBlock Text="{Binding ActiveName}"/>
    <Slider Value="{Binding SliderPos}" Maximum="{Binding SliderLength}"/>
    <Button Content="Play" Command="{Binding Play}"/>
</StackPanel>
...