ViewModel中的DependencyProperty注册 [英] DependencyProperty Registration in ViewModel

查看:73
本文介绍了ViewModel中的DependencyProperty注册的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现了很多关于ViewModels及其属性的讨论,它们比较了以下两种方法: INotifyPropertyChanged 的实现或通过 Dependency Properties 的实现。

I am finding a lot of discussions about ViewModels and their Properties that compare two approches: implementation of INotifyPropertyChanged or implementation via Dependency Properties.

我在做INotifyPropertyChanged时(工作正常),但是我在实施DP方式时遇到困难。

While I am doing INotifyPropertyChanged a lot (and it's working) I am having difficulties implementing the DP-approach.

当我注册像这样的ViewModel中的DP

When I am registering the DP in the ViewModel like this

    public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyUserControl));

并尝试在以下地方使用它:

and trying to use it somewhere with:

<myNameSpace:MyUserControl SomeProperty="{Binding ...}"/>

存在编译器错误:

The property 'SomeProperty' does not exist in XML namespace 'clr-namespace:myNameSpace'.

我在做什么错??

EDIT1

ViewModel看起来像这样:

The ViewModel looks like this:

public class MyUserControlVM : DependencyObject
{

    public string SomeProperty
    {
        get { return (string)GetValue(SomePropertyProperty); }
        set { SetValue(SomePropertyProperty, value); }
    }

    public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyUserControl));     
}


推荐答案

您是否已实现标准属性存取器?完整的DP签名如下所示:

Have you implemented the standard property accessors? A complete DP signature looks like this:

public static readonly DependencyProperty PropertyNameProperty =
        DependencyProperty.Register("propertyName", typeof (PropertyType), typeof (MyUserViewModel), new PropertyMetadata(default(PropertyType)));

    public PropertyType PropertyName
    {
        get { return (PropertyType) GetValue(PropertyNameProperty); }
        set { SetValue(PropertyNameProperty  value); }
    }

然后您的代码应该可以工作。有关DP与INotifyPropertyChanged的更多信息:对我来说,主要的权衡是速度与可读性。用依赖项属性声明乱扔ViewModels很痛苦,但是您在通知管道中获得了大约30%的速度。

Then your code should work. One more info regarding DP's vs. INotifyPropertyChanged: For me, the main tradeoff is speed vs. readability. It's a pain littering your ViewModels with dependency property declarations, but you gain about 30% speed in the notification pipeline.

编辑:

您在View的类型上注册属性,它应该是ViewModel的类型,即

You register the property on the View's type, it should be the ViewModel's type, i.e.

public static readonly DependencyProperty PropertyNameProperty =
        DependencyProperty.Register("propertyName", 
        typeof (PropertyType), 
        typeof (MyUserViewModel), 
        new PropertyMetadata(default(PropertyType)));

而不是

public static readonly DependencyProperty PropertyNameProperty =
        DependencyProperty.Register("propertyName", 
        typeof (PropertyType),
        typeof (MyUserControl), 
        new PropertyMetadata(default(PropertyType)));

编辑2:

好,您在这里混了一些东西:您可以在ViewModel和View上同时具有依赖项属性。对于前者,您可以在控件的代码后边(即MyUserControl.xaml.cs)中定义DP。对于后者,如上所示,您可以在ViewModel中定义它。代码的问题在于用法:

Ok, you're mixing something up here: You can have dependency properties both, on your ViewModel and your View. For the former, you define the DP in the control's codebehind (i.e. MyUserControl.xaml.cs). For the latter you define it in the ViewModel as I have shown it above. The problem with your code lies in the usage:

您正在尝试将 DataContext 的某些值绑定到在视图中称为 SomeProperty
的属性:

You are trying to bind some value of your DataContext to a property called SomeProperty on the view:

<myNameSpace:MyUserControl SomeProperty="{Binding SomePropertyBindingValue}"/>

在视图模型上定义依赖项属性时,没有属性 SomeProperty ,因此会出现编译器错误。为了使上述用法有效,您需要将DP放在 View的代码的后面,并在ViewModel上定义普通属性 SomePropertyBindingValue

As you've defined the dependency property on the view model, there is no property SomeProperty on the view, hence you get the compiler error. To make the above usage work, you need to put the DP in the View's codebehind and define a normal property SomePropertyBindingValue on the ViewModel.

要在ViewModel上定义DP并在视图中使用它,您需要绑定到此属性:

To define the DP on the ViewModel and use it in the view, you need to bind TO this property:

<myNameSpace:MyUserControl Width="{Binding SomeProperty}"/>

假设您已正确连接ViewModel和View,这会将视图宽度绑定到ViewModel的属性 SomeProperty 。现在,如果在ViewModel上设置了 SomeProperty ,尽管您尚未实现INPC,UI也会更新。

Supposed you've wired up ViewModel and View correctly, this will bind the views width to your ViewModel's property SomeProperty. Now, if SomeProperty is set on the ViewModel, the UI will update, though you haven't implemented INPC.

编辑3:

据我了解,您的问题是-要获得所需的行为-您需要在其上绑定一个依赖项属性 control 设置为单独的 ViewModels 上的两个属性: MainWindowVM 上的一个属性应绑定到 UserControl ,然后-从 UserControl -回到另一个 ViewModel UserControl1VM )。这里的设计有些曲折,并且不知道确切的上下文,所以我不明白为什么您不能在ViewModel级别处理属性同步:

From what I understand your problem is that - to get the desired behavior - you would need to bind one dependency property on the control to two properties on separate ViewModels: One property on MainWindowVM should be bound to the UserControl and then - from the UserControl - back to another ViewModel (UserControl1VM). There is a bit of twist in the design here and without knowing the exact context, I don't see why you couldn't handle the property synch on ViewModel level:

我让我的ViewModels或多或少类似于View的嵌套结构:

I let my ViewModels more or less resemble the nested structure of the View:

假设您有一个视图(伪代码):

Say you have a view (pseudo-code):

<Window>
    <UserControl1 />
</Window>

让窗口的数据上下文为 MainWM ,无论它来自何处,这是不合适的XAML(!):

Let the data context of the window be MainWM, whereever it comes from, this is not proper XAML(!):

<Window DataContext="[MainVM]">
    <UserControl1 />
</Window>

问题1是,为什么用户控件需要它自己的 ViewModel ?您只需将其绑定到 MainVM 的属性'SomeProperty':

Question 1 is, why does the user control need it's own ViewModel? You could simply bind it to MainVMs property 'SomeProperty':

<Window DataContext="[MainVM]">
    <UserControl Text="{Binding SomeProperty}" />
</Window>

好吧,说你真的有很好的理由为什么需要 UserControlViewModel 拥有自己的属性'UCSomeProperty':

Ok, say you really have agood reason why you would need a UserControlViewModel which has it's own property 'UCSomeProperty':

public class UserControlVM
{
    public string UCSomeProperty { get; set; } // Let INPC etc. be implemented
}

添加 UserControlVM 属性添加到 MainVM

public class MainVM
{
    public UserControlVM UserControlVM { get; set; } // INPC etc.
}

现在,您可以设置绑定了:

Now, you can set up the binding:

<Window DataContext="[MainVM]">
    <UserControl DataContext="{Binding UserControlVM}" 
                 Text="{Binding UCSomeProperty}" />
</Window>

最后,再次不知道您的具体情况以及是否有意义,但是让我们说您现在想要一个 MainVM上的属性与用户控件的ViewModel属性上的属性同步:

Last, again without knowing your specific case and whether it makes sense, but let's say you now want a property on 'MainVM' which is in synch with the property on the user control's ViewModel's property:

public class MainVM
{
    public string SomeProperty
    {
         get { return UserControlVM.UCSomeProperty; }
         set { UserControlVM.UCSomeProperty = value; }
    }

    public UserControlVM UserControlVM { get; set; } // INPC etc.

    public MainVM()
    {
         UserControlVM = new UserControlVM();
         UserControlVM.NotifyPropertyChanged += UserControlVM_PropertyChanged;
    }

    private void UserControlVM_PropertyChanged(object sender, BlaArgs e)
    {
         if (e.PropertyName == "UCSomeProperty")
              RaisePropertyChanged("SomeProperty");
    }
 }

您可以像这样使用绑定,例如:

You could use the binding like this, for example:

 <Window DataContext="[MainVM]">
    <UserControl DataContext="{Binding UserControlVM}" 
                 Text="{Binding UCSomeProperty}" />
    <TextBlock Text="{Binding SomeProperty}" />
</Window>

MainVM 上的SomeProperty和 UCSomeProperty 上的 em> USerControlVM 现在始终相同,并且在两个ViewModel上都可用。希望这对您有帮助...

SomeProperty on MainVM and UCSomeProperty on USerControlVM are always the same now and available on both ViewModels. I hope this helps...

这篇关于ViewModel中的DependencyProperty注册的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆