Где я могу разместить логику для моей ICommand?

Я недавно начал использовать шаблон MVVM в Silverlight, и я не уверен, правильно ли я его использую.

графический интерфейс пользователя

В настоящее время у меня есть MainView, который имеет комбобокс секторов фондового рынка. Когда пользователь выбирает сектор (например, ENERGY) и нажимает кнопку "Добавить", список акций для этого сектора отображается в списке. Рядом с каждой акцией в списке находится кнопка удаления, которая позволяет удалить отдельную акцию из списка.

Я реализовал следующие ViewModels. (Ниже приведено только указание кода)

public class MainViewModel
{
  public SectorViewModel CurrentSector 
  {
     get;
     set;
  }

  public string SelectedSector 
  {
     get;
     set;
  }


  public void AddSectorClickedCommand()
  {
     CurrentSector = new SectorViewModel(SelectedSector);
  }

}

public class SectorViewModel
{
     public ObservableCollection<StockViewModel>  Stocks = new ObservableCollection<StockViewModel>();

     public SectorViewModel(string sector)
     {
        List<Stocks> stocklist = StockProvider.GetStocks(sector);
        for each (var s in stocklist)
        {
            StockViewModel svm = new StockViewModel(s);
            svm.Remove+= { //Remove svm from Stocks collection logic
            Stocks.add(svm);

        }
     }
}

Мой вопрос в какой viewmodel лучше всего добавить реализацию кода для кнопки "Удалить" каждой строки в списке?? Кнопка Удалить должна удалить StockViewModel из коллекции SectorViewModel.Stocks.

В настоящее время я добавил метод RemoveClicked в StockViewModel(как показано выше). Этот код запускает событие обратно в SectorViewModel, а метод Remove Stock объекта SectorViewModel удаляет StockViewModel из коллекции Stock.

Есть ли лучший способ реализовать эту функцию удаления? Я новичок в MVVM и не уверен, что это лучший подход для разработки этой функциональности, поскольку SectorViewModel должен регистрироваться на события StockViewModel.

1 ответ

Лично мне не нравятся события, потому что вы должны отписаться от них, а также они могут быть использованы там, где это не подходит.

Я бы использовал параметр конструктора для обработки команды удаления, что-то вроде этого:

public class StockViewModel
{
    public StockViewModel(Stock stock, Action<StockViewModel> removeCommandAction)
    {
        //...
        this.RemoveCommand = new DelegateCommand(() => removeCommandAction(this));
    }
}

public class SectorViewModel
{
    public SectorViewModel()
    {
        //...
        StockViewModel svm = new StockViewModel(s, this.RemoveStock);
        Stocks.add(svm);
    }

    private void RemoveStock(StockViewModel stock)
    {
        //...
    }
}

Другой подход заключается в использовании какого-либо шаблона EventAggregator, например, Messenger класс из легкого инструментария MVVM. Но я думаю, что это излишнее решение для такой простой задачи:

public StockViewModel(Stock stock, IMessenger messenger)
{
    //...
    this.RemoveCommand = new DelegateCommand(() => 
        messenger.Send(new NotificationMessage<StockViewModel>(this, RemoveItemNotification)));
}

public SectorViewModel(IMessenger messenger)
{
    //...
    messenger.Register<NotificationMessage<StockViewModel>>(this, msg =>
    {
        if (msg.Notification == StockViewModel.RemoveItemNotification)
        {
            this.RemoveStock(msg.Content);
        }
    }
}

Также я слышал, что Silverlight 5 поддерживает привязку к относительному источнику. Так что есть 3-й подход. Я не уверен, работает ли этот пример, но, по крайней мере, он должен:

<Button Content="Remove" 
    Command="{Binding DataContext.RemoveCommand RelativeSource={RelativeSource AncestorType=ListBox}}"
    CommandParameter="{Binding}" />
public class SectorViewModel
{
    public SectorViewModel()
    {
        this.RemoveCommand = new DelegateCommand(obj => this.RemoveStock((StockViewModel)obj));
    }

    public ICommand RemoveCommand { get; set; }
}

Последний пример, кстати, наиболее предпочтителен и используется в приложениях WPF, потому что WPF всегда имел привязку RelativeSource.

Другие вопросы по тегам