Привет.
Как принято в концепции MVVM управлять состояниями доступности выполнения команд в нескольких моделях представлений(ViewModel)?
Допустим есть задача реализовать каркас приложения по типу медиаплеера в рамках подхода MVVM. Понятно, что кнопки: "Старт", "Стоп", "Пауза", и т.д. это часть т.н. "машины состояний".
Если представить, что они находятся в различных ViewModel, как тогда реализовать логику переключения(доступности) этих кнопок-команд?
Если не затруднит, прошу, привести маленький пример. Спасибо.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, DmitryB, Вы писали:
DB>Привет.
DB>Как принято в концепции MVVM управлять состояниями доступности выполнения команд в нескольких моделях представлений(ViewModel)?
DB>Допустим есть задача реализовать каркас приложения по типу медиаплеера в рамках подхода MVVM. Понятно, что кнопки: "Старт", "Стоп", "Пауза", и т.д. это часть т.н. "машины состояний".
DB>Если представить, что они находятся в различных ViewModel, как тогда реализовать логику переключения(доступности) этих кнопок-команд?
DB>Если не затруднит, прошу, привести маленький пример. Спасибо.
Ну значит, нужно выделить плеер в отдельный класс, все модели представлений будут обладать его экземпляром. Дальше им остаётся подписаться на события о его изменениях и менять доступность своих команд. Кроме того, в WPF и без того состояние команд (ICommand.CanExecute) опрашивается достаточно часто.
В рамках
моего подхода это будет выглядеть примерно так:
| | PlayerViewModel.cs |
| | public abstract class MediaPlayer
{
public event EventHandler StateChanged;
public bool CanPlay { get; }
public bool CanPause { get; }
public bool CanStop { get; }
public abstract void Play();
public abstract void Pause();
public abstract void Stop();
}
public class PlayerViewModel : ViewModel
{
private readonly MediaPlayer mediaPlayer;
public PlayerViewModel(MediaPlayer mediaPlayer)
{
this.mediaPlayer = mediaPlayer;
this.mediaPlayer.StateChanged += HandleMediaPlayerStateChanged;
}
public ICommand PlayCommand { get { return GetCommand(this.mediaPlayer.Play, () => this.mediaPlayer.CanPlay); } }
public ICommand PauseCommand { get { return GetCommand(this.mediaPlayer.Pause, () => this.mediaPlayer.CanPause); } }
public ICommand StopCommand { get { return GetCommand(this.mediaPlayer.Stop, () => this.mediaPlayer.CanStop); } }
private void HandleMediaPlayerStateChanged(object sender, EventArgs e)
{
// Этот вызов заставит WPF опросить команды о их состоянии
this.CommandManager.InvalidateRequerySuggested();
}
protected override void DisposeManagedObjects()
{
// Не забываем отписаться от события, модель живёт обычно меньше, чем плеер.
this.mediaPlayer.StateChanged -= HandleMediaPlayerStateChanged;
}
}
|
| | |
Можно сделать несколько таких моделей и все они будут дружно реагировать на изменения состояния плеера.