Wpf UserControl и MVVM
Я думаю о написании WPF User Control для моего приложения. Я использую MVVM в своем приложении.
Пользовательский элемент управления может потребовать свойства зависимостей, которые могут быть установлены в моем родительском представлении. при использовании MVVM идея состоит в том, что Parent View в конечном итоге создаст привязку между UserControls
DP и VM с родительским представлением)
Dependency Properties
необходимо создать в классе View, поскольку VM не наследует от DependencyObject
. Это означает добавление кода в код XAML позади.
Мне было интересно, можете ли вы дать советы относительно того, как я должен создавать пользовательский элемент управления при разработке приложения WPF с использованием MVVM...
Ответы
Ответ 1
Случай 1: Если вы создаете этот элемент управления только для использования в приложении, вы можете создать для него ViewModel
, но вам не нужно создавать DP, ваша ViewModel
может просто реализовать INotifyPropertyChanged
а ваш родительский Vm может по-прежнему привязывать к ним.
В нашем случае для пользовательских элементов управления мы создали отдельную виртуальную ParentVM
и ее экземпляр присутствовал в ParentVM
. Таким образом, родительское представление будет иметь этот элемент управления и будет связывать UserControlVM
с этим UserControlVM
управления (ParentVM.UserControlVM
), а ParentVM.UserControlVM
позаботится о других привязках.
Случай 2. Если ваш элемент управления будет использоваться другими приложениями/разработчиками, и вы не хотите, чтобы он был простым, продолжайте создавать пользовательские элементы управления после реализации шаблона элемента управления. Таким образом, вы можете создавать элементы управления без внешнего вида и использовать dependency properties
. Более того, тот, кто использует этот элемент управления, не должен знать о связанной модели представления и использовать ее.
Некоторые из подобных вопросов/сообщений:
Вопрос о дизайне WPF (пользовательский элемент управления или mvvm): Вопрос о дизайне WPF (пользовательский элемент управления или mvvm)
Пользовательский элемент управления в WPF с использованием концепции MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/6293b176-e1e9-4610-af49-d53e6d294969/
Ад пользовательского управления WPF с MVVM и свойствами зависимости: ад пользовательского управления WPF с MVVM и свойствами зависимости
Ответ 2
A UserControl
является частью "View" в "MVVM", так же как элементы управления TextBox
или ListView
являются частью представления.
Если вы решите использовать MVVM для разработки своего UserControl
или записать его в QBASIC (не рекомендуется), он не нарушит шаблон MVVM для потребителей вашего UserControl
, если они могут делать все, что им нужно с помощью UserControl
, привязав к DependencyProperty
, выставленному на вашем UserControl
. т.е. ваш UserControl
должен показывать свойства, от которых он зависит (отсюда и название). Как только вы поймете, этот DependencyProperty
внезапно приобретет большой смысл, и вы хотите, чтобы они были полезны для измененных обработчиков событий и значений по умолчанию, которые вы указываете в своем конструкторе.
Если ваш UserControl
находится в другой сборке или нет, я не вижу, как это имеет значение.
Тем не менее многие будут выступать за то, чтобы вы создали свой UserControl
с использованием шаблона MVVM для всех хороших причин, связанных с MVVM, например. помогая другому разработчику смотреть на ваш код. Однако некоторые вещи просто невозможны и/или намного сложнее и менее эффективны, взломав XAML, чтобы сделать это - я не говорю о вашем садовом разнообразии. Добавить пользовательскую форму, но, например, UserControl
обрабатывает макет тысяч визуальных эффектов. Кроме того, поскольку вы работаете в своем представлении, вы НЕ хотите, чтобы ваши тэги UserControl
ViewModels смешивались с вашими приложениями!
В основном я говорю, что в MVVM хорошо использовать MVVM на вашем представлении!
Ответ 3
По сути, вместо привязки вашего текста данных UserControl к userControlViewModel лучше сделать это на первом дочернем элементе пользовательского элемента управления. Таким образом, все ссылки, которые вы делаете в элементе управления, будут связаны с userControlViewModel, но свойства зависимостей могут быть установлены из набора данных контекста, где вы хотите использовать свой UserControl.
Этот шаблон хорошо сработал для меня на вашем XAML UserControl:
<UserControl x:Class="Six_Barca_Main_Interface.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Six_Barca_Main_Interface"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="900" d:DesignWidth="900">
<DockPanel x:Name="rootDock" >
<TextBlock>{Binding SomethingInMyUserControlViewModel}</TabControl>
</DockPanel>
</UserControl>
Тогда на код позади:
public partial class MyUserControl : UserControl
{
UserControlViewModel _vm;
public MyUserControl()
{
InitializeComponent();
//internal viewModel set to the first child of MyUserControl
rootDock.DataContext = new UserControlViewModel();
_vm = (UserControlViewModel)rootDock.DataContext;
//sets control to be able to use the viewmodel elements
}
#region Dependency properties
public string textSetFromApplication
{
get{return (string)GetValue(textSetFromApplicationProperty);}
set{SetValue(textSetFromApplicationProperty, value);}
}
public static readonly DependencyProperty textSetFromApplicationProperty = DependencyProperty.Register("textSetFromApplication", typeof(string), typeof(MyUserControl), new PropertyMetadata(null, OnDependencyPropertyChanged));
private static void OnDependencyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((MyUserControl)d)._vm.SomethingInMyUserControlViewModel =
e.NewValue as string;
}
#endregion