Как обрабатывать выполнение и может выполнять условия в динамической кнопке в MVVM

2

У меня есть Button как аксессуар в моем TabControl, где находится 5 TabItem. Эта кнопка копирует другой объект, используемый в вкладках. Каждый TabItem имеет CustomView (где все его компоненты находятся, TextView, TextBox и т.д.). Я хочу иметь возможность реализовать другую функциональность для этой кнопки для каждой вкладки в одной команде, поэтому я внедрил общую команду копирования, которая проверяет текущий вкладка, чтобы увидеть, что мы в настоящее время находимся на какой вкладке, но теперь лучший способ справиться с моими не может выполнить условия без повторения моего случая переключения в методе "Условия"? Например, первая кнопка закладки не может быть выполнена (отключена), если ее объект равен нулю, вторая кнопка вкладки не может быть выполнена, когда ее объект имеет значение null.

  • Первая вкладка "Пользователи" имеет CustomerView

  • Вторая вкладка "Активность" имеет ActivityView

Код:

public RelayCommandWithCannotExecuteReason Copy
        {
            get
            {
                if (_copy == null)
                {
                    _copy = new RelayCommandWithCannotExecuteReason(
                        x =>
                        {

                            switch (SelectedTabIndex) {
                                case 1:
                                    Clipboard.SetData("First", object1);
                                    break;
                                case 2:

                                    Clipboard.SetData("Second", object2;
                                    break;
                            }

                        }, CanCopyConditions);
                }

                return _copy;
            }
        }
Теги:
wpf
mvvm

1 ответ

1
Лучший ответ

Почему бы не подклассифицировать тип RelayCommandWithCannotExecuteReason и создать выделенный объект команды? Вся эта логика содержится в команде, и все, что вы делаете, - это создание нескольких команд во всех ваших моделях.

Нет ничего плохого в создании выделенного командного класса для обработки специфической логики VM, что и делают программисты. Создание конкретной реализации абстракции, такой как ICommand или ваш RelayCommandWithCannotExecuteReason является SOLID.

public class CopyCommand : RelayCommandWithCannotExecuteReason
{
    ViewModel _vm;
    public CopyCommand( ViewModel vm)
    { 
       _vm = vm;
    }

    public void Execute(object parameter) 
    {
       switch (_vm.SelectedTabIndex) 
       {
         case 1:
            _vm.Clipboard.SetData("First", object1);
            break;
         case 2:
           _vm.Clipboard.SetData("Second", object2;
            break;
        }
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

}

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

 public CopyCommand Copy
 {
     get
     {
          if (_copy == null)
          {
             _copy = new CopyCommand(this);
          }
       return _copy;
      }

Или создайте экземпляр в конструкторе или инициализаторе основной виртуальной машины:

public ViewModel() //constructor
{
  _copy = new CopyCommand(this);

}

public CopyCommand Copy
{
     get
     {
         return _copy;
     }
}

Если у вас есть экземпляр модели просмотра для каждой вкладки, и вы хотите делегировать логику CanExecute() на "SelectedTab", вам понадобится что-то вроде этого:

Предположим, что все ваши модели представлений наследуют базовый класс, подобный этому:

public abstract class BaseTabViewModel
{
   public abstract bool CanCopy();
}

Затем вы будете подклассифицировать этот базовый класс в моделях просмотра вкладок. Вы бы выполнили абстракцию:

 public class Tab1ViewModel : BaseTabViewModel
 {
    …

 public override bool CanCopy(){
     //custom logic....
     return true; 
 }

Теперь нам нужно изменить порядок CopyCommand для ссылки на абстракцию, я изначально закодировал эту команду для использования ViewModel, теперь мы вместо этого определим тип как абстракцию. Поэтому измените класс ViewModel:

public class CopyCommand : RelayCommandWithCannotExecuteReason
{
    BaseTabViewModel _vm;
    public CopyCommand( BaseTabViewModel vm)
    { 
      _vm = vm;
    }

Теперь метод CanExecute() может вызвать соответствующую логику:

 public bool CanExecute(object parameter)
 {
      return _vm.CanCopy();
 }

Это работает только в том случае, если:

  • Все модели представления BaseTabViewModel являются экземплярами типа BaseTabViewModel.

Этот механизм намного более OO и более гибкий. Удачи.

  • 0
    Правда, я скорее использую меньше кода, но как я могу создать подкласс? А что вы имеете в виду с выделенным объектом команды?
  • 0
    Спасибо! Но у вкладок есть разные canexecute, как я могу добавить разные canexecute для каждого SelectedTabIndex, мне нужен регистр переключения внутри CanExecute (параметр объекта)?
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню