Как реализовать элементы меню, которые зависят от текущего выбора в приложении, похожем на проводник WPF MVVM - PullRequest
1 голос
/ 26 марта 2010

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

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

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

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

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

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

Ответы [ 3 ]

1 голос
/ 26 марта 2010

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

0 голосов
/ 27 марта 2010

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

0 голосов
/ 26 марта 2010

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

Я думаю, что был бы склонен отступить от всех различных архитектурных вариаций 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 и IsSynchronizedWithCurrentItem.

НТН,
Berryl

...