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。