Wpf ViewModel中的从属属性注册

Wpf ViewModel中的从属属性注册,wpf,mvvm,dependency-properties,Wpf,Mvvm,Dependency Properties,我发现很多关于ViewModel及其属性的讨论比较了两种方法:INotifyPropertyChanged的实现或通过依赖属性的实现 当我在做InotifyProperty时,改变了很多(它正在工作),我在实现DP方法时遇到了困难 当我像这样在ViewModel中注册DP时 public static readonly DependencyProperty SomePropertyProperty = DependencyProperty.Register("SomePr

我发现很多关于ViewModel及其属性的讨论比较了两种方法:INotifyPropertyChanged的实现或通过依赖属性的实现

当我在做InotifyProperty时,改变了很多(它正在工作),我在实现DP方法时遇到了困难

当我像这样在ViewModel中注册DP时

    public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyUserControl));
<myNameSpace:MyUserControl SomeProperty="{Binding SomePropertyBindingValue}"/>
并尝试在某个地方使用它:

<myNameSpace:MyUserControl SomeProperty="{Binding ...}"/>
我做错了什么


编辑1

ViewModel如下所示:

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));     
}
除此之外:

public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyUserControl));
您还需要:

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

您是否实现了标准的属性访问器?完整的DP签名如下所示:

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));     
}
public静态只读从属属性property属性nameproperty=
Register(“propertyName”、typeof(PropertyType)、typeof(MyUserViewModel)、new PropertyMetadata(默认值(PropertyType));
公共属性类型属性名称
{
获取{return(PropertyType)GetValue(PropertyNameProperty);}
set{SetValue(PropertyNameProperty值);}
}
那么你的代码应该可以工作了。关于DP与INotifyPropertyChanged的另一个信息是:对我来说,主要的折衷是速度与可读性。在ViewModels中乱丢依赖属性声明是一件痛苦的事情,但是在通知管道中,您可以获得大约30%的速度

编辑:

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

public静态只读从属属性property属性nameproperty=
DependencyProperty.Register(“propertyName”,
类型(属性类型),
类型(MyUserViewModel),
新的PropertyMetadata(默认值(PropertyType));
而不是

public静态只读从属属性property属性nameproperty=
DependencyProperty.Register(“propertyName”,
类型(属性类型),
类型(MyUserControl),
新的PropertyMetadata(默认值(PropertyType));
编辑2:

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

您正试图将
DataContext
的某些值绑定到名为
SomeProperty
关于这一观点:

<myNameSpace:MyUserControl SomeProperty="{Binding SomePropertyBindingValue}"/>
假设已正确连接ViewModel和View,这将把视图宽度绑定到ViewModel的属性
SomeProperty
。现在,如果在ViewModel上设置了
SomeProperty
,用户界面将更新,尽管您尚未实现INPC

编辑3:

据我所知,您的问题是为了获得所需的行为,您需要将控件上的一个依赖项属性绑定到单独ViewModels上的两个属性:MainWindowVM上的一个属性应该绑定到UserControl,然后从UserControl返回到另一个ViewModel(UserControl1VM)。这里的设计有点扭曲,在不知道确切上下文的情况下,我不明白为什么不能在ViewModel级别处理属性同步:

我让我的视图模型或多或少类似于视图的嵌套结构:

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

将UserControlVM属性添加到MainVM:

公共类MainVM
{
public UserControlVM UserControlVM{get;set;}//INPC等。
}
现在,您可以设置绑定:

<Window DataContext="[MainVM]">
    <UserControl DataContext="{Binding UserControlVM}" 
                 Text="{Binding UCSomeProperty}" />
</Window>
您可以像这样使用绑定,例如:

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

MainVM上的SomeProperty和USerControlVM上的UCSomeProperty现在总是相同的,并且在两个ViewModels上都可用。我希望这有助于…

当你说

<myNameSpace:MyUserControl SomeProperty="{Binding ...}"/>
仅声明
typeof(MyUserControl)
不足以使属性可用于
MyUserControl

MyUserControl
类没有属性
SomeProperty
,而是在视图模型中,因此会出现编译器错误

理想情况下,DependencyProperty应该在UserControl的代码隐藏中声明,而不是像下面的代码那样在ViewModel中声明

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

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

public class MyUserControlVM
{
  public string SomePropertyBindingValue{get;set;}
}
然后可以将依赖项属性与viewModel属性绑定。像这样

    public static readonly DependencyProperty SomePropertyProperty =
        DependencyProperty.Register("SomeProperty", typeof(string), typeof(MyUserControl));
<myNameSpace:MyUserControl SomeProperty="{Binding SomePropertyBindingValue}"/>

编辑-根据评论提出问题

我有MainWindow及其DataContext MainWindowVM和UserControl1 以及在此主窗口中的DataContext UserControl1VM。我要装订 MainWindowVM中的一个(普通)属性指向UserControl1上的DP,即 再次绑定到UserControl1VM中的(普通)属性。连接 我现在缺少的是UserControl1中DP之间的一个 以及UserControl1VM中的属性

我建议你重新考虑你的要求,也许这不是解决你问题的最好方法。原因如下:

您希望一个属性对MainWindowVM和UserControl1VM都是公共的,您正试图通过将ViewModel绑定到视图的Dependency属性并将其从视图传递回子ViewModel来实现这一点。这打破了MVVM模式的目的——在视图和视图模型之间分离责任


如果您将其作为构造函数参数从MainWIndowVM传递给UserControl1VM,则会更容易。这样,您就可以将它们绑定到视图,而不是通过视图进行传递。

您是否还有名为SomeProperty的属性?请查看我的编辑…是的,因为您正在尝试在
MyUserControl
上设置
SomeProperty
,而该属性未声明此属性。您混淆了UserControl和ViewModel类。问题是,为什么要在视图模型中使用依赖属性?为什么不保持INotifyPropertyChanged?但必须在UserCon中声明属性
("SomeProperty", typeof(string), typeof(MyUserControl))
public class MyUserControl
{
    public string SomeProperty
    {
        get { return (string)GetValue(SomePropertyProperty); }
        set { SetValue(SomePropertyProperty, value); }
    }

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

public class MyUserControlVM
{
  public string SomePropertyBindingValue{get;set;}
}
<myNameSpace:MyUserControl SomeProperty="{Binding SomePropertyBindingValue}"/>