Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF RelativeSource behavior

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.

like image 766
WpfBee Avatar asked Nov 27 '22 14:11

WpfBee


2 Answers

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

like image 73
sa_ddam213 Avatar answered Dec 05 '22 00:12

sa_ddam213


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.

like image 32
WpfBee Avatar answered Dec 05 '22 00:12

WpfBee