简体   繁体   中英

How to bind or reference a UserControl from another UserControl in WPF?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM