Как можно использовать Command в привязке данных в WPF?

Как превратить метод Play() из ViewModel в Command и связать его с кнопкой для выполнения действия при нажатии?
  • 10 июня 2024 г. 22:51
Ответы на вопрос 2
Чтобы использовать Command в привязке данных в WPF, необходимо создать класс, который будет реализовывать интерфейс ICommand. Вот пример реализации класса команды:

```csharp
public class RelayCommand : ICommand
{
    private Action _execute;
    private Func<bool> _canExecute;

    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return _canExecute == null || _canExecute();
    }

    public void Execute(object parameter)
    {
        _execute();
    }
}
```

Затем нужно добавить свойство типа RelayCommand в ваш ViewModel и вызывать методы Play() через эту команду. Например, в ViewModel:

```csharp
public class MyViewModel
{
    public RelayCommand PlayCommand { get; set; }

    public MyViewModel()
    {
        PlayCommand = new RelayCommand(Play);
    }

    public void Play()
    {
        // Ваш код для выполнения действий
    }
}
```

Наконец, свяжите кнопку в XAML с командой из вашего ViewModel:

```xml
<Button Content="Play" Command="{Binding PlayCommand}" />
```

Теперь при нажатии на кнопку будет выполняться метод Play() из вашего ViewModel через команду.
Ну, если прям на чистом WPF, без всякого упрощающего жизнь обвеса типа ReactiveUI, то как-то так. 

Код вьюмодельки.
internal class MainViewModel
{
	private sealed class PlayCmd(MainViewModel mainViewModel) : ICommand
	{
		/// <summary>
		/// Можно ли вызвать команду? Влияет на доступность привязанных к команде контролов, например кнопки
		/// </summary>
		public bool CanExecute(object? parameter) =>
			// команду Play можно вызвать только если мы ещё не начали проигрывание
			!mainViewModel.isPlaying;

		/// <summary>
		/// Ивент, нужный чтобы уведомить об изменении значения свойства CanExecute
		/// </summary>
		public event EventHandler? CanExecuteChanged;

		public void Execute(object? parameter)
		{
			// вызываем метод у вьюмодели
			mainViewModel.Play();
			// дёргаем событие, чтобы сообщить всем, кто привязался к команде,
			// что её статус "можно исполнить" изменился
			// если этого не сделать, то кнопка НЕ задизаблится (хотя CanExecute уже возвращает false)
			this.OnCanExecuteChanged();
		}

		private void OnCanExecuteChanged() =>
			this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
	}

	private readonly PlayCmd playCommand;
	private bool isPlaying = false;

	public MainViewModel()
	{
		this.playCommand = new(this);
	}

	public ICommand PlayCommand => this.playCommand;

	public void Play()
	{
		//Player.Play();
		this.isPlaying = true;
	}
}

Код вьюхи.
<Window x:Class="Miramax.MainWindow"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
		xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		xmlns:local="clr-namespace:Miramax"
		mc:Ignorable="d"
		Title="MainWindow" Height="450" Width="800">
	<Window.DataContext>
		<local:MainViewModel />
	</Window.DataContext>
	<Grid>
		<Button Command="{Binding PlayCommand}">Click</Button>
	</Grid>
</Window>
Похожие вопросы