如何在 WPF 中从另一个 UserControl 绑定或引用一个 UserControl?

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

在我的应用程序中,我有一个 UserControl,它托管另一个 UserControl,如下所示:

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

现在在宿主 BarControl 中,我想计算它相对于宿主 FooControl 控件的位置。目前我正在从 FooControl 后面的代码调用 child 控件的成员,如下所示:

this.NestedControl.ComputeRelativePos(this);

在这个方法中,我计算的位置是这样的:

public void ComputeRelativePos(Control relativeTo)
{
    var pos = this.TranslatePoint(new System.Windows.Point(0, 0), relativeTo);

    // ...
}

现在我想从嵌套的 BarControl 的事件处理程序(例如 SizeChanged)中删除此调用和 re-compute 位置。我想这样做,这样 BarControl 不需要托管在 FooControl 或另一个控件中,显式调用 ComputeRelativePos:

public BarControl()
{
    this.InitializeComponent();
    this.SizeChanged += (sender, args) => 
    {
        this.ComputeRelativePos(this.OuterControl);
    };
}

但是,我不太确定如何为 OuterControl 属性 创建绑定。我已经这样定义了 属性:

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

并在 FooControl 标记中定义绑定,如下所示:

<local:BarControl x:Name="NestedControl" OuterControl="{Binding RelativeSource={RelativeSource Self}}" />

但是 OuterControl 似乎设置不正确:

this.SizeChanged += (sender, args) => this.ComputeRelativePos(this.OuterControl); // this.OuterControl is `null`

我还尝试绑定到 FooControl 实例名称 1:

<local:BarControl x:Name="NestedControl" 
    OuterControl="{Binding RelativeSource={RelativeSource Self}, Path=Name}" />

... 这样我就可以从可视化树中查询它(就像建议的 here),但它也没有用。

所以我的一般问题是,如何访问绑定到 child 的 属性 的 parent 控件?我也会接受解决这个问题的另一种方法,因为我对 XAML/WPF.

相当缺乏经验

提前致谢。

1 当然还要相应地定义 DependencyProperty

我不想详细说明你在做什么以及为什么这样做,但要让依赖项 属性 正常工作,你必须更改:

<local:BarControl x:Name="NestedControl" 
OuterControl="{Binding RelativeSource={RelativeSource Self}, Path=Name}" />

至:

<local:BarControl x:Name="NestedControl" OuterControl="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}" />

说到这里,您的事件处理程序大小更改将在设置依赖项控制之前命中。控件初始化后设置依赖属性。

但是之后当你调整大小时你会看到 relativeTo 被设置为 FooControl。