In my application I have a UserControl
, that hosts another UserControl
, like this:
<UserControl x:Class="FooControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp">
<local:BarControl x:Name="NestedControl" />
</UserControl>
Now within the hosted BarControl
, I want to compute the position of it, relative to the hosting FooControl
control. Currently I am calling a member of the child control from FooControl
s code behind, like so:
this.NestedControl.ComputeRelativePos(this);
and within this method, I compute the position like this:
public void ComputeRelativePos(Control relativeTo)
{
var pos = this.TranslatePoint(new System.Windows.Point(0, 0), relativeTo);
// ...
}
Now I want to eliminate this call and re-compute the position from event handlers (like for example SizeChanged
) of the nested BarControl
. I want to do this, so that BarControl
does not require to be hosted within a FooControl
or another control, explicitly calling ComputeRelativePos
:
public BarControl()
{
this.InitializeComponent();
this.SizeChanged += (sender, args) =>
{
this.ComputeRelativePos(this.OuterControl);
};
}
However, I am not quite sure how to create a binding for the OuterControl
property. I have defined the property like so:
public Control OuterControl
{
get { return this.GetValue(OuterControlProperty) as Control; }
set { this.SetValue(OuterControlProperty, value); }
}
public static readonly DependencyProperty OuterControlProperty =
DependencyProperty.Register("OuterControl", typeof(Control), typeof(BarControl), new UIPropertyMetadata(null));
and defined the binding in the FooControl
markup like this:
<local:BarControl x:Name="NestedControl" OuterControl="{Binding RelativeSource={RelativeSource Self}}" />
but the OuterControl
does not appear to be set correctly:
this.SizeChanged += (sender, args) => this.ComputeRelativePos(this.OuterControl); // this.OuterControl is `null`
I also tried binding to the FooControl
instance name 1:
<local:BarControl x:Name="NestedControl"
OuterControl="{Binding RelativeSource={RelativeSource Self}, Path=Name}" />
... so that I can query it from the visual tree (like suggested here), but it did not work either.
So my general question is, how do I access a parent control, that is bound to a child's property? I would also accept an alternative approach to this problem, since I'm fairly inexperienced with XAML/WPF.
Thanks in advance. 🙂
1 And of course defining the DependencyProperty
accordingly.
I don't want to go into the details of what you are doing and why, but to get the dependency property working you have to change:
<local:BarControl x:Name="NestedControl"
OuterControl="{Binding RelativeSource={RelativeSource Self}, Path=Name}" />
to:
<local:BarControl x:Name="NestedControl" OuterControl="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />
When this is said, your event handler size changed will be hit before the dependency control is set. Dependency properties are set after the control is initialized.
But afterward when you resize you will see that relativeTo is set to FooControl.