Ад управления пользователями WPF с MVVM и свойствами зависимости - PullRequest
15 голосов
/ 14 апреля 2010

Вот что я пытаюсь сделать:

  • Я пишу UserControl, который я хочу использовать другим разработчикам.
  • Я хочу, чтобы конечные пользователи могли использовать мой элемент управления с помощью свойств зависимости.

    <lib:ControlView ControlsText={Binding Path=UsersOwnViewModelText} />
    
  • Я использую шаблон MVVM.

  • Я связываю свои ViewModels с их View, используя <DataTemplates>

    <DataTemplate DataType="{x:Type local:ControlViewModel}">  
        <local:ControlView />  
    </DataTemplate>
    

Итак, у меня два вопроса:

  1. Правильно ли я считаю, что если UserControl используется в XAML, то UserControl должен установить ViewModel в качестве DataContext, когда происходит событие Loaded элемента управления вместо использования метода <DataTemplate>? 1030 *

  2. Как разрешить пользователям привязывать данные к свойствам зависимостей моего элемента управления, оставаясь привязанными к моему ViewModel?

Ответы [ 4 ]

25 голосов
/ 14 апреля 2010

Вы должны разделить два варианта использования:

  1. (Пользовательский) элемент управления, который будет использоваться другими разработчиками.
  2. Пользовательский элемент управления, который будет использоваться вашим приложением.

Важно, что последнее зависит от первого, а не наоборот.

В сценарии использования 1 будут использоваться свойства зависимостей, привязки шаблонов и все, что нужно для создания обычного элемента управления WPF:

MyControl.cs:

public class MyControl : Control
{
    // dependency properties and other logic
}

Generic.xaml:

<ControlTemplate Type="local:MyControl">
    <!-- define the default look in here, using template bindings to bind to your d-props -->
</ControlTemplate>

Затем вы бы определили вариант использования 2 как:

MyViewModel.cs:

public class MyViewModel : ViewModel
{
    // properties and business logic
}

MyView.xaml:

<UserControl ...>
    <local:MyControl SomeProperty="{Binding SomePropertyOnViewModel}" .../>
</UserControl>

Лучшее из двух миров с чистым разделением. Другие разработчики зависят только от элемента управления, который может (и, вероятно, должен) находиться в совершенно другой сборке, чем ваша модель представления и представление.

10 голосов
/ 14 апреля 2010

Прежде всего, я не считаю MVVM хорошим выбором, если вы разрабатываете UserControl, который будет использоваться другими. Неуправляемый контроль - это то, что вы действительно должны развивать. У Джеремии Моррилла есть сообщение в блоге на эту тему.

С учетом сказанного, вы можете установить текст данных с помощью XAML, если у вас есть открытый конструктор по умолчанию.

Внутри ControlView.xaml положено:

<UserControl.DataContext>
    <local:ControlViewModel />
</UserControl.DataContext>
1 голос
/ 20 февраля 2018

По сути, вместо привязки текста данных вашего UserControl к userControlViewModel лучше сделать это на первом дочернем элементе пользовательского элемента управления. Таким образом, все ссылки, которые вы делаете в элементе управления, будут привязаны к userControlViewModel, но свойства зависимостей могут быть установлены из набора данных контекста, где вы хотите использовать свой 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

Затем, когда вы используете это на главном экране, вы можете установить свойство зависимостей со значением, которое вы хотите передать MyUSerControl

1 голос
/ 10 апреля 2014

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...