【问题标题】:XAML binding not working on dependency property?XAML 绑定不适用于依赖属性?
【发布时间】:2017-03-04 05:03:17
【问题描述】:

我正在尝试(但失败)对 xaml 中的依赖属性进行数据绑定。当我在后面使用代码时它工作得很好,但在 xaml 中却不行。

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

<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},你会发现你绑定到了错误的数据上下文。
  • 您应该将属性名称(“Test”)作为第一个参数传递给 Register 方法。我找不到接收 Type 作为第一个参数的重载。
  • MyControl 的 DataContext 是什么?它应该是主窗口
  • 如果数据上下文错误,它也无法与解决方案背后的代码一起使用。 DataContext 在两个构造函数(窗口和用户控件)中都设置为 this
  • 是的,我已经尝试过RegisterAttached。不幸的是,它也不起作用。

标签: c# wpf xaml data-binding dependency-properties


【解决方案1】:

依赖属性声明必须如下所示:

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); }
}

UserControl 的 XAML 中的绑定必须将控件实例设置为源对象,例如通过设置绑定的RelativeSource 属性:

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

同样重要的是,永远不要在其构造函数中设置 UserControl 的 DataContext。我确定有类似的东西

DataContext = this;

删除它,因为它有效地防止从 UserConrol 的父级继承 DataContext。

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

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

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

【讨论】:

  • 恐怕没用。顺便说一句,您为DependencyProperty 编写的声明与我的问题完全相同。
  • 远非完全一样。在您的问题中,您忘记了属性名称(“Test”)和 PropertyMetadata 上的 new 关键字。这些细节很重要!
  • 天哪,你完全正确!我非常抱歉。我一定是贴错了代码。
  • 查看我关于在 UserControl 的 ctor 中设置 DataContext 的更新答案。你不能那样做!
  • DataContext = this; 包含此内容的教程普遍由 trolling assholes 编写。
猜你喜欢
  • 2014-01-09
  • 2023-03-13
  • 2011-06-25
  • 1970-01-01
  • 2017-12-18
  • 2011-12-20
  • 2014-02-03
  • 1970-01-01
相关资源
最近更新 更多