【问题标题】:MVVM + UserControl + Dependency PropertyMVVM + UserControl + 依赖属性
【发布时间】:2013-03-05 22:56:12
【问题描述】:

好吧,这和这个问题有点关系:WPF Printing multiple pages from a single View Model

我试图遵循那里给出的建议,但现在我被卡住了。

我的应用程序使用 MainView.xaml 和适当的 MainViewViewModel.cs,我在后台使用 MVVM Light。

现在 - 根据帖子 - 我似乎必须执行以下操作:

  • 创建用户控件
  • 从用户控件中公开一些属性
  • 确保视图模型显示这些属性

这个想法很清楚,但我在尝试相互通知时被卡住了。

我的用户控件 (UcTest.xaml) 公开了一个依赖属性:

public string SpecialText
{
    get { return (string)GetValue(SpecialTextProperty); }
    set
    {
        SetValue(SpecialTextProperty, value);

    }
}

// Using a DependencyProperty as the backing store for SpecialText.  This enables animation, styling, binding, etc...
public static readonly DependencyProperty SpecialTextProperty =
    DependencyProperty.Register("SpecialText", typeof(string), typeof(UcTest), new PropertyMetadata(new PropertyChangedCallback(SpecialTextChangedPropertyCallback)));

private static void SpecialTextChangedPropertyCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    // Do something
    Debug.WriteLine("Ffgdgf");
}

好的,所以我现在有了一个具有一些依赖属性的用户控件。然而,这些属性与我的 ViewModel 属性完全分开(那些是应该显示的)。

所以基本上我有两种可能:

  • 我现在如何告诉 UserControl 的 ViewModel 某些属性已更改?
  • 是否有可能忘记依赖属性并直接访问视图模型?

附加信息 #1: 我已经上传了一个(简单)我在这里尝试做的例子:Example Project。我想从我的 MainViewViewModel 更改 UserControl1 中标签的值(通过 UserControl1 的 ViewModel 中的绑定属性)。

【问题讨论】:

  • 这意味着我的 UserControl 需要实现 INotifyPropertyChanged 这基本上是我的 ViewModel 应该做的。

标签: wpf mvvm user-controls dependency-properties


【解决方案1】:

您通常会将 UserControl 的属性bind 传递给 ViewModel 属性。双向绑定可以双向工作,从 ViewModel 到 View,反之亦然。

<Window x:Class="TestApplication.MainWindow" ...>
    <Window.DataContext>
        <local:MyViewModel/>
    </Window.DataContext>
    <Grid>
        <local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
    </Grid>
</Window>

要直接访问上例中的 ViewModel 对象,您可以简单地将 UserControl 的 DataContext 属性转换为 ViewModel 类型。 DataContext 继承自 MainWindow。

var viewModel = DataContext as MyViewModel;
var property = viewModel.MyViewModelProperty;

您当然也可以直接将一个专门的 ViewModel 实例分配给 UserControl 的DataContext

<local:UcTest SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>
    <local:UcTest.DataContext>
        <local:UserControlViewModel/>
    </local:UcTest.DataContext>
</local:UcTest>

或者您可以将 ViewModel 实例创建为资源字典中的资源并像这样分配 DataContext

<local:UcTest DataContext="{StaticResource MyUserControlViewModel}"
              SpecialText="{Binding MyViewModelProperty, Mode=TwoWay}"/>

【讨论】:

  • 嗯,我想我可能误会你了。问题是 UserControl 有自己的 ViewModel 我想绑定到。还是您认为将属性保留在 MainViewModel 中并仅使用没有自己的 ViewModel 的 UserControl 会更好?
  • 这取决于您的应用程序设计。两者都是有效的解决方案。您也可以直接分配 UserControl 的 DataContext 属性。
  • 嗯,不..我不太明白这一点。你介意发布一个例子吗?因为一旦我将 UserControl 的 DataContext 更改为 UserControlViewModel,我就不能再分配任何变量,因为 UserControl 不知道这些属性。如果 SpecialText 不是 DependencyProperty,我如何将某些内容分配给“SpecialText”?
  • 查看我的编辑。 “如果 SpecialText 没有 DependencyProperty,我如何为“SpecialText”分配一些东西?”是什么意思。 SpecialText 是一个依赖属性,它是这样设计的。
  • 是的(哦,这很难解释)。重点是依赖属性“特殊文本”与 ViewModel 分离。我上传了一个小例子(我的主帖中的链接)来说明我的意思。
【解决方案2】:

好的,经过数小时的谷歌搜索,似乎“正确”的方法是根本不这样做。一般的方法是将数据保留在您的 MainViewModel 中,而不是为 UserControl 使用额外的 ViewModel(我发现它有点......好吧..不太好)。主要问题是没有简单的机制将数据从 Dependency Property 获取到 ViewModel。

对于打印,我现在又回到纯粹的代码中。

【讨论】:

  • 这可能适用于您将选项卡项分隔到用户控件中的情况。但是一般的控件,比如文件浏览器,会被多次显示呢?
  • @Tom L. 在您的情况下,我能想到的最好办法是不在用户控件中设置数据上下文,然后在 Windows 加载时将传递的属性从 DP 保存到变量,然后将上下文设置为 VM 的新实例。然后在 VM 中设置适当的属性并继续。这并不理想,但它确实完成了工作。我希望在 DP 的元数据中,您可以指定在什么上下文中获取绑定。
猜你喜欢
  • 2014-04-10
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
  • 2017-12-24
  • 1970-01-01
  • 2023-04-07
  • 2013-08-12
相关资源
最近更新 更多