Передача параметров команде

Последнее обновление: 18.10.2016

Команда может принимать один параметр типа object, вместо которого мы можем передать любой объект или даже коллекцию объектов. Например, продолжим работу с проектом из прошлой темы и добавим в него удаление объекта из списка. Для этого изменим код ApplicationViewModel следующим образом:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;

namespace MVVM
{
    public class ApplicationViewModel : INotifyPropertyChanged
    {
        private Phone selectedPhone;
        public ObservableCollection<Phone> Phones { get; set; }

        // команда добавления нового объекта
        private RelayCommand addCommand;
        public RelayCommand AddCommand
        {
            get
            {
                return addCommand ??
                  (addCommand = new RelayCommand(obj =>
                  {
                      Phone phone = new Phone();
                      Phones.Insert(0, phone);
                      SelectedPhone = phone;
                  }));
            }
        }
		
		// команда удаления
        private RelayCommand removeCommand;
        public RelayCommand RemoveCommand
        {
            get
            {
                return removeCommand ??
                  (removeCommand = new RelayCommand(obj =>
                  {
                      Phone phone = obj as Phone;
                      if (phone != null)
                      {
                          Phones.Remove(phone);
                      }
                  },
                 (obj) => Phones.Count > 0));
            }
        }

        public Phone SelectedPhone
        {
            get { return selectedPhone; }
            set
            {
                selectedPhone = value;
                OnPropertyChanged("SelectedPhone");
            }
        }

        public ApplicationViewModel()
        {
            Phones = new ObservableCollection<Phone>
            {
                new Phone { Title="iPhone 7", Company="Apple", Price=56000 },
                new Phone {Title="Galaxy S7 Edge", Company="Samsung", Price =60000 },
                new Phone {Title="Elite x3", Company="HP", Price=56000 },
                new Phone {Title="Mi5S", Company="Xiaomi", Price=35000 }
            };
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName]string prop = "")
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }
}

Здесь добавлена команда удаления объекта из списка:

private RelayCommand removeCommand;
public RelayCommand RemoveCommand
{
    get
    {
        return removeCommand ??
            (removeCommand = new RelayCommand(obj =>
            {
                Phone phone = obj as Phone;
                if (phone != null)
                {
                    Phones.Remove(phone);
                }
            },
            (obj) => Phones.Count > 0));
    }
}

Здесь предполагается, что в качестве параметра в команду будет передаваться удаляемый объект Phone. Ну а поскольку в реальности параметр имеет тип object, то его еще надо привести к типу Phone.

Стоит отметить, что в качестве второго параметра в конструктор RelayCommand передается делегат Func<obj, bool>, который позволяет указать условие, при котором будет доступна команда. В нашем случае нет смысла удалять элементы из списка, если в списке нет элементов.

И также изменим код MainWindow.xaml:

<Window x:Class="MVVM.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:MVVM"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="FontSize" Value="14" />
        </Style>
        <Style TargetType="TextBox">
            <Setter Property="FontSize" Value="14" />
        </Style>
        <Style TargetType="Button">
            <Setter Property="Width" Value="40" />
            <Setter Property="Margin" Value="5" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="0.8*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="0.2*" />
        </Grid.RowDefinitions>
        <ListBox Grid.Column="0" ItemsSource="{Binding Phones}"
                 SelectedItem="{Binding SelectedPhone}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="5">
                        <TextBlock FontSize="18" Text="{Binding Path=Title}" />
                        <TextBlock Text="{Binding Path=Company}" />
                        <TextBlock Text="{Binding Path=Price}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button Command="{Binding AddCommand}">+</Button>
            <Button Command="{Binding RemoveCommand}" 
                    CommandParameter="{Binding SelectedPhone}">-</Button>
        </StackPanel>

        <StackPanel Grid.Column="1" DataContext="{Binding SelectedPhone}">
            <TextBlock Text="Выбранный элемент"  />
            <TextBlock Text="Модель" />
            <TextBox Text="{Binding Title, UpdateSourceTrigger=PropertyChanged}" />
            <TextBlock Text="Производитель" />
            <TextBox Text="{Binding Company, UpdateSourceTrigger=PropertyChanged}" />
            <TextBlock Text="Цена" />
            <TextBox Text="{Binding Price, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
    </Grid>
</Window>

Здесь добавлена кнопка удаления. Для нее установлена привязка к команде RemoveCommand. Кроме того, с помощью атрибута CommandParameter кнопка устанавливает объект, который передается команде. В данном случае это объект из свойства SelectedPhone:

<Button Command="{Binding RemoveCommand}" 
		CommandParameter="{Binding SelectedPhone}">-</Button>

Теперь мы сможем удалять элементы из списка. Причем, если в списке не будет элементов, то кнопка будет недоступна, благодаря тому, что в конструктор RelayCommand выше было передано выражение (obj) => Phones.Count > 0, которое устанавливает условие выполнения команды:

Параметры команд в MVVM в WPF
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850