将ViewModel定义为数据绑定的DependencyProperty是不是一个不好的做法?

本文关键字:一个 定义 ViewModel 数据绑定 DependencyProperty 是不是 | 更新日期: 2023-09-27 18:08:53

我有一个UserControl MyView,它有一个内部UserControl子视图。

2个UserControls的视图模型与视图具有相同的层次结构,例如,MyViewModel内部有SubViewModel,如下面的代码所示。

public class MyViewModel
{
    private readonly SubViewModel _subViewModel = new SubViewModel();
    public SubViewModel SubViewModel { get { return _subViewModel; } }
    private void HandleSubViewModel()
    {
        // Do what is necessary to handle SubViewModel
    }
}

我的问题是关于如何绑定SubViewModel到SubView。

现在我在SubView的代码后面定义SubViewModel,并将其绑定到MyViewModel类的SubViewModel属性。

public partial class SubView : UserControl
{
    public static readonly DependencyProperty SubViewModelProperty = DependencyProperty.Register(
    "SubViewModel", typeof (SubViewModel), typeof (SubView), new PropertyMetadata(default(SubViewModel)));
    public SubViewModel SubViewModel
    {
        get { return (SubViewModel) GetValue(SubViewModelProperty); }
        set { SetValue(SubViewModelProperty, value); }
    }
}
<UserControl x:Class="MyProject.View.MyView"
             xmlns:parts="clr-namespace:MyProject.View.Parts">
    <Grid DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}, Path=MyViewModel}">
        <parts:SubView SubViewModel="{Binding SubViewModel}"/>
    </Grid>
</UserControl>

以这种方式绑定内部视图模型是一种不好的做法吗?

如果是,我如何更好地绑定它?

将ViewModel定义为数据绑定的DependencyProperty是不是一个不好的做法?

它可能不好的一个原因是,如果SubViewModel内部的属性发生了变化,MyViewModel将无法知道这一点。因此,例如,如果有任何验证需要在MyViewModel级别执行和处理,您将无法这样做。

解决这个问题,当一个属性改变;您必须在SubViewModel中引发一个事件,并使MyViewModel订阅它,并在收到它后做出适当的反应。

除此之外,我没有看到这样的缺点。但请阅读这些链接以获取更多信息:MVVM和嵌套视图模型

MVVM:如何处理嵌套视图模型之间的交互?

你可以这样做:视图模型:

public class MyViewModel
{
    private readonly SubViewModel _subViewModel;
    public SubViewModel SubViewModel
    {
        get { return _subViewModel; }
    }
    public MyViewModel()
    {
        _subViewModel = new SubViewModel();
        _subViewModel.Text1 = "blabla";
    }
}
public class SubViewModel : DependencyObject
{
    public string Text1
    {
        get { return (string)GetValue(Text1Property); }
        set { SetValue(Text1Property, value); }
    }
    public static readonly DependencyProperty Text1Property =
        DependencyProperty.Register("Text1", typeof(string), typeof(SubViewModel));
}

SubUserControl:

<UserControl x:Class="WpfApplication1.SubUserControl"
         xmlns= ... >
<Grid Height="200" Width="300" Background="Aqua">
      <TextBlock Text="{Binding SubViewModel.Text1}" /> 
</Grid>