WPF RelativeSource behavior
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:
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:
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:
Related videos on Youtube
WpfBee
Updated on September 12, 2020Comments
-
WpfBee over 3 years
I have some problems in understanding
RelativeSource
binding behavior. Below is the code that bindsLabel
content toStackPanel
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 changeAncestorType=Grid
andAncestorLevel=2
. I have 2 questions:I think I should change AncestorLevel to 2, to bind to Grid. But it worked for
AncestorLevel=1
. Why?I am also not able to bind label to Window tag.Please suggest.
-
WpfBee about 11 years1. 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 about 11 yearsIt does work for window,
Content="{Binding Path=Tag,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}
works fine here -
WpfBee about 11 yearsOh, 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 about 11 yearsWhat VS version are you using?
-
WpfBee about 11 yearsI have done the same as your updated answer. But it updates binding at run time. I am using VS2010.
-
WpfBee about 11 years
-
sa_ddam213 about 11 yearsHmm.. 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 about 11 yearsFinal 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 over 7 yearsYour 'Alternative Method' helped me tremendously. Thanks!