WPF中Button的SourceUpdated事件未触发,绑定源变更未同步至内容
WPF绑定问题:UI未更新且SourceUpdated事件未触发
问题代码
XAML文件
<Window x:Class="notify_on_source_updated.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:notify_on_source_updated" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Button x:Name="myButton" Click="myButton_Click" /> </Window>
代码后置文件
namespace notify_on_source_updated { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public string SourceText {get; set;} public MainWindow() { InitializeComponent(); SourceText = "test"; Binding binding = new Binding(); binding.Source = SourceText; binding.NotifyOnSourceUpdated=true; myButton.SourceUpdated += myButton_SourceUpdated; myButton.SetBinding(ContentControl.ContentProperty, binding); } private void myButton_Click(object sender, RoutedEventArgs e) { SourceText = "changed"; } private void myButton_SourceUpdated(object sender, DataTransferEventArgs e) { MessageBox.Show("Updated!"); } } }
疑惑与解答
1. 点击按钮后Button Content未更新为"changed"
原因:SourceText是普通CLR属性,未实现INotifyPropertyChanged接口。WPF的数据绑定依赖属性变更通知同步UI,当属性值修改时,如果没有触发PropertyChanged事件,WPF无法感知值的变化,因此不会更新UI。
2. SourceUpdated事件从未触发
原因:你混淆了SourceUpdated事件的触发逻辑:
SourceUpdated仅在目标控件的值回传给源对象时触发(比如TwoWay绑定下,用户修改TextBox的Text,值同步到源属性的场景)。- 你的绑定是默认的
OneWay模式(仅源→目标同步),且操作是手动修改源属性值,这种场景下不会触发SourceUpdated。若要监听源属性更新到目标的动作,应该使用TargetUpdated事件,并设置binding.NotifyOnTargetUpdated=true。
修正方案
步骤1:实现INotifyPropertyChanged接口
让窗口类实现接口,给SourceText添加属性变更通知:
namespace notify_on_source_updated { public partial class MainWindow : Window, INotifyPropertyChanged { private string _sourceText; public string SourceText { get => _sourceText; set { if (_sourceText != value) { _sourceText = value; OnPropertyChanged(nameof(SourceText)); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public MainWindow() { InitializeComponent(); SourceText = "test"; // 绑定源改为当前窗口实例,而非直接绑定SourceText字段 Binding binding = new Binding(nameof(SourceText)) { Source = this, // 启用目标更新通知(源→目标同步时触发) NotifyOnTargetUpdated = true }; // 绑定TargetUpdated事件 myButton.TargetUpdated += MyButton_TargetUpdated; myButton.SetBinding(ContentControl.ContentProperty, binding); } private void myButton_Click(object sender, RoutedEventArgs e) { SourceText = "changed"; } private void MyButton_TargetUpdated(object sender, DataTransferEventArgs e) { MessageBox.Show("目标已更新!"); } } }
步骤2:明确绑定方向与事件的对应关系
- OneWay绑定:源→目标,源变化时更新目标,对应
TargetUpdated事件(需设置NotifyOnTargetUpdated=true)。 - TwoWay绑定:源↔目标,目标变化回传源时触发
SourceUpdated事件(需设置NotifyOnSourceUpdated=true),源变化更新目标时触发TargetUpdated。
若要测试SourceUpdated,可使用TextBox的TwoWay绑定示例:
// 构造函数中替换绑定逻辑 TextBox textBox = new TextBox(); Binding binding = new Binding(nameof(SourceText)) { Source = this, Mode = BindingMode.TwoWay, NotifyOnSourceUpdated = true }; textBox.SourceUpdated += TextBox_SourceUpdated; textBox.SetBinding(TextBox.TextProperty, binding); // 将textBox添加到窗口布局 this.Content = textBox;
此时在TextBox中输入文本,值同步到SourceText时会触发SourceUpdated事件。
内容的提问来源于stack exchange,提问作者user32882
相关产品推荐
相关产品推荐

