WPF Multibinding RelativeSource Findancestor 评估性能

WPF Multibinding RelativeSource Findancestor evaluation performance

对于以下 MultiBinding 表达式,如果多次更改 PropB,绑定引擎将搜索 DataGrid 祖先多少次?

<MultiBinding Converter="{StaticResource TestConverter}"> 
    <Binding Path="PropA"/> 
    <Binding Path="PropB" /> 
    <Binding Path="DataContext.Sub.PropertyC" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=DataGrid}" /> 
</MultiBinding>

如果 PropertyC(及其路径)从未改变,它是否只搜索一次?还是每次更改多重绑定中的一个属性时它都会搜索祖先?假设每个 属性.

上都有更改通知

我认为唯一可行的测试方法是实际删除控件以查看它是否找到了正确的控件。

这样测试,无论是否使用MultiBinding,看起来好像只评估一次。

<Window x:Class="RelativeTest.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"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel x:Name="Stack">
        <TextBlock x:Name="TB1" Text="Foo" />
        <TextBlock x:Name="TB2" Text="Bar" />

        <Border BorderThickness="1" BorderBrush="Black" />

        <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=StackPanel}, Path=Children[0].Text}" 
                   Foreground="Red" />

        <TextBlock Foreground="Blue">
            <TextBlock.Text>
                <MultiBinding StringFormat="{}{2}">
                    <Binding ElementName="TB1" Path="Text" />
                    <Binding ElementName="TB2" Path="Text" />
                    <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=StackPanel}" Path="Children[0].Text" />
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
        <Button Click="ButtonBase_OnClick" Content="Remove 1st Child" />
    </StackPanel>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
        Stack.Children.Remove(Stack.Children[0]);
        TB1.Text = "You'll see me if I am looked up once.";
        TB2.Text = "You'll see me twice if I am re-evaulated each time";
    }
}

当运行最初你会看到:

单击该按钮时,它将删除第一个子项并更改 TextBlocks 以显示更新的文本以指示它现在绑定到哪个子项。