19

我创建了一个带有一些 DependencyProperties 的 UserControl(在此示例中只有一个字符串属性)。当我实例化 UserControl 时,我可以设置 UserControl 的属性并按预期显示。当我尝试通过 Binding 替换静态文本时,没有显示任何内容。

我的 UserControl 如下所示:

<User Control x:Class="TestUserControBinding.MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="30" d:DesignWidth="100">
    <Grid>
    <Label Content="{Binding MyText}"/>
  </Grid>
</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

  }
}

当我在 MainWindow 中尝试此操作时,一切都按预期进行:

<Window x:Class="TestUserControBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestUserControBinding"
        Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <local:MyUserControl MyText="Hello World!"/>
  </StackPanel>
</Window>

但这不起作用:

<Window x:Class="TestUserControBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestUserControBinding"
        Title="MainWindow" Height="350" Width="525">
  <StackPanel>
    <local:MyUserControl MyText="{Binding Path=Text}"/>
    <Label Content="{Binding Path=Text}"/>
  </StackPanel>
</Window>

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

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

4

2 回答 2

28

在您的以下绑定中UserControl

<Label Content="{Binding MyText}"/>

我不确定如何将文本直接设置为 MyText 属性。你必须DataContextUserControl某个地方设置它才能工作。

无论如何,此绑定是问题所在 - 据我了解您的情况,您不想绑定到 的DataContextUserControl因为它不一定具有 MyText 属性。您想绑定到UserControl自身,特别是DependencyProperty您创建的。为此,您需要使用RelativeSource绑定,如下所示:

<Label Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=MyText}"/>

这会将可视化树向上导航到 MyUserControl,然后在那里找到 MyText 属性。它不会依赖于DataContext,它将根据您放置的位置而改变UserControl

在这种情况下,local指的是您需要在以下位置定义的命名空间UserControl

<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"
         ...>

你的第二个例子应该在那个时候起作用。

于 2013-06-07T13:57:39.417 回答
5

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

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

让我解释


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

当您在主页上绑定时,例如它会在主页 DataContext 上<local:MyUserControl MyText="{Binding Path=Text}"/>查找属性并将依赖属性设置为该值。这是您所期望的,并且有效!TextMyText

当前状态 所以代码中用户控件的状态是这样的,它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"

然后正确地将绑定从默认路径转移DataContext名为ucMyUserControl. 如:

  <Label Content="{Binding MyText, ElementName=ucMyUserControl }"/>

请注意,VS2017/2019 实际上会ElementName在您命名控件后进行智能感知。


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

没有提到解决方案的原始情况的副作用是,您可以将用户控件的绑定绑定到Text它并且它将起作用,因为绑定默认为页面的数据上下文。微妙的...

<User Control x:Class="TestUserControBinding.MyUserControl"
             mc:Ignorable="d" 
             d:DesignHeight="30" d:DesignWidth="100">
 <Grid>
    <Label Content="{Binding Text}"/>

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

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

于 2019-10-02T14:52:40.130 回答