Как ICommand WPF может быть представлен в виде простой строки, которая слабо связана с пользовательским интерфейсом?

#c# #.net #wpf #cab #prism

#c# #.net #wpf #cab #prism

Вопрос:

В прошлом с Windows forms я использовал части составного блока приложения пользовательского интерфейса в сочетании с некоторой централизованной обработкой команд и правилами безопасности для достижения слабо связанного подхода MVC к привязке интерфейса к выполнению команд. Я хотел бы знать, как это сделать в WPF с помощью ICommand или RoutedCommand ?

Мои предыдущие реализации состояли бы из следующего:

  1. Свяжите каждую команду со строкой в виде URI на основе REST, такого как cmd://myapp/orders/create
  2. Напишите пользовательский ICommand (не путать с WPF), который обрабатывал бы выполнение команды, у него просто были Execute() метод и CanExecute свойство вместе с Undo() и `CanUndo, если он поддерживал возможности отмены.
  3. Объекты интерфейса, необходимые для выполнения команды, тогда будут слабо связаны
    1. Обработка Click события, которое не будет знать, какую команду выполнять, а просто передаст централизованное CommandManager имя команды для выполнения.
    2. Как только CommandManager получит выполнение команды, он просто использует возможности «многие ко многим» в блоке приложения составного пользовательского интерфейса для вызова события command.
    3. Перед фактическим выполнением команды диспетчер команд выполняет проверку безопасности, которая в основном заключается в том, чтобы спросить меня SecurityManager если вошедший в систему пользователь может выполнить командную строку, правила безопасности загружаются через XML-файл и состоят из шаблонов, таких как ‘cmd://myapp /finance /*’
    4. Как только событие command вызывается при получении команды, оно будет отвечать за определение состояния и контекста с помощью зависимостей, основанных на модели представления.

Мне нравится этот подход, потому что он прост в написании, слабо связан, а командам разрешено получать состояние интерфейса только через view-model, которые находятся через DI. Блок приложения Composite UI также упростил для меня «включить / отключить / недоступно»

Аналогичным образом я могу воспроизвести почти все, кроме ‘строкового’ представления команды, это жизненно важно, поскольку контекст безопасности, который мы написали, может заблокировать целый раздел, обрабатывая шаблоны команд, такие как cmd://myapp/finance/* , мы также можем затем позволить пользователю определять привязки ярлыков команд и т.д.

Ключевыми требованиями для меня являются:

  1. Команды должны быть представлены в виде строк, это абсолютное требование.
  2. Должна иметь возможность указывать, что командная строка «включена», «отключена» и «Недоступна» (что означает, что она должна быть скрыта в пользовательском интерфейсе.
  3. Элементы интерфейса не должны знать, как обрабатывать команду или как предоставлять контекст, за это отвечают сами команды через обнаруживаемые ими объекты view-model.
  4. Выполнение команды должно быть централизованным, т. Е. мне нужен объект диспетчера команд, который обрабатывает вызов события для выполнения команды наряду с обслуживанием стека отмены.

РЕДАКТИРОВАТЬ: я только что подумал о том, как обеспечить привязку команды с помощью экспорта MEF для предоставления пользовательских метаданных, предоставляющих имя команды, ImportMany может затем загрузить их в my CommandManager , теперь это просто вопрос

  1. Сообщать элементам интерфейса a Command String , которые они вызывают, и;
  2. Разрешение изменять состояние командных строк (включено / отключено / недоступно).

ПРАВКА 2: я думал о решении, в котором my CommandManager принимает Register(Control, String) способ, при котором можно зарегистрировать элемент управления с помощью командной строки, диспетчер команд может затем обрабатывать включение / выключение / скрытие элементов пользовательского интерфейса по мере изменения их состояния и привязывать к ним события, это обеспечивает гораздо большую гибкость и развязку, а также позволяет настраивать пользователя (перемещение меню, конфигурации кнопок, сочетания клавиш и т.д.). Это вызывает беспокойство, хотя я не использую ни одной точки ICommand средства, предоставляемого WPF, в конце концов, я не думаю, что это имеет значение, но я хотел бы знать, можно ли использовать средство командования, предоставляемое WPF, таким простым способом, как я определил. Другим преимуществом является то, что этот метод не зависит от WPF и может использоваться где угодно.

Ответ №1:

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

но конкретно для вашей проблемы я просто хотел сказать: если вы полностью пропускаете ICommand, вы определенно теряете то, что wpf делает за кулисами. Например: метод ICommands CanExecute. WPFs commandmanager запрашивает этот метод в зависимости от пользовательского ввода в ваше приложение. В противном случае вам пришлось бы самостоятельно обрабатывать распространение изменений состояния «включено» / «отключено» / «недоступно» и реализовывать свою собственную логику для включения / выключения кнопки.

также команды можно использовать не только для событий щелчка.

и последнее: команды могут выполняться без WPF — это просто интерфейс, и он явно не привязан к wpf

Комментарии:

1. Спасибо Маркусу. Я думаю, что происходит то, что я пытаюсь найти способ сделать ICommand гибким, кажется, что это слишком тесно связано с реализацией команды. Наиболее важная концепция заключается в том, чтобы имена команд или ключи были представлены в виде строк, чтобы позволить модели безопасности определять, может ли команда быть выполнена из контекста безопасности. Мне кажется, что модель, предоставляемая WPF, больше настроена на действия, действующие на элементы интерфейса, а не на действия, действующие на домены.