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"
没有问题我错在哪里?
在您的UserControl
中使用以下绑定:
<Label Content="{Binding MyText}"/>
我不确定如何将文本直接设置为MyText属性。您必须在UserControl
上的某个地方设置DataContext
才能使其工作。
无论如何,这个绑定是问题-正如我所理解的场景,您不想绑定到UserControl
的DataContext
,因为那不一定有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粘贴到页面上。