wpf MVVM + UserControl + 依赖属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15176115/
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-13 07:49:29  来源:igfitidea点击:

MVVM + UserControl + Dependency Property

wpfmvvmuser-controlsdependency-properties

提问by Tom L.

Alright, this is somewhat related to this question: WPF Printing multiple pages from a single View Model

好吧,这与这个问题有些相关:WPF 从单个视图模型打印多个页面

I tried to follow the advice given there but now I am stuck.

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

My application uses a MainView.xaml and the appropriate MainViewViewModel.cs, I am using MVVM Light in the background.

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

Now - according to the post - it seems I have to do the following:

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

  • Create a user control
  • Expose some properties from the user control
  • Make sure the view model shows these properties
  • 创建用户控件
  • 从用户控件中公开一些属性
  • 确保视图模型显示这些属性

The idea is clear but I am stuck when trying to notify each other.

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

My user control (UcTest.xaml) exposes a Dependency Property:

我的用户控件 (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");
}

Alright, so I do now have a user control which has some dependency properties. Yet, these properties are completely separated from my ViewModel properties (those are the ones which shall be displayed).

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

So basically I have two possibilities:

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

  • How can I now tell my ViewModel for the UserControl that some properties have changed?
  • Is there a possibility to forget about the dependency properties and access the view model directly?
  • 我现在如何告诉 UserControl 的 ViewModel 某些属性已更改?
  • 是否有可能忘记依赖属性并直接访问视图模型?

Additional info #1: I have uploaded a (simple) example of what I am trying to do here: Example Project. I would like to change the value of the label in UserControl1 (via the binding property in the ViewModel for UserControl1) from my MainViewViewModel.

附加信息 #1:我上传了一个(简单的)示例,说明我在此处尝试执行的操作:Example Project。我想从我的 MainViewViewModel 更改 UserControl1 中标签的值(通过 UserControl1 的 ViewModel 中的绑定属性)。

采纳答案by Tom L.

Alright, after hours of googling it appears that the "correct" approach to this is not to do it at all. The general approach is to keep the data in your MainViewModel and not use an additional ViewModel for the UserControl (which I find a little ... well .. not so good). The main problem is that there is no easy mechanism to get the Data from the Dependency Property to the ViewModel.

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

For printing, I have now gone back to doing it purely in code.

对于打印,我现在又回到纯粹用代码来做。

回答by Clemens

You would usually bindthe UserControl's property to the ViewModel property. A two-way binding would work in both directions, from ViewModel to View and vice versa.

您通常会将UserControl 的属性绑定到 ViewModel 属性。双向绑定可以在两个方向上工作,从 ViewModel 到 View,反之亦然。

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

To directly access the ViewModel object in the above example, you could simply cast the UserControl's DataContextproperty to the ViewModel type. The DataContext is inherited from the MainWindow.

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

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


You could of course also directly assign a specialized ViewModel instance to the UserControl's DataContext:

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

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

or you may create the ViewModel instance as a resource in a resource dictionary and assign the DataContext like this

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

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