#wpf #mvvm #binding
#wpf #mvvm #привязка
Вопрос:
Допустим, у меня есть MasterViewModel
, которые содержат коллекцию ItemModel
. Если бы я хотел добавить новое ItemModel
в свою коллекцию, я бы вставил AddItemCommand
это MasterViewModel
. Теперь, если я хочу отобразить кнопку удаления рядом с каждым элементом, куда бы я поместил эту команду? Конечно, не в ItemModel
?!
Нужно ли мне создавать почти идентичную копию ItemModel
, например ItemViewModel
? Это звучало бы как большая работа по поддержке, но даже тогда я не уверен, как команда сможет удалить ItemModel
из коллекции.
Наиболее очевидный подход, по-видимому AddItemCommand
, и RemoveItemCommand
в MasterViewModel
, но как выполнить привязку данных в этом случае? DataContext элемента управления переключается на коллекцию, поэтому у меня больше нет видимости этих команд с уровня отдельного элемента. Я видел трюк с привязкой, который находит DataContext предка, но это выглядит настолько банально или, по крайней мере, не интуитивно понятно. Это предпочтительное решение или есть лучший подход?
Комментарии:
1. ViewModel предназначен для команд и другой работы по привязке между представлением и моделью… Модель — это бизнес-логика. Так что да, вам также нужен ItemViewModel
2. Обе команды должны быть реализованы в модели представления, в которой размещена коллекция, с которой должны работать команды. Вы не должны устанавливать коллекцию в качестве DataContext. Моделью представления должен быть DataContext. Вы просто привязываетесь к коллекции / свойству этой модели представления, настраивая
Binding.Path
. Если вам нужна помощь для исправления вашего DataContext, вы должны опубликовать свой текущий связанный код. Что касается команды удаления: это действительно зависит от того, какое представление данных вы используете.DataGrid
уже предоставляет команду удаления, что сэкономит вам некоторую работу.3. Обычно вам приходится привязывать модель
SelectedItem
представления. При нажатии на элемент или элемент управления, например, кнопку удаления внутри этого элемента, вы автоматически выбираете элемент. Команда удаления просто должна удалитьSelectedItem
из исходной коллекции. Вы действительно должны опубликовать связанный код.4. спасибо @BionicCode. Я бы предпочел использовать
CommandParameter="{Binding}"
вместо свойства SelectedItem5. Использование SelectedItem неверно, так как вы хотели бы иметь возможность удалять любой элемент без необходимости его выбора.
Ответ №1:
AddItemCommand
определенно принадлежит, MasterViewModel
поскольку это не может быть операцией над отдельным элементом.
RemoveItemCommand
также принадлежит, MasterViewModel
поскольку он обновит список элементов. Однако привязка не соответствует базовой методологии.
- Предполагая, что кнопка, которая запускает команду, является частью шаблона элемента, тогда вам нужно использовать относительную привязку для поиска команды (это то, что вы назвали «хакерским»?)
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.RemoveItemCommand}"
- Вы должны указать команде, какой элемент должен быть удален
CommandParameter="{Binding}"
и используйте этот параметр в методе, соответствующем вашей команде.
Комментарии:
1. Я писал то же самое. Заслуженный балл.
2. Да, это привязка, о которой я говорил. Вероятно, я должен сказать, неинтуитивный, а не хакерский, но я буду считать, что это правильный способ сделать это тогда. Спасибо.