XAML绑定在依赖属性上无法工作?

10

我正在尝试在XAML中为一个依赖属性进行数据绑定,但一直失败。当我使用代码后台时,它可以正常工作,但是在XAML中却不行。

用户控件只是一个绑定到该依赖属性的。

<UserControl x:Class="WpfTest.MyControl" [...]>
     <TextBlock Text="{Binding Test}" />
</UserControl>

依赖属性是一个简单的字符串:

public static readonly DependencyProperty TestProperty 
= DependencyProperty.Register("Test", typeof(string), typeof(MyControl), new PropertyMetadata("DEFAULT"));

public string Test
{
    get { return (string)GetValue(TestProperty); }
    set { SetValue(TestProperty, value); }
}

我在主窗口中有一个常规属性,并使用通常的INotifyPropertyChanged实现。

private string _myText = "default";
public string MyText
{
   get { return _myText; }
   set {  _myText = value; NotifyPropertyChanged(); }
}

目前为止一切都很好。如果我将这个属性绑定到主窗口上的 TextBlock,一切都能正常工作。如果MyText发生更改,则文本会正确更新,世界也平静了。

<TextBlock Text="{Binding MyText}" />

然而,如果我在我的用户控件上做同样的事情,什么也不会发生。

<local:MyControl x:Name="TheControl" Test="{Binding MyText}" />

现在有趣的部分是,如果我在代码后端执行完全相同的绑定,它就能起作用!

TheControl.SetBinding(MyControl.TestProperty, new Binding
{
    Source = DataContext,
    Path = new PropertyPath("MyText"),
    Mode = BindingMode.TwoWay
});
为什么在XAML中它不能工作?

展示更多的XAML。我怀疑如果你绑定到{Binding},你会发现你正在绑定到错误的数据上下文。 - SledgeHammer
你应该将属性名称(“Test”)作为第一个参数传递给Register方法。我找不到一个以Type作为第一个参数的重载。 - Mehrzad Chehraz
1
如果数据上下文错误,则代码解决方案也无法正常工作。在窗口和用户控件的构造函数中,DataContext 都设置为 this - Oliver
是的,我已经尝试过RegisterAttached。不幸的是它也没有起作用。 - Oliver
那么我唯一能看到的区别就是你明确设置了Mode = BindingMode.TwoWay。在XAML中尝试一下吧。 - user1562155
显示剩余3条评论
1个回答

32

依赖属性声明必须像这样:

public static readonly DependencyProperty TestProperty =
    DependencyProperty.Register(
        nameof(Test),
        typeof(string),
        typeof(MyControl),
        new PropertyMetadata("DEFAULT"));

public string Test
{
    get { return (string)GetValue(TestProperty); }
    set { SetValue(TestProperty, value); }
}
中XAML的绑定必须将控件实例设置为源对象,例如通过设置绑定的RelativeSource属性:

<UserControl x:Class="WpfTest.MyControl" ...>
     <TextBlock Text="{Binding Test,
         RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</UserControl>

同样非常重要的一点是,永远不要在用户控件的构造函数中设置DataContext。我相信一定有类似于

DataContext = this;

请将其移除,因为它有效地阻止了从UserControl的父级继承DataContext。

通过在代码后台中设置Source = DataContext来显式设置绑定源,而在

<local:MyControl Test="{Binding MyText}" />

绑定源隐式地是当前的DataContext。然而,该DataContext已经被赋值为UserControl本身的构造函数中的赋值,而不是从窗口继承的DataContext(即视图模型实例)。


1
很抱歉,它没有起作用。顺便说一下,你写的DependencyProperty声明与我的问题中完全相同。 - Oliver
1
请查看我有关在UserControl的构造函数中设置DataContext的更新答案。你绝不能这样做! - Clemens
继承父级的DataContext有什么重要性?设置依赖属性并将其绑定是否足够? - Oliver
11
DataContext = this; 包含这行代码的教程通常都是由恶意捣乱的人编写的。 - user1228
@Oliver绑定是针对DataContext的。如果您将DC更改为意外的内容,您的绑定将失败。 - user1228
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接