C# 绑定到UserControl DependencyProperty

C# 绑定到UserControl DependencyProperty,c#,wpf,binding,user-controls,dependency-properties,C#,Wpf,Binding,User Controls,Dependency Properties,我已经创建了一个带有一些DependencyProperties的UserControl(在这里的示例中只有一个string属性)。当我实例化Usercontrol时,我可以设置Usercontrol的属性,并按预期显示它。当我试图通过绑定替换静态文本时,不会显示任何内容 我的UserControl如下所示: 背后的代码是: namespace TestUserControBinding { public partial class MyUserControl : UserContro

我已经创建了一个带有一些DependencyProperties的UserControl(在这里的示例中只有一个string属性)。当我实例化Usercontrol时,我可以设置Usercontrol的属性,并按预期显示它。当我试图通过绑定替换静态文本时,不会显示任何内容

我的UserControl如下所示:


背后的代码是:

namespace TestUserControBinding {

  public partial class MyUserControl : UserControl {
    public MyUserControl() {
      InitializeComponent();
      this.DataContext = this;
    }

    public static readonly DependencyProperty MyTextProperty = 
                   DependencyProperty.Register(
                         "MyText", 
                          typeof(string), 
                          typeof(MyUserControl));

    public string MyText {
      get {
        return (string)GetValue(MyTextProperty);
      }
      set {
        SetValue(MyTextProperty, value);
      }
    }// MyText

  }
}
当我在主窗口中尝试此操作时,一切都如预期的那样:


但这不起作用:


标签的行为是正确的,因此属性“Text”没有问题


我犯了什么错?我思考了几个小时,但找不到任何我忘记的东西。

在您的
用户控件中绑定以下内容:

<Label Content="{Binding MyText}"/>
<UserControl x:Class="TestUserControBinding.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:TestUserControBinding"
         ...>
这将在可视化树上导航到MyUserControl,然后在那里找到MyText属性。它将不依赖于
DataContext
,后者将根据您放置
UserControl
的位置而改变

在这种情况下,
local
指的是需要在
UserControl
中定义的名称空间:

<Label Content="{Binding MyText}"/>
<UserControl x:Class="TestUserControBinding.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:TestUserControBinding"
         ...>


您的第二个示例应该在这一点上起作用。

对于如何设置
DataContext
s存在误解。这对你不利

最终,对用户控件上的
MyText
的绑定不是绑定到控件的
MyText
依赖属性,而是绑定到页面的
DataContext
,并且没有
MyText
属性

让我解释一下


解释当用户控件放在主页面上时,它继承其父控件的
DataContext
StackPanel
)。如果未设置父级的
DataContext
,它将沿着链向上移动到
StackPanel
的父级的
DataContext
(ad Infinium),直到它到达页面的
DataContext
(在您的示例中,它已设置且有效)

当您在主页面(如
上进行绑定时,它会在主页面DataContext上查找
文本
属性,并将依赖属性
MyText
设置为该值。这正是你所期望的,而且很有效

当前状态 因此,代码中用户控件的状态是这样的,它的
DataContext
绑定到页面的
DataContext
,并且设置了
MyText
依赖属性但是内部控制对
MyText
的绑定失败为什么?

用户控件具有父控件的数据上下文,您要求该控件绑定到该数据上下文上的
MyText
属性。没有这样的属性,它就失败了


分辨率

要绑定到控件的实例并从
MyText
属性获取值,只需在控件上放置一个名称(元素名称),如

<User Control x:Class="TestUserControBinding.MyUserControl"
             ...
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             x:Name="ucMyUserControl"
请注意,VS2017/2019实际上会在您命名控件后智能感知
ElementName


仅使用父数据上下文的副作用

没有提到解决方案的原始情况的一个副作用是,您可以将用户控件的绑定绑定到
文本
,而将起作用,因为绑定默认为页面的datacontext。微妙的


这是可行的,从技术上讲,您可以删除dependency属性。如果控件未在项目外部使用,则可以将其设计为绑定到其他命名属性,而不会产生不良影响


然后,所有用户控件都可以成为主页的实际子控件,就像您刚刚将内部XAML粘贴到页面上一样。

@Brian。。。代码“this.DataContext=this;”应注意将DataContext设置为local。不是吗?哦,是的,我错过了。但是如果您正在创建一个
用户控件
,我认为手动设置
数据上下文
不是一个好主意。
DataContext
用于表示从容器继承或分配的上下文。
RelativeSource
绑定允许您在不中断标准
DataContext
继承流的情况下实现所需的结果(绑定到
dependencProperty
)。如果
UserControl
的使用者设置了自己的
DataContext
,则尝试覆盖您的
DataContext
将失败。这正是问题所在。我现在在
MyUserControl
的开始标记中使用
x:Name=“MyName”
而不是将MyUserControl的DataContext设置为自身,并且绑定更改为:
,我认为您的解决方案也应该可以,但它有点笨拙。是的,使用
ElementName
绑定将实现相同的结果,如果你确信其他人不会修改你的代码并错误地更改/删除名称,那么这个答案与问题完全无关。我想知道为什么它被如此高的票数甚至被接受。你混淆了控件和它们的数据上下文。你应该改写你的帖子来解决这个困惑。
<User Control x:Class="TestUserControBinding.MyUserControl"
             mc:Ignorable="d" 
             d:DesignHeight="30" d:DesignWidth="100">
 <Grid>
    <Label Content="{Binding Text}"/>