C# 如何通过绑定引用WPF UserControl中的自定义属性值?
我正在构建一个带有自定义用户控件的WPF应用程序,并试图了解属性绑定应该如何工作。我甚至连最基本的绑定都做不到,而且它很简单,可以提炼成一个小例子,所以我认为有更多WPF经验的人可能会让我走上正确的道路 我已经定义了一个名为TestControl的自定义UserControl,它公开了一个Foo属性,该属性打算在放置UserControl时在XAML中设置 TestControl.xaml.csC# 如何通过绑定引用WPF UserControl中的自定义属性值?,c#,wpf,xaml,binding,user-controls,C#,Wpf,Xaml,Binding,User Controls,我正在构建一个带有自定义用户控件的WPF应用程序,并试图了解属性绑定应该如何工作。我甚至连最基本的绑定都做不到,而且它很简单,可以提炼成一个小例子,所以我认为有更多WPF经验的人可能会让我走上正确的道路 我已经定义了一个名为TestControl的自定义UserControl,它公开了一个Foo属性,该属性打算在放置UserControl时在XAML中设置 TestControl.xaml.cs 使用System.Windows; 使用System.Windows.Controls; 命名空间绑
使用System.Windows;
使用System.Windows.Controls;
命名空间绑定测试
{
公共部分类TestControl:UserControl
{
public static readonly dependencProperty FooProperty=dependencProperty.Register(“Foo”、typeof(string)、typeof(TestControl));
公共字符串Foo
{
获取{return(string)GetValue(FooProperty);}
set{SetValue(FooProperty,value);}
}
公共测试控制()
{
初始化组件();
}
}
}
TestControl的标记仅将其定义为具有单个按钮的控件,其标签文本显示Foo属性的当前值:
TestControl.xaml
在我的MainWindow类中,我只放置了一个TestControl实例,其Foo属性设置为“Hello”
main window.xaml
我希望当我构建并启动这个应用程序时,我会看到一个窗口,上面有一个按钮,上面写着“你好”。但是,按钮是空的:绑定似乎不起作用
如果我向TestControl的按钮添加一个click处理程序,我可以验证该值是否正在幕后更新:
//添加到TestControl.xaml.cs:
私有无效按钮\u单击(对象发送者,路由目标e)
{
WriteLine(“单击按钮;Foo是{0}'”,Foo);
}
//在TestControl.xaml中更新:
//
当我点击按钮时,我会点击按钮;Foo是“Hello”
,但GUI从不更新。我尝试过使用Path=Foo
,XPath=Foo
等,以及设置UpdateSourceTrigger=PropertyChanged
并使用NotifyOnTargetUpdated=True
验证更新。。。似乎没有任何东西会导致UI中的文本被更新以匹配基础属性值,即使属性值似乎得到了很好的更新
我做错了什么?我觉得在我处理这件事的过程中,有一个简单而根本的误解
编辑:
仔细研究和阅读之后,我找到了一个潜在的解决方案:即,在TestControl.xaml(x:name=“control”
)中向根UserControl元素添加一个名称,并更改绑定以显式指定该控件({binding Foo,ElementName=control}
)
我猜测,默认情况下,Button元素上的{Binding Foo}
仅表示“在这个按钮控件上查找名为'Foo'的属性”,而我假设它的意思是“在声明这个按钮的上下文中,即在TestControl上查找名为'Foo'的属性”
指定显式元素名是这里的最佳解决方案吗?您必须将绑定的源对象设置为UserControl实例,例如:
<Button Content="{Binding Foo, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
或
...
如果有许多这样的绑定,还可以将UserControl的XAML中顶级元素的DataContext设置为UserControl实例:
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<Button Content="{Binding Foo}" />
<Button Content="{Binding Bar}" />
</Grid>
但是,您必须避免设置UserControl的DataContext(这通常是“专家”博客作者推荐的),因为这会破坏UserControl属性的基于DataContext的绑定,如
<local:TestControl Foo="{Binding SomeFoo}" />
漂亮!覆盖整个控件的DataContext是我希望可能的方法。一般来说,绑定具有“DataContext”的概念是我所缺少的难题中的一部分。感谢您对UserControl/DataContext陷阱的修复、词汇表和提示。覆盖整个控件的DataContext正是您应该避免的!看看上面的解释。啊,我可以看出我的措辞会有多么误导。我只是指第二个示例,即在根控件下的顶级元素(即本例中的网格)上设置DataContext。
<local:TestControl Foo="{Binding SomeFoo}" />