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