.net Wpf 用户控件和 MVVM

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3333934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 14:33:26  来源:igfitidea点击:

Wpf UserControl and MVVM

.netwpfmvvmuser-controlsdependency-properties

提问by byte

I am thinking about writing a WPF User Control for my application. I am using MVVM in my application.

我正在考虑为我的应用程序编写 WPF 用户控件。我在我的应用程序中使用 MVVM。

User control's may require Dependency Properties that can be set my Parent View. when using MVVM, the idea is that the Parent View will eventually create a binding between the UserControlsDP with Parent View's VM)

用户控件可能需要可以设置我的父视图的依赖属性。使用 MVVM 时,想法是父视图最终会在UserControlsDP 与父视图的 VM之间创建绑定)

Dependency Propertiesneed to be created in the View class as VM do not inherit from DependencyObject. This means adding code within the XAML code behind.

Dependency Properties需要在 View 类中创建,因为 VM 不继承自DependencyObject. 这意味着在后面的 XAML 代码中添加代码。

I was wondering if you can give advice as to how I should design a user control when developing WPF application using MVVM...

我想知道您是否可以就我在使用 MVVM 开发 WPF 应用程序时应该如何设计用户控件提出建议...

回答by akjoshi

Case 1:If you are creating this control just to be consumed in your application then you can go ahead and create a ViewModelfor it, but then you don't need to create DP's, your ViewModelcan just implement INotifyPropertyChangedand your parent Vm can still bind to them.

案例 1:如果您创建这个控件只是为了在您的应用程序中使用,那么您可以继续ViewModel为它创建一个,但是您不需要创建 DP,您ViewModel只需实现INotifyPropertyChanged并且您的父 Vm 仍然可以绑定到他们。

In our case, for user controls we have created separate VM's and an instance of it was present in ParentVM. So parent view will have this control in it and will bind the UserControlVMto this control(ParentVM.UserControlVM) and usercontrol will take care of other bindings.

在我们的例子中,对于用户控件,我们创建了单独的 VM,并且它的一个实例存在于ParentVM. 因此,父视图将在其中包含此控件并将绑定UserControlVM到此控件(ParentVM.UserControlVM),而用户控件将负责其他绑定。

Case 2:If your control will be used by other applications/developers and you don't want to keep it simple then go ahead with creating custom controls following control template implementation. This way you can create look-less controls and use dependency propertiestoo. Moreover whoever uses that control doesn't need to know about the related view model and use it.

案例 2:如果您的控件将被其他应用程序/开发人员使用,并且您不想让它保持简单,那么继续在控件模板实现之后创建自定义控件。通过这种方式,您可以创建无外观控件并使用dependency properties。此外,使用该控件的人不需要了解相关的视图模型并使用它。

Some of the similar questions/posts:

一些类似的问题/帖子:

WPF design question (custom control or mvvm): WPF design question (custom control or mvvm)

Custom control in WPF using MVVM concept: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/6293b176-e1e9-4610-af49-d53e6d294969/

WPF User Control hell with MVVM and Dependency Properties: WPF User Control hell with MVVM and Dependency Properties

WPF design question (custom control or mvvm): WPF design question (custom control or mvvm)

使用 MVVM 概念的 WPF 中的自定义控件:http: //social.msdn.microsoft.com/Forums/en-US/wpf/thread/6293b176-e1e9-4610-af49-d53e6d294969/

带有 MVVM 和依赖属性的WPF 用户控制地狱:带有 MVVM 和依赖属性的 WPF 用户控制地狱

回答by markmnl

A UserControlis part of the "View" in "MVVM" just like the TextBoxor ListViewcontrols are part of the View.

AUserControl是“MVVM”中“视图”的一部分,就像TextBoxListView控件是视图的一部分一样。

Whether you decide to use MVVM to develop your UserControlitself or write it in QBASIC (not recommended) it does not break the MVVM pattern for the consumers of your UserControlso long as they can do every thing they need with your UserControlby binding to DependencyProperty's exposed on your UserControl. i.e. Your UserControlshould expose the properties it is dependentupon (hence the name). Once you grasp this DependencyProperty's suddenly make a whole lot of sense and you want their helpful on changed event handlers and default values you specify in their constructor.

无论你决定使用 MVVM 来开发你UserControl自己还是用 QBASIC 编写它(不推荐)它都不会破坏你的消费者的 MVVM 模式,UserControl只要他们可以UserControl通过绑定到DependencyProperty的暴露来做他们需要的一切事情你的UserControl。即您UserControl应该公开它所依赖的属性(因此得名)。一旦你掌握了这一点DependencyProperty,就会突然变得很有意义,并且你希望它们对更改的事件处理程序和您在构造函数中指定的默认值有所帮助。

If your UserControlis in a different assembly or not I cannot see how that makes a difference.

如果您UserControl在不同的程序集中,我看不出这有什么不同。

That said many would advocate you build your UserControlusing the MVVM pattern itself for all the good reasons MVVM brings e.g. helping another developer looking at your code. However some things simply are not possible and/or much harder more complex and less performant hacking the XAML to do this - I am not talking about your garden variety Add User Form but for example a UserControlhandling the layout of thousands of visuals. Furthermore since you are working in your View you do NOTwant your UserControl's ViewModels mixed in with you applications!

这就是说,许多人会提倡您UserControl使用 MVVM 模式本身来构建您的构建,因为 MVVM 带来了所有很好的理由,例如帮助另一个开发人员查看您的代码。然而,有些事情根本不可能和/或更难更复杂和性能更差的 XAML 黑客来做到这一点 - 我不是在谈论你的花园品种添加用户表单,而是例如UserControl处理数千个视觉效果的布局。此外,由于您在 View 中工作,您希望您UserControl的 ViewModel 与您的应用程序混合!

Basically I am saying it is well within MVVM not to use MVVM on your View!

基本上我是说在 MVVM 中不要在您的视图上使用 MVVM!

回答by Mura

Basically, instead of binding your UserControl's datacontext to the userControlViewModel, it's better to do it on the first child element of the user control. That way, all the references that you make within the control will be bound to the userControlViewModel, but the dependencies properties can be set from the data context set where you want to use your UserControl.

基本上,与其将 UserControl 的数据上下文绑定到 userControlViewModel,不如在用户控件的第一个子元素上执行此操作。这样,您在控件中创建的所有引用都将绑定到 userControlViewModel,但可以从要使用 UserControl 的数据上下文集设置依赖项属性。

This pattern has worked pretty well for me, on your UserControl XAML:

这个模式对我来说效果很好,在你的 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>

Then on the code behind:

然后在后面的代码上:

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