Удаление элементов в MVVM: реализация списка Title с крестиками в WPF ListView

WPF ListView - это мощный контрол, который позволяет отображать списки данных в приложении. Одним из часто используемых сценариев является отображение списка элементов с возможностью удаления каждого элемента. В данной статье мы рассмотрим, как реализовать такой функционал с использованием паттерна проектирования MVVM.

Создание модели данных

Первым шагом является создание модели данных, которая представляет элементы списка. В нашем примере мы будем использовать простую модель, которая содержит только одно свойство - название элемента. Создайте новый класс "TitleModel" и добавьте в него следующий код:

public class TitleModel
{
   public string Title { get; set; }
}

Создание ViewModel

Следующим шагом является создание ViewModel, которая будет управлять отображением списка элементов и его функциональностью. Создайте новый класс "TitleListViewModel" и добавьте в него следующий код:

public class TitleListViewModel : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

   private ObservableCollection<TitleModel> _titles;

   public ObservableCollection<TitleModel> Titles
   {
       get { return _titles; }
       set
       {
           _titles = value;
           OnPropertyChanged("Titles");
       }
   }

   public TitleListViewModel()
   {
       Titles = new ObservableCollection<TitleModel>
       {
           new TitleModel { Title = "Title 1" },
           new TitleModel { Title = "Title 2" },
           new TitleModel { Title = "Title 3" },
           new TitleModel { Title = "Title 4" },
           new TitleModel { Title = "Title 5" }
       };
   }

   protected void OnPropertyChanged(string propertyName)
   {
       if (PropertyChanged != null)
       {
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
       }
   }
}

Здесь мы создаем ObservableCollection "Titles", который содержит объекты "TitleModel". Мы также инициализируем его в конструкторе ViewModel. Этот список будет использоваться для отображения нашего списка элементов.

Создание представления

Теперь мы можем создать представление, которое отобразит наш список элементов и предоставит функциональность удаления каждого элемента. Для этого мы будем использовать контрол ListView и добавим к нему стиль, который будет отображать крестик для каждого элемента. Создайте новый файл "TitleListView.xaml" и добавьте в него следующий код:

<ListView ItemsSource="{Binding Titles}">
   <ListView.ItemTemplate>
       <DataTemplate>
           <Grid>
               <Grid.ColumnDefinitions>
                   <ColumnDefinition Width="*" />
                   <ColumnDefinition Width="20" />
               </Grid.ColumnDefinitions>
               <TextBlock Text="{Binding Title}" />
               <Button Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource AncestorType=ListView}}"
                       CommandParameter="{Binding}" Grid.Column="1" Content="X" />
           </Grid>
       </DataTemplate>
   </ListView.ItemTemplate>
</ListView>

Здесь мы связываем "ItemsSource" ListView с "Titles" ViewModel, которую мы создали ранее. Мы также добавляем стиль к каждому элементу списка, который отображает крестик для удаления каждого элемента. Кнопка "X" имеет привязку команды к "DeleteCommand" ViewModel, которую мы реализуем следующим шагом.

Реализация команды удаления

Создайте новый класс "DeleteCommand" и добавьте в него следующий код:

public class DeleteCommand : ICommand
{
   public event EventHandler CanExecuteChanged;

   private readonly Action<TitleModel> _executeMethod;
   private readonly Func<TitleModel, bool> _canExecuteMethod;

   public DeleteCommand(Action<TitleModel> executeMethod, Func<TitleModel, bool> canExecuteMethod = null)
   {
       _executeMethod = executeMethod;
       _canExecuteMethod = canExecuteMethod;
   }

   public void Execute(object parameter)
   {
       _executeMethod((TitleModel)parameter);
   }

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

   public void OnCanExecuteChanged()
   {
       if (CanExecuteChanged != null)
       {
           CanExecuteChanged(this, EventArgs.Empty);
       }
   }
}

Этот класс представляет команду удаления элемента. Он принимает два параметра: "executeMethod" и "canExecuteMethod". "executeMethod" - это метод, который будет вызываться при выполнении команды удаления. "canExecuteMethod" - это метод, который определяет, можно ли вызывать "executeMethod". Если "canExecuteMethod" возвращает "false", то кнопка удаления будет отключена.

Теперь мы можем добавить свойство "DeleteCommand" к нашей ViewModel, которое будет содержать экземпляр "DeleteCommand". Добавьте следующий код в класс "TitleListViewModel":

public ICommand DeleteCommand { get; }

public TitleListViewModel()
{
   Titles = new ObservableCollection<TitleModel>
   {
       new TitleModel { Title = "Title 1" },
       new TitleModel { Title = "Title 2" },
       new TitleModel { Title = "Title 3" },
       new TitleModel { Title = "Title 4" },
       new TitleModel { Title = "Title 5" }
   };

   DeleteCommand = new DeleteCommand(OnDelete, CanDelete);
}

private bool CanDelete(TitleModel title)
{
   return true;
}

private void OnDelete(TitleModel title)
{
   Titles.Remove(title);
}

Мы создаем "DeleteCommand" в конструкторе и добавляем его в свойство "DeleteCommand". Мы также определяем методы "CanDelete" и "OnDelete", которые будут вызываться при выполнении команды удаления.

Итоги

Теперь мы можем запустить наше приложение и убедиться, что у нас есть список элементов с крестиком для удаления каждого элемента. Когда пользователь нажимает на крестик, элемент списка удаляется. Мы использовали паттерн проектирования MVVM для реализации этой функциональности, что позволяет нам улучшить разделение между логикой приложения и представлением.

Смотри также: