【发布时间】:2020-06-17 09:31:08
【问题描述】:
我正在使用自定义 UserControls 构建一个 WPF 应用程序,并且我试图了解属性绑定应该如何工作。我什至无法让最基本的绑定工作,而且它很简单,可以提炼成一个小例子,所以我认为有更多 WPF 经验的人可能能够让我走上正轨。
我定义了一个名为 TestControl 的自定义 UserControl,它公开了一个 Foo 属性,该属性旨在在放置 UserControl 时在 XAML 中设置。
TestControl.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace BindingTest
{
public partial class TestControl : UserControl
{
public static readonly DependencyProperty FooProperty = DependencyProperty.Register("Foo", typeof(string), typeof(TestControl));
public string Foo
{
get { return (string)GetValue(FooProperty); }
set { SetValue(FooProperty, value); }
}
public TestControl()
{
InitializeComponent();
}
}
}
TestControl 的标记只是将它定义为一个带有单个按钮的控件,其标签文本显示 Foo 属性的当前值:
TestControl.xaml
<UserControl x:Class="BindingTest.TestControl"
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"
xmlns:local="clr-namespace:BindingTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Button Content="{Binding Foo}" />
</Grid>
</UserControl>
在我的 MainWindow 类中,我只需放置一个 TestControl 实例,并将其 Foo 属性设置为“Hello”。
MainWindow.xaml
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BindingTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:TestControl Foo="Hello" />
</Grid>
</Window>
我希望当我构建和启动这个应用程序时,我会看到一个带有单个按钮的窗口,上面写着“你好”。但是,按钮是空白的:绑定似乎不起作用。
如果我向 TestControl 的按钮添加点击处理程序,我可以验证值是否在后台更新:
// Added to TestControl.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("Button clicked; Foo is '{0}'", Foo);
}
// Updated in TestControl.xaml:
// <Button Content="{Binding Foo}" Click="Button_Click" />
当我点击按钮时,我得到Button clicked; Foo is 'Hello',但 GUI 永远不会更新。我尝试过使用Path=Foo、XPath=Foo 等,以及设置UpdateSourceTrigger=PropertyChanged 并使用NotifyOnTargetUpdated=True 验证更新...似乎没有任何结果导致UI 中的文本被更新以匹配底层属性值,即使属性值似乎更新得很好。
我做错了什么?我觉得我的处理方式只是一个简单而根本的误解。
编辑:
四处逛逛并阅读similar questions 使我找到了一个潜在的解决方法:即,向 TestControl.xaml (x:Name="control") 中的根 UserControl 元素添加一个名称,并更改绑定以明确指定该控件({Binding Foo, ElementName=control})。
我猜默认情况下,Button 元素上的 {Binding Foo} 仅表示 “在此 Button 控件上找到一个名为 'Foo' 的属性”,而我认为它的意思是"在声明此 Button 的上下文中,即在 TestControl 上找到名为 'Foo' 的属性"。
在这里指定一个明确的 ElementName 是最好的解决方法吗?
【问题讨论】:
标签: c# wpf xaml binding user-controls