【问题标题】:Dependency Property + UserControl + ViewModel依赖属性 + UserControl + ViewModel
【发布时间】:2015-03-19 22:51:31
【问题描述】:

鉴于我有这个 UserControl:

public class MyStringUserControl : UserControl
{
    public string MyString
    {
        get { return (string)GetValue(MyStringProperty); }
        set { SetValue(MyStringProperty, value); }
    }

    public static readonly DependencyProperty MyStringProperty =
        DependencyProperty.Register("MyString", typeof(string), typeof(MyStringUserControl),
            new FrameworkPropertyMetadata(null));
}

还有这个 ViewModel:

public class MyStringViewModel
{
    public string MyString { get; set; }
}

现在我在另一个视图中使用 MyStringUserControl,如下所示:

<controls:MyStringUserControl MyString="{Binding SomeStringProperty} />

我正在寻找一种优雅的方式将此字符串绑定回 MyStringViewModel。
我也对必须复制 UserControl 代码和 ViewModel 后面的每个属性的事实感到不自在。有没有更好的方法来做到这一点?

编辑#1:

我想这样做的原因是因为单元测试(即使没有 InitializeComponent,创建 UserControl 也需要很长时间)

【问题讨论】:

  • 为什么需要在用户控件上使用 ViewModel?我不记得曾经有过 TextBoxViewModel 或 ComboBoxViewModel。我是 MVVM 的忠实粉丝,但我认为用户控件就是……一个控件。简单明了。
  • 因为单元测试。如果我直接使用 UserControl,则每次测试都需要大约 700 毫秒来创建控件。
  • 对于单元测试,您可以跳过构造函数中的 InitializeComponents() 调用。
  • 谢谢,但是没有 InitializeComponent 的事件仍然需要大约 100 毫秒,这太长了。
  • @nvoigt 我同意在没有上下文的情况下很难理解 NKusperer 正在做的事情是否合适,但我会说我有时也做过类似的事情,当时我觉得它们是合适的。作为示例,我创建了一个 LoginViewModel 和一个 LoginView,我将 LoginViewModel 设置为内部并将其设置为 DataContext。这对我来说更有意义,然后将所有内容都填充到 CodeBehind 并将 DataContext 设置为 self.我还能够创建视图的其他版本(窗口、用户控件、页面)。

标签: c# wpf mvvm data-binding user-controls


【解决方案1】:

如果我打算这样做,我会使用 DependencyProperty 的 PropertyChanged 事件处理程序来设置我的 ViewModel 的属性,并使用我的 ViewModel 的 PropertyChanged 事件处理程序来设置我的 DependencyProperty。话虽如此,我从来没有理由走这条特别的路。

private SomeViewModel _viewModel;

public static readonly DependencyProperty MyStringProperty = DependencyProperty.Register("MyString", typeof(string), typeof(MyStringUserControl), new PropertyMetadata(OnMyStringChanged));

public MyStringUserControl()
{
    InitializeComponent();

    _viewModel = new SomeViewModel();
    _viewModel.PropertyChanged += OnViewModelPropertyChanged;

    this.DataContext = _viewModel;
}

private static void OnMyStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ((MyStringUserControl)d).OnMyStringChanged(e.NewValue);
}

private void OnMyStringChanged(string newValue)
{
    _viewModel.SomeProperty = newValue;
}

private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "SomeProperty":
            SetValue(MyStringProperty, _viewModel.SomeProperty);
            break;
        default:
            break;
    }
}

【讨论】:

  • 这是非常紧密的耦合。
【解决方案2】:

复制您的属性绝对没有意义。使用 MVVM 意味着您需要为每个 UserControl 提供一个视图模型。当我使用UserControl 作为视图的part 时,我很少为它使用单独的视图模型。有时,我只会在后面的UserControl 代码中使用DependencyPropertys,而其他时候我会直接将数据绑定到父视图模型。这完全取决于您想对数据做什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-25
    • 2014-08-31
    • 2017-12-24
    • 1970-01-01
    • 2023-04-07
    • 2014-04-10
    • 2013-08-12
    • 1970-01-01
    相关资源
    最近更新 更多