DependencyObject.InvalidateProperty无法正常工作

基于MSDN的文档 ……

您还可以使用InvalidateProperty强制重新评估对无法实现推荐的INotifyPropertyChanged通知机制的数据源的绑定…

……下面的代码应该有效,但事实并非如此。

public partial class Window1 : Window { private Payload _payload = new Payload(); public Window1() { InitializeComponent(); this.DataContext = _payload; } private void Invalidate(object sender, RoutedEventArgs e) { _payload.Timestamp = DateTime.Now.Add(TimeSpan.FromHours(1)).ToLongTimeString(); Button b = sender as Button; b.InvalidateProperty(Button.ContentProperty); } } public class Payload { private String _payload = DateTime.Now.ToLongTimeString(); public String Timestamp { get { return _payload; } set { _payload = value; } } }  

知道造成这种行为的原因是什么吗?

如你所说,它应该工作,但不是。 但有一个简单的解决方法:

 // Doesn't work: //b.InvalidateProperty(Button.ContentProperty); // Works: BindingOperations.GetBindingExpression(b, Button.ContentProperty).UpdateTarget(); 

我调试到参考源,并且在您的情况下所有InvalidateProperty都会导致将缓存值从BindingExpression重新读取到Button Content属性中。 另外,我不知道什么时候甚至是必要的,但是让BindingExpression重新读取原始属性是没有用的。

由于解决方法既方便又通用,唯一需要进一步努力的是向微软提交错误报告。

是。 我有个主意。

您的代码不起作用的原因是该按钮要求新值,但Binding对象保留旧的,因为它没有获得PropertyChanged通知。 标准场景中的变化链如下所示:

Payload.Timestamp – >绑定对象 – > Button.ContentProperty

在您的方案中,当您调用InvalidateProperty链时:

绑定对象 – > Button.ContentProperty

因此,您应该通过下一个代码通知绑定对象其源已被更改:

  private void Invalidate(object sender, RoutedEventArgs e) { _payload.Timestamp = DateTime.Now.Add(TimeSpan.FromHours(1)).ToLongTimeString(); Button b = sender as Button; BindingExpression be = b.GetBindingExpression(Button.ContentProperty); be.UpdateTarget(); } 

正如您所看到的,我甚至不应该调用InvalidateProperty ,因为更改底层源的Binding机制会自动强制Button刷新内容。

我们从来没有得到它的工作,这是诀窍的function:

 private void InvalidateProperty(DependencyProperty property, FrameworkElement container) { container.SetBinding(property, container.GetBindingExpression(property).ParentBinding); } 

以下是我们称之为:

 private void Invalidate(object sender, RoutedEventArgs e) { _payload.Timestamp = DateTime.Now.Add(TimeSpan.FromHours(1)).ToLongTimeString(); Button b = sender as Button; //b.InvalidateProperty(Button.ContentProperty); this.InvalidateProperty(Button.ContentProperty, b); } 

我还必须将DataContext设置为_payload。