Binding to UserControl DependencyProperty

本文关键字:DependencyProperty UserControl to Binding | 更新日期: 2023-09-27 18:17:19

我创建了一个UserControl与一些DependencyProperties(在这里的例子中只有一个字符串属性)。当我实例化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
    
  }
}

当我在主窗口中尝试时,一切都如预期:

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

标签的行为是正确的,所以属性"Text"

没有问题

我错在哪里?

Binding to UserControl DependencyProperty

在您的UserControl中使用以下绑定:

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

我不确定如何将文本直接设置为MyText属性。您必须在UserControl上的某个地方设置DataContext才能使其工作。

无论如何,这个绑定是问题-正如我所理解的场景,您不想绑定到UserControlDataContext,因为那不一定有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"
         ...>

你的第二个例子应该在这一点上工作

对于DataContext s的设置存在误解。这对你不利……

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

让我来解释


说明当用户控件放在主页上时,它继承其控件父控件的DataContext (StackPanel)。如果父节点的DataContext没有设置,它将向上移动到StackPanel的父节点的DataContext(和Infinium),直到它到达页面的DataContext (,在您的示例中已设置并有效)。

当你在主页上绑定时,比如<local:MyUserControl MyText="{Binding Path=Text}"/>,它会在主页的DataContext上查找Text属性,并将依赖属性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"

,然后将绑定从默认的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粘贴到页面上。

相关文章:
  • 没有找到相关文章