2016-04-22 7 views
2

У меня следующая ситуация:MVVM Master Detail с WPF TreeView

Просмотров:

  • EbayCategoriesView (с TreeView)
  • MaintainEbayCategoryView (с полями категории детализации)

ViewModels:

  • EbayAllCategoriesViewModel (с ObservableCollection EbayCategoryViewModel под названием EbayCategories).
  • EbayCategoryViewModel (с Категория Properties)

EbayCategoryViewModel имеет общественную собственность, то есть список, который называется ChildrenCategories. TreeView привязан к ObservableCollection, и каждый узел TreeView представляет собой HyperLink. Я бы хотел, чтобы при нажатии на гиперссылку система открыла MaintainEbayCategoryView и загрузила ее данными EbayCategoryViewModel.

Я использую шаблон MVVM; EbayCategoryViewModel принимает входной параметр ICommand в конструкторе. Когда я заселить ObservableCollection в EbayAllCategoriesViewModel, я создаю новый RelayCommand для каждого элемента коллекции и передать функцию, которая должна быть выполнена:

hierarchyList.Add(new EbayCategoryViewModel(
        item.EbayCategoryName, 
        item.EbayCategoryID, 
        FillRecursive(flatList, item.EbayCategoryID, item.EbayCategoryName), 
        parentCategoryName, 
        item.EbayOrder, 
        new RelayCommand(cmd => this.LoadCategoryDetails()) 
         )); 

Моя проблема сейчас является то, что в LoadCategoryDetails() метод в EbayAllCategoriesViewModel У меня нет ссылки на узел дерева EbayCategoryViewModel, который был нажат (SelectedItem в TreeView не является общедоступным, а также я не уверен, что он содержит щелчок элемента ...).

Даже если я нашел обходное решение, я хотел бы понять, что является правильным подходом к решению моей проблемы, учитывая шаблон MVVM. Поскольку у меня уже есть все поля категорий в EbayCategoryViewModel, я мог бы получить доступ к текущему объекту EbayCategoryViewModel, который был бы нажат, не получив снова доступ к моему источнику данных.

Заранее благодарим за любые предложения.

ответ

2

Почему вы не передаете экземпляр EbayCategoryViewModel в качестве параметра в обработчике команд. Таким образом, у вас будет экземпляр виртуальной машины.

hierarchyList.Add(new EbayCategoryViewModel(
        item.EbayCategoryName, 
        item.EbayCategoryID, 
        FillRecursive(flatList, item.EbayCategoryID, item.EbayCategoryName), 
        parentCategoryName, 
        item.EbayOrder, 
        new RelayCommand(param=> this.LoadCategoryDetails(param)) 
         )); 

и где вы являются обязательными для вашей команды вы можете установить CommandParameter вернуть DataContext т.е. экземпляр EbayCategoryViewModel CommandParameter="{Binding}"

+0

Спасибо Nitin, это выглядит более элегантным решением, оно отлично работает. – Alessandro

2

@ ответ Нитин является правильным, но вот еще один способ, это еще проще:

var ecvm = new EbayCategoryViewModel(
     item.EbayCategoryName, 
     item.EbayCategoryID, 
     FillRecursive(flatList, item.EbayCategoryID, item.EbayCategoryName), 
     parentCategoryName, 
     item.EbayOrder, 
     null); 

// Guessing at the name of your command property here 
ecvm.LoadCategoryDetailsCommand 
    = new RelayCommand(cmd => this.LoadCategoryDetails(ecvm)); 

hierarchyList.Add(ecvm); 

И в другом месте ...

public void LoadCategoryDetails(EbayCategoryViewModel vm) 
{ 
    // Do stuff 
} 

Я делаю лично предпочитаю свой ответ Нитину из-за семантики этой конкретной команды: он говорит, что категория загружает свои собственные детали.Я не думаю, что есть случай, когда вы скажете Category A рассказать категории B, чтобы загрузить его, поэтому я не вижу необходимости давать команде параметр. В каждом случае, когда вы используете его, вы действительно говорите «Дорогая категория, пожалуйста, загрузите свои данные, и, кстати, это тот, кто вы есть». Необходимость этой избыточности объясняется довольно произвольной детализацией реализации в вашей модели viewmodel. Это не разрушительно, но требует дополнительных усилий со стороны потребителей ваших классов, не добавляя ничего.

Если это была команда для родителя, семантика будет «сообщать определенному ребенку о загрузке своих деталей», а затем параметр будет правильным способом рассказать ему, какой ребенок. И это точная семантика метода родителя LoadCategoryDetails(ecvm), так как мы с Нитином предложили вам переписать его.

Ответ Нитина - это традиционное профессиональное профессиональное программирование WPF. Это правильно по любым стандартам. Но мой предпочтение было бы скрыть передачу этого параметра, когда метод вызывается из этой команды на EbayCategoryViewModel. Это не очень сильное предпочтение, чтобы оправдать количество прозы, которую я только что сбрасывал, но я думал, что объясню, почему я добавил ненужный ответ (lolseewhatididthere?).

+0

Я оценил ваше предложение, оно также отлично работает. Я предпочитаю решение Nitin, поскольку он более изящный и лаконичный. – Alessandro

+0

@Alessandro Нет проблем - его ответ правильный, стандартный WPF. Он тоже занял первое место! Я обновляю свой ответ каким-то воздушным богословским бессвязным движением. –