WPF相对源行为

4

我在理解 RelativeSource 绑定行为方面遇到了一些问题。 下面的代码将 Label 的内容正确地绑定到 StackPanel 的标记:

<Window x:Class="Binding_RelativeSource.MainWindow" Tag="Window Tag">
    <Grid Tag="Grid Tag">
        <StackPanel Tag="StackPanel Tag" Height="100" HorizontalAlignment="Left" Margin="156,97,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="200">
            <Label Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=StackPanel},FallbackValue=BindingFailed}" Height="28" Name="label1" />
        </StackPanel>
    </Grid>
</Window>

上述代码没有绑定Grid标签,如果我改变AncestorType=GridAncestorLevel=2。 我有两个问题:
  1. 我认为我应该将AncestorLevel更改为2,以绑定到网格。但是它适用于AncestorLevel=1. 为什么?

  2. 我也无法将标签绑定到Window标记。请指教。

2个回答

28
"AncestorLevel"用于查找正确的祖先元素进行绑定,这是因为可能会存在多个相同类型的祖先元素。
以下是一个说明此情况的场景:
<Grid Tag="AncestorLevel 3">
    <Grid Tag="AncestorLevel 2">
        <Grid Tag="AncestorLevel 1">
            <StackPanel Tag="StackPanel Tag" Height="100" HorizontalAlignment="Left" Margin="156,97,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="200">
                <Label Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=Grid},FallbackValue=BindingFailed}" Height="28"  />
                <Label Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=2,AncestorType=Grid},FallbackValue=BindingFailed}" Height="28"  />
                <Label Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=3,AncestorType=Grid},FallbackValue=BindingFailed}" Height="28"  />
            </StackPanel>
        </Grid>
    </Grid>
</Grid>

结果:

enter image description here

替代方法

但是您可以使用ElementName绑定来简化代码,这将使用元素的Name

例如:

<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Name="MyWindow" Tag="This is the window">
    <Grid Name="Grid1" Tag="First grid">
        <Grid Name="Grid2" Tag="Second grid">
            <Grid Name="Grid3" Tag="ThirdGrid">
                <StackPanel Name="stackPanel1" Tag="StackPanel Tag" Height="160" HorizontalAlignment="Left" Margin="156,97,0,0" VerticalAlignment="Top" Width="200">
                    <Label Content="{Binding ElementName=MyWindow, Path=Tag}" Height="28"  />
                    <Label Content="{Binding ElementName=Grid1, Path=Tag}" Height="28"  />
                    <Label Content="{Binding ElementName=Grid2, Path=Tag}" Height="28"  />
                    <Label Content="{Binding ElementName=Grid3, Path=Tag}" Height="28"  />
                    <Label Content="{Binding ElementName=stackPanel1, Path=Tag}" Height="28"  />
                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</Window>

结果:

enter image description here

如果您想绑定回到 Window,您仍然可以使用 FindAncestor
<Window x:Class="WpfApplication9.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Tag="This is the window">
    <Grid>
        <StackPanel Height="100" HorizontalAlignment="Left" Margin="156,97,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="200">
            <Label Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window},FallbackValue=BindingFailed}" Height="28"  />
        </StackPanel>
    </Grid>

结果:

enter image description here


  1. 在我的情况下,如果我不提及AncestorLevel属性,那么就应该没问题。我验证过了,在没有设置AncestorLevel属性的情况下,StackPanel和Grid都可以正常工作。但是对于Window来说,它却不能正常工作,你能告诉我原因吗?
  2. 我理解ElementName属性绑定,这个没有问题。但是,我想知道为什么RelativeSource绑定对于StackPanel和Grid有效,而对于Window无效。请给我建议。
- WpfBee
它适用于窗口,Content = "{Binding Path = Tag,RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = Window} 在这里运行良好。 - sa_ddam213
哦,是的。这对我也起作用了。但是对于窗口来说,它是在运行时绑定的。对于Grid和StackPanel,它实际上是在编译时绑定的。有特定的原因吗? - WpfBee
我已经按照你更新的答案做了相同的事情。但它在运行时更新绑定。我正在使用VS2010。 - WpfBee
我的最终结论是:这是VS2010设计器的问题,它不会更新Window标记的RelativeSource绑定。它会在设计器中更新其他控件(我已经检查了Grid和StackPanel),但对于Window,它只会在运行时更新。微软在VS2012中做了一个解决方法。 - WpfBee
显示剩余4条评论

2

我的最终结论是:这是VS2010设计器的问题,它不会更新Window标记的RelativeSource绑定。它会更新其他控件(我用Grid和StackPanel进行了检查)的绑定,但对于Window,它只会在运行时更新。Microsoft在VS2012中为此做了解决方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接