我创建了一个带有一些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>
标签的行为是正确的,因此“Text”属性没有问题
我的错误是什么?我思考了几个小时,但找不到任何我忘记的东西。
答案 0 :(得分:14)
在UserControl
中使用以下绑定:
<Label Content="{Binding MyText}"/>
我不确定如何直接将文本设置为MyText属性。您必须在DataContext
某处设置UserControl
才能使其生效。
无论如何,这个绑定是问题 - 因为我理解你的场景,你不想绑定到DataContext
的{{1}},因为它不一定具有MyText属性。您想要绑定到UserControl
本身,特别是您创建的UserControl
。为此,您需要使用DependencyProperty
绑定,如下所示:
RelativeSource
这会将可视化树导航到MyUserControl,然后在那里找到MyText属性。它不依赖于<Label Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=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"
...>
你的第二个例子应该在那时起作用。
答案 1 :(得分:0)
对DataContext
的设置方式有误解。这对你不利...
最终,与用户控件上的MyText
的绑定未未绑定到控件的MyText
的依赖项属性,而是被绑定到页面的DataContext
,并且没有MyText
属性。
让我解释一下
说明:将用户控件放在您的主页上时,它将继承其控件父级的DataContext
(StackPanel
)。如果未设置父级的DataContext
,它将向上移动到StackPanel
父级的DataContext
(在Infinium中),直到到达页面的DataContext
(< em>在您的示例中已设置且有效)。
在诸如<local:MyUserControl MyText="{Binding Path=Text}"/>
之类的主页上进行绑定时,它将在主页DataContext上寻找Text
属性,并将依赖项属性MyText
设置为该值。 您期望的是什么,它会起作用!
当前状态
因此,您的代码中用户控件的状态是这样,其DataContext
绑定到页面的DataContext
并设置了MyText
依赖项属性。 但是,内部控制与MyText
的绑定失败。 为什么?
用户控件具有父级的数据上下文,并且您要控件绑定到那个数据上下文上的MyText
属性。没有这样的属性,它将失败。
解决方案
要绑定到控件的实例并从MyText
属性获取值,只需在控件上放置一个名称(元素名称),例如< / p>
<User Control x:Class="TestUserControBinding.MyUserControl"
...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
x:Name="ucMyUserControl"
,然后正确地将绑定从默认的DataContext
转移到名为ucMyUserControl
的 elementnamed 命名实例。如:
<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粘贴到页面上一样。