我一直在努力理解并使用依赖属性。
我已经阅读了大量关于DP的描述和解释,我也认为我理解应该在哪里使用它们。
我已阅读this,其中包含链接/参考。
然而,我仍然有问题。这些可能只是精神障碍,也许我坚持一些我无法放弃的想法或信念..无论如何..
我想要做的是创建一个带有DP的控件。 在xaml中使用该控件并绑定到DP。
当我在xaml中指定DP的值时,该值将按预期显示在用户控件上。
<DpTestProj:UserControl1 MyName="Steve"
然而,当我尝试绑定它时,没有设置值,我得到了
System.Windows.Data错误:40:BindingExpression路径错误:'object'''UserControl1'(Name ='')'上找不到'PersonName'属性。 BindingExpression:路径= PERSONNAME; DataItem ='UserControl1'(Name =''); target元素是'UserControl1'(Name =''); target属性是'MyName'(类型'String')
这表明我在某处绑定或datacontext做错了。 但是我看不清楚。
我的代码如下。
UserControl1具有以下DP
public const string MyNamePropertyName = "MyName";
public string MyName
{
get
{
return (string)GetValue(MyNameProperty);
}
set
{
SetValue(MyNameProperty, value);
}
}
public static readonly DependencyProperty MyNameProperty = DependencyProperty.Register(
MyNamePropertyName,
typeof(string),
typeof(UserControl1),
new UIPropertyMetadata("No Name"));
它在MainWindow上使用就像这样
<StackPanel x:Name="LayoutRoot">
<DpTestProj:UserControl1 MyName="{Binding PersonName}" MyList="{Binding SomeListItems}" />
</StackPanel>
我正在使用MVVM Light,MainWindow的数据上下文是
DataContext="{Binding Main, Source={StaticResource Locator}}">
PersonName是一个普通的CLR(字符串)属性,它存在于MainViewModel
上如果我更容易发布整个解决方案here
答案 0 :(得分:0)
你的DependencyProperty不是问题;问题是您将绑定到的数据。绑定不会从Locator
资源中找到名为Main.PersonName的属性。
答案 1 :(得分:0)
答案是......
你不能直接用一个vanilla绑定绑定到dp的clr包装器(即使你已经将userControl的dataContext设置为这个(即userControl背后的代码))
您可以执行以下两项操作之一来更改UI元素中反映的依赖项属性。
1)在FindAncestor模式下使用RelativeSource绑定
{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DpWrapperProp}"
2)使用Dp的回调来更新UI元素。 (如果您使用回调进行某些验证,那么这可能是您的路线)。 因为回调是静态,所以您需要创建一个非静态方法来执行更新,并从静态方法中调用它。 ui元素(标签为textBlock)也需要命名。
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
}
*以上示例是通用的,与我的原始代码无关。
在this和this 的帮助下,我到达了这些解决方案答案 2 :(得分:-1)
<DpTestProj:UserControl1 MyName="{Binding MyName}" ... />
<强>更新强>
好的,我仔细看了一下你的解决方案。在UserControl1
中,您基本上会覆盖原始的DataContext。
为了使事情有效,只需删除该行:
public UserControl1() { InitializeComponent();DataContext = this;// this makes you lose your MainViewModel }
然后相应地修改UserControl1.xaml
以绑定到原始MainViewModel
:
<Label Content="{Binding PersonName}"/>
<ListBox ItemsSource="{Binding SomeListItems}" MinHeight="100" MinWidth="100"/>
现在我不知道您为什么要将UserControl1
的视图模型设置为自己的原始场景。这是一种非常不寻常的做事方式,不像MVVM那样。如果您真的想要走这条路线,则必须创建一个新的ViewModel,将原始MainViewModel
存储在一个属性中,将UserControl1
存储在另一个属性中。