Как реализовать элементы меню, зависящие от текущего выбора, в приложении, подобном WPF MVVM explorer

StackOverflow https://stackoverflow.com/questions/2525759

  •  22-09-2019
  •  | 
  •  

Вопрос

Я новичок в WPF и MVVM, и я работаю над приложением, использующим оба.Приложение похоже на проводник Windows, поэтому рассмотрим приложение с главным окном с меню (ShellViewModel), древовидным элементом управления (TreeViewModel) и элементом управления списком (ListViewModel).Я хочу реализовать такие пункты меню, как Правка -> Удалить, которые удаляют выбранный в данный момент элемент (который может быть в дереве или в списке).

Я использую RelayCommand Джоша Смита, и привязать menuitem к DeleteItemCommand в ShellViewModel несложно.Похоже, однако, что реализация DeleteItemCommand требует некоторой довольно тесной связи между ShellViewModel и двумя дочерними моделями представления (TreeViewModel и ListViewModel), чтобы отслеживать фокус / выбор и направлять действие соответствующему дочернему элементу для реализации.Мне это кажется неправильным и заставляет меня думать, что я что-то упускаю.

Написание менеджера фокуса и / или менеджера выбора для ведения бухгалтерского учета не кажется слишком сложным, и его можно было бы выполнить без объединения классов вместе.Оконная система уже отслеживает, на каком представлении находится фокус, и кажется, что я бы дублировал код.

В чем я не уверен, так это в том, как бы я перенаправил команду из ShellViewModel либо в ListViewModel, либо в TreeViewModel, чтобы выполнить фактическую работу, не внося беспорядок в код.Когда-нибудь приложение будет расширено, чтобы включать в себя более двух дочерних элементов, и я хочу, чтобы оболочка была как можно более неосведомлена о дочерних элементах, чтобы сделать это расширение как можно более безболезненным.

Рассматриваем некоторые примеры приложений WPF / MVVM (зашифрованный текст Карла Шиффлетта, Демо-версия MVVM Джоша Смита, и т.д.), я не видел никакого кода, который делает это (или я этого не понял).

Независимо от того, считаете ли вы мой подход некорректным или я просто упускаю небольшой нюанс, пожалуйста, поделитесь своими мыслями и помогите мне вернуться в нужное русло.Спасибо!

Это было полезно?

Решение

Существуют некоторые неотъемлемые проблемы с реализацией MVVM Джоша Смита.Взгляните на сообщение Уорда Белла на эту тему: http://neverindoubtnet.blogspot.com/2010/03/mvvm-josh-smiths-way.html.Возможно, вы захотите взглянуть на некоторые альтернативные фреймворки MVVM, такие как Caliburn, которые используют подход ViewModel first и разрывают эту связь.

Другие советы

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

Я думаю, что был бы склонен отказаться от всех различных архитектурных вариаций MVVM и примеров приложений и просто использовать старый добрый OOD.Почему бы не иметь какой-нибудь базовый класс ViewModel (т. Е. DetailsViewModelBase) для TreeViewVm и ListViewVm.Поместите туда DeleteCommand с методами CanDelete и Delete, которые имеют столько реализаций, сколько разделяют подклассы (или абстрактные, если таковых нет), а также SelectedItem .Затем привяжите SelectedItem к элементам управления, аналогичным приведенному ниже xaml:

    <ListView AlternationCount="2" MinHeight="250" MaxHeight="400" 
          ItemsSource="{Binding Projects.View}" 
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedProject, Mode=TwoWay}"
          behaviors:SelectionBehavior.DoubleClickCommand="{Binding PickCommand}"
          ItemContainerStyle="{StaticResource listingRowStyle}"
                      >

Привязки клавиш выбираются как SelectedItem и синхронизируются с CurrentItem.

HTH,
Беррил

Я нашел запись в блоге автор: Кент Бугарт, который описывает то, что он называет ActiveAwareCommand.Кажется, это делает то, что я искал, хотя я еще не пробовал.В комментарии к сообщению упоминается IActiveAware от Prism как имеющее аналогичное поведение.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top