Команда может принимать один параметр типа 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
, которое устанавливает условие выполнения команды: