我在尝试在代码中短时间设置绑定时注意到了这一点。其实我只是想获取绑定提供的值。所以我设置绑定,获取目标属性的值并立即清除绑定。一切都很好,直到为绑定设置了模式 FindAncestor 的 RelativeSource。在这种情况下,目标属性返回其默认值。
经过一些调试后,我发现 FindAncestor 绑定的 BindingExpression 的属性 Status 设置为 Unattached。对于其他类型的绑定,BindingExpression.Status 设置为 Active。
我写了一些代码来说明这一点。
Window1.xaml
<Window x:Class="Wpf_SetBindingInCode.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="Window"
Title="Window1"
Height="300" Width="300"
DataContext="DataContext content">
<StackPanel>
<Button Content="Set binding" Click="SetBindingButtonClick"/>
<TextBlock x:Name="TextBlock1"/>
<TextBlock x:Name="TextBlock2"/>
<TextBlock x:Name="TextBlock3"/>
</StackPanel>
</Window>
Window1.xaml.cs
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void SetBindingButtonClick(object sender, RoutedEventArgs e)
{
Binding bindingToRelativeSource = new Binding("DataContext")
{
RelativeSource = new RelativeSource { Mode = RelativeSourceMode.FindAncestor, AncestorType = typeof(Window1) },
};
Binding bindingToElement = new Binding("DataContext")
{
ElementName = "Window"
};
Binding bindingToDataContext = new Binding();
BindingOperations.SetBinding(TextBlock1, TextBlock.TextProperty, bindingToRelativeSource);
BindingOperations.SetBinding(TextBlock2, TextBlock.TextProperty, bindingToElement);
BindingOperations.SetBinding(TextBlock3, TextBlock.TextProperty, bindingToDataContext);
Trace.WriteLine("TextBlock1.Text = \"" + TextBlock1.Text + "\"");
Trace.WriteLine("TextBlock2.Text = \"" + TextBlock2.Text + "\"");
Trace.WriteLine("TextBlock3.Text = \"" + TextBlock3.Text + "\"");
var bindingExpressionBase1 = BindingOperations.GetBindingExpressionBase(TextBlock1, TextBlock.TextProperty);
var bindingExpressionBase2 = BindingOperations.GetBindingExpressionBase(TextBlock2, TextBlock.TextProperty);
var bindingExpressionBase3 = BindingOperations.GetBindingExpressionBase(TextBlock3, TextBlock.TextProperty);
Trace.WriteLine("bindingExpressionBase1.Status = " + bindingExpressionBase1.Status);
Trace.WriteLine("bindingExpressionBase2.Status = " + bindingExpressionBase2.Status);
Trace.WriteLine("bindingExpressionBase3.Status = " + bindingExpressionBase3.Status);
}
}
上面的代码产生以下输出:
TextBlock1.Text = ""
TextBlock2.Text = "DataContext content"
TextBlock3.Text = "DataContext content"
bindingExpressionBase1.Status = Unattached
bindingExpressionBase2.Status = Active
bindingExpressionBase3.Status = Active
但尽管如此,表单上的所有三个 TextBlock 都具有预期值 - “DataContext 内容”。
所以我的问题是:
为什么在调用 BindingOperations.SetBinding(...) 后,RelativeSourceMode.FindAncestor 绑定不立即提供值?
有没有办法强制这种绑定更新目标属性?我试图调用 bindingExpression.UpdateTarget() - 它不像预期的那样工作。