Wpf UserControl и MVVM

18

Я думаю о написании WPF User Control для моего приложения. Я использую MVVM в своем приложении.

Пользовательским элементам управления могут потребоваться свойства зависимостей, которые могут быть установлены в моем родительском представлении. при использовании MVVM идея состоит в том, что Parent View в конечном итоге создаст привязку между UserControls DP и VM).

Dependency Properties необходимо создать в классе View, поскольку VM не наследуется от DependencyObject . Это означает добавление кода в код XAML позади.

Мне было интересно, можете ли вы дать советы относительно того, как я должен создавать пользовательский элемент управления при разработке приложения WPF с использованием MVVM ...

    
задан byte 26.07.2010 в 12:17
источник

3 ответа

24

Случай 1: Если вы создаете этот элемент управления, который будет использоваться только в вашем приложении, вы можете пойти и создать для него ViewModel , но тогда вам не нужно создавать DP , ваш ViewModel может просто реализовать INotifyPropertyChanged , а ваш родительский Vm все равно может привязываться к ним.

В нашем случае для пользовательских элементов управления мы создали отдельные виртуальные машины, и экземпляр его присутствовал в ParentVM . Таким образом, представление родителя будет иметь этот элемент управления и привяжет UserControlVM к этому элементу управления ( ParentVM.UserControlVM ), а usercontrol позаботится о других привязках.

Случай 2: Если ваш элемент управления будет использоваться другими приложениями / разработчиками, и вы не хотите, чтобы это было простым, продолжайте создавать пользовательские элементы управления после реализации шаблона управления. Таким образом, вы можете создавать элементы управления без видимых элементов и использовать dependency properties . Более того, тот, кто использует этот элемент управления, не должен знать о соответствующей модели представления и использовать его.

Некоторые из похожих вопросов / сообщений:

  

Вопрос проектирования WPF (пользовательский контроль или   MVVM):    вопрос дизайна WPF (пользовательский контроль или mvvm)

     

Пользовательский контроль в WPF с использованием MVVM   концепция:    Ссылка

     

Пользовательский контроль WPF ад с MVVM и   Свойства зависимостей:    Адреса пользователей WPF с MVVM и свойствами зависимостей

    
ответ дан akjoshi 26.07.2010 в 14:32
  • hi akjoshi, какой startegy вы используете для привязки от родительской виртуальной машины к свойству свойств управления? Не могли бы вы привести небольшой пример? –  byte 26.07.2010 в 17:33
  • По общему признаку я установил DataContext дочернего элемента управления объектом UserCOntrolVM, который присутствует в ParentVM. поэтому скажите, что у вас есть главное окно, внутри которого присутствует ваш пользовательский элемент управления. Теперь для контекста данных главного окна задано значение ParentVM, этот ParentVM будет выставлять свойство типа UserControlVM. Теперь нам просто нужно установить контекст данных пользовательского элемента управления следующим образом: <local: UserControl DataContext="{Binding Path = UserControlVM}" /> –  akjoshi 27.07.2010 в 08:35
  • Спасибо akjoshi, я использую эту стратегию в своем приложении, и все VM реализуют INotifyPropertyChanged. Мой вопрос был больше связан с привязкой свойств к вашему комментарию: «ваш ViewModel может просто реализовать INotifyPropertyChanged, а ваш родительский Vm все равно может привязываться к ним». Создаете ли вы элементы управления VM в ParentVM и позвольте ParentVM напрямую привязываться к элементам управления VM? –  byte 27.07.2010 в 10:43
7

A UserControl является частью «View» в «MVVM», так же как элементы управления TextBox или ListView являются частью представления.

Если вы решили использовать MVVM для разработки самого UserControl или записать его в QBASIC (не рекомендуется), он не нарушает шаблон MVVM для потребителей вашего UserControl , если они могут делать все, что им нужно с вашим UserControl путем привязки к DependencyProperty , выставленной на UserControl . т. е. ваш UserControl должен выставлять свойства зависимые на (отсюда и название). Как только вы поймете, что DependencyProperty внезапно приобретут большой смысл, и вы хотите, чтобы они были полезны для измененных обработчиков событий и значений по умолчанию, которые вы указываете в своем конструкторе.

Если ваш UserControl находится в другой сборке или нет, я не вижу, как это имеет значение.

Тем не менее многие будут выступать за то, чтобы вы создали свой UserControl , используя шаблон MVVM для всех хороших причин, вызванных MVVM. помогая другому разработчику смотреть на ваш код. Однако некоторые вещи просто невозможны и / или намного сложнее и менее эффективны для взлома XAML для этого - я не говорю о вашем садовом разнообразии. Добавить форму пользователя, но, например, UserControl обрабатывает макет тысяч визуальных эффектов. Кроме того, поскольку вы работаете в своем представлении, вы NOT хотите, чтобы ваши ViewModels UserControl смешивались с вашими приложениями!

В основном я говорю, что в MVVM хорошо использовать MVVM на вашем представлении!

    
ответ дан markmnl 10.04.2014 в 02:53
  • Я поддержал вас, потому что это был хороший ответ, но также потому, что я хотел быть тем, кто сделал ваш бал в 4444 году до 4454 баллах –  Adam Plocher 11.03.2016 в 23:47
  • Хорошая рекомендация держать виртуальные машины приложения и UserControl отдельно (+1). –  Bob Sammers 15.06.2016 в 16:52
0

В принципе, вместо привязки datacontext UserControl к userControlViewModel лучше сделать это на первом дочернем элементе пользовательского элемента управления. Таким образом, все ссылки, которые вы делаете в элементе управления, будут привязаны к userControlViewModel, но свойства зависимостей могут быть установлены из набора контекстов данных, в котором вы хотите использовать свой UserControl.

Этот шаблон работал очень хорошо для меня, на вашем UserControl XAML:

<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
    
ответ дан Mura 20.02.2018 в 19:39