.net 试图理解依赖项属性

.net 试图理解依赖项属性,.net,dependency-properties,.net,Dependency Properties,我一直在努力理解并获得一些关于依赖性属性的知识 我已经阅读了大量关于DP的描述和解释,我也认为我理解应该在哪里使用它们 我已经阅读了其中包含的链接/参考资料 然而,我仍然有问题。这些也许只是心理障碍,也许我执着于一些我无法放弃的想法或信念。。无论如何 我想做的是创建一个带有DP的控件。 在xaml中使用该控件并绑定到DP 当我在xaml中为DP指定一个值时,该值将按预期显示在用户控件上 <DpTestProj:UserControl1 MyName="Steve" 它在主窗口上的使用方式

我一直在努力理解并获得一些关于依赖性属性的知识

我已经阅读了大量关于DP的描述和解释,我也认为我理解应该在哪里使用它们

我已经阅读了其中包含的链接/参考资料

然而,我仍然有问题。这些也许只是心理障碍,也许我执着于一些我无法放弃的想法或信念。。无论如何

我想做的是创建一个带有DP的控件。 在xaml中使用该控件并绑定到DP

当我在xaml中为DP指定一个值时,该值将按预期显示在用户控件上

<DpTestProj:UserControl1 MyName="Steve"
它在主窗口上的使用方式如下

<StackPanel x:Name="LayoutRoot">
    <DpTestProj:UserControl1 MyName="{Binding PersonName}" MyList="{Binding SomeListItems}" />
</StackPanel>
PersonName是位于MainViewModel上的普通CLR(字符串)属性

如果比较容易的话,我已经发布了整个解决方案

并相应地编辑您的
UserControl1.xaml
,以绑定到原始
MainViewModel

<Label Content="{Binding PersonName}"/>
<ListBox ItemsSource="{Binding SomeListItems}" MinHeight="100" MinWidth="100"/>


现在我不知道为什么要将
UserControl1
的视图模型设置为自身。这是一种非常不寻常的做事方式,不像MVVM。如果你真的想这样做,你必须创建一个新的ViewModel,在一个属性中存储原始的
MainViewModel
,在另一个属性中存储
UserControl1

你的DependencyProperty不是这里的问题;问题是您要将其绑定到的数据。无论定位符是什么,绑定都找不到名为Main.PersonName的属性。

答案是

您不能使用普通绑定直接绑定到dp的clr包装器(即使您已将userControl的dataContext设置为此(即userControl的代码隐藏))

您可以执行以下两种操作之一来获得对UI元素中反映的依赖项属性的更改

1) 在FindAncestor模式下使用相对资源绑定

{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DpWrapperProp}"
2) 使用Dp的回调更新UI元素。(如果您使用回调进行一些验证,那么这可能就是您的路线)。 因为回调是静态的,所以需要创建一个非静态方法来执行更新,并从静态方法调用该方法。ui元素(label textBlock whatever)也需要命名

    private static void ChangeText(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as MyUserControl).UpdateText(e.NewValue.ToString());
    }

    private void UpdateText(string newText)
    {
        MyLabel.Content = newText; //set the content of the named label 
                                   //defined in the userControl XAML
    }
*上面的示例是通用的,与我的原始代码没有必然的联系


仅供参考,我是在和的帮助下得出这些解决方案的,这消除了绑定错误,但您所做的是将DP绑定到其自身。因此,默认值显示在UserControlOK,yes中,它将值从mainViewModel获取到UserControl1上的控件中。但是它否定了依赖属性的需要。基本上,我是想用DP做点什么,仅此而已。@Cha0sEngine我想说,在这样的用例中(绑定到域模型数据,通过控件层次结构自动传递datacontext),您不需要处理依赖属性。它们是WPF/Silverlight基础设施的一部分,用于确保某些UI概念正常工作。当实现您自己的常规控件或框架元素时,依赖项属性变得有趣和必要。在这种情况下,您将无法使用与之相反的视图模型。@herzmeister der welten正如我所说,我正在试验依赖属性。这是一个非常简单的用户控件。如果我们现在忘记我的主窗口(测试线束),您将如何实现我的“控制”?您会使用DP来启用绑定吗?您会在用户控件上使用MVVM吗?还是不可能呢?谢谢。也许我们需要一个更有意义的例子,否则就很难用更好的方式澄清问题。是的,指导原则是在您自己的控件和用户控件上使用DPs使其可绑定,而在视图模型上使用MVVM(INotifyPropertyChanged)。那么,您是否正在尝试实现一个
PersonInfo控件
,您可以在该控件上以声明方式设置名称和一些来自外部的列表?我现在相信您真正想要的是TemplateBinding(或相对源TemplatedParent绑定):不,这就是令人困惑的地方。我试过了,如果
{Binding PersonName}
在标签中工作,那么它在usercontrol中也会工作。如果在依赖项属性上放置一个
OnPropertyChanged
回调,它是否被命中?和/或:输出窗口中是否存在任何绑定错误?那就是:嗯,是的。应该这样。这样做。。获取绑定表达式错误。System.Windows.Data错误:40:BindingExpression路径错误:“在”“对象”“UserControl1”“(名称=”“”)上找不到PersonName”属性。BindingExpression:Path=PersonName;DataItem='UserControl1'(名称='');目标元素是“UserControl1”(名称=“”);目标属性为“MyName”(类型为“String”)是否覆盖
UserControl
DataContext
?比如说,在
用户控件的构造函数中
? public UserControl1() { InitializeComponent(); DataContext = this; // this makes you lose your MainViewModel }
<Label Content="{Binding PersonName}"/>
<ListBox ItemsSource="{Binding SomeListItems}" MinHeight="100" MinWidth="100"/>
{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DpWrapperProp}"
    private static void ChangeText(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as MyUserControl).UpdateText(e.NewValue.ToString());
    }

    private void UpdateText(string newText)
    {
        MyLabel.Content = newText; //set the content of the named label 
                                   //defined in the userControl XAML
    }