Based on the documentation via MSDN...
You can also use InvalidateProperty to force re-evaluation of a binding against a data source that is not a
we never got it working either, here's the function which does the trick:
private void InvalidateProperty(DependencyProperty property,
FrameworkElement container)
{
container.SetBinding(property,
container.GetBindingExpression(property).ParentBinding);
}
And here's how we call it:
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);
}
I also had to set DataContext to _payload.
As you mentioned, it ought to work but doesn't. But there is a simple workaround:
// Doesn't work:
//b.InvalidateProperty(Button.ContentProperty);
// Works:
BindingOperations.GetBindingExpression(b, Button.ContentProperty).UpdateTarget();
I debugged into the reference source and all InvalidateProperty
does in your situation is cause a cached value to be re-read from the BindingExpression
into the Button
Content
property. Offhand, I don't know when this would even be necessary but it's not useful to get the BindingExpression
to re-read the raw property.
Since the workaround is convenient and general, the only further effort warranted is filing a bug report with Microsoft.
Yes. I have an idea.
The reason why your code doesn't work is that button asks for new value, but Binding object holds the old one as it hasn't got PropertyChanged notification. The changes chain in standart scenario looks like:
Payload.Timestamp -> Binding object -> Button.ContentProperty
In your scenario, when you call InvalidateProperty
chain is:
Binding object -> Button.ContentProperty
So, you should notify binding object that its source has been changed with next code:
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();
}
As you can see, I even shouldn't call InvalidateProperty
, because the Binding mechanizm due to changed underlying source will automatically force Button to refresh content.