WPF RelativeSource behavior

23,029

Solution 1

Final conclusion from my end: It was VS2010 designer problem that it does not update RelativeSource binding for Window tag. It updates binding for other controls (I checked with Grid & StackPanel) in designer but for Winodw it gets updated at run time. Microsoft has done workaround in VS2012 for it.

Solution 2

The AncestorLevel is use to find the correct ancestor to bind to, this is because there could be more than one ancestor of that type.

Here is a scenario that shows this:

<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>

Result:

enter image description here

Alternative Method

But you can simplify the code by using ElementName binding, this uses the Name of the element

Example:

<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>

Result:

enter image description here

If you want to bind back to the Window you can still use 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>

Result:

enter image description here

Share:
23,029

Related videos on Youtube

WpfBee
Author by

WpfBee

Updated on September 12, 2020

Comments

  • WpfBee
    WpfBee over 3 years

    I have some problems in understanding RelativeSource binding behavior. Below is the code that binds Label content to StackPanel Tag correctly:

    <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>
    

    Above code does not bind Grid Tag, if I change AncestorType=Grid and AncestorLevel=2. I have 2 questions:

    1. I think I should change AncestorLevel to 2, to bind to Grid. But it worked for AncestorLevel=1. Why?

    2. I am also not able to bind label to Window tag.Please suggest.

  • WpfBee
    WpfBee about 11 years
    1. It means in my case if I do not mention AncestorLevel, it should be fine. I verified it, it's working for StackPanel & Grid without setting AncestorLevel property. But it's not working for Window, why? Can you give me the reason, please? 2. I understand, ElementName property binding. I have no problem with that. But, I want to know the reason, why RelativeSource binding is working for StackPanel and Grid, but not for Window. Please suggest.
  • sa_ddam213
    sa_ddam213 about 11 years
    It does work for window, Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window} works fine here
  • WpfBee
    WpfBee about 11 years
    Oh, yes. It also worked for me. But it is binding at run time for window. For Grid & StackPanel it does at compile time. Any specific reason?
  • sa_ddam213
    sa_ddam213 about 11 years
    What VS version are you using?
  • WpfBee
    WpfBee about 11 years
    I have done the same as your updated answer. But it updates binding at run time. I am using VS2010.
  • WpfBee
    WpfBee about 11 years
  • sa_ddam213
    sa_ddam213 about 11 years
    Hmm.. I tried in VS2010 and it did not work in the designer, I am using VS2012 and it does work in the designer, But my assumtion is that the Window is not reallt instansiated yet in the designer as the window we see in the designer in not a real window, so perhaps they added a workaround in VS2012 for this.
  • WpfBee
    WpfBee about 11 years
    Final conclusion from my end: It was VS2010 designer problem that it does not update RelativeSource binding for Window tag. It updates binding for other controls (I checked with Grid & StackPanel) in designer but for Winodw it gets updated at run time. Microsoft has done workaround in VS2012 for it.
  • Viking
    Viking over 7 years
    Your 'Alternative Method' helped me tremendously. Thanks!