从内部控件绑定控件属性

Bind control property from the inner control

我有一个包含另一个控件的控件。 InnerControl 包含一些 属性,例如 ButtonVisibility。简化的 InnerControl 代码示例如下

public class InnerControl : ControlBase
{
    //...
    public Visibility ButtonVisibility
    {
        get { return (Visibility)GetValue(ButtonVisibility); }
        set { SetValue(ButtonVisibility, value); }
    }

    public static readonly DependencyProperty ButtonVisibility =
        DependencyProperty.Register(
            "ButtonVisibility",
            typeof (Visibility),
            typeof (InnerControl),
            new PropertyMetadata(Visibility.Collapsed));
}

这是包含 InnerControl 作为依赖项的 MainControl 代码 属性

public class MainControl : ControlBase
{
    //...
    public InnerControl MyInner
    {
        get { return (InnerControl) GetValue(MyInnerProperty); }
        set { SetValue(MyInnerProperty, value); }
    }

    public static readonly DependencyProperty MyInnerProperty =
        DependencyProperty.Register(
            "MyInner",
            typeof (InnerControl),
            typeof (MainControl),
            new PropertyMetadata(null, OnMyInnerPropertyChanged));

    private static void OnMyInnerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //...
    }
}

我在 Generic.xaml

中有两个不同的控件模板
<Style TargetType="local:InnerControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:InnerControl">
                <Grid x:Name="ContainerGrid">
                    <!-- some markup -->
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="local:MainControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MainControl">
                <Grid x:Name="RootGrid">

                    <Button x:Name="MyButton" Visibility="{TemplateBinding ???}"/>

                    <ContentControl x:Name="MyInnerControl" Content="{TemplateBinding MyInner}" />

                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

这就是我如何使用此控件的方式

<controls:MainControl>
    <controls:MainControl.MyInner>
        <controls:InnerControl ButtonVisibility="Visible">
            <!-- some markup -->                
        </controls:InnerControl>
    </controls:MainControl.MyInner>

    <!-- some markup -->
</controls:MainControl>

我需要在单击按钮后更改 MainControl 的状态。这就是它位于 MainControl 模板中的原因。

那么,任何人都可以建议我如何将 ButtonVisibilityMyInner 绑定到 MainControl 上的 MyButton 吗?

WPF 附加属性有助于从内部控件更改主控件的状态。

你需要直接绑定到InnerControl的"ButtonVisibility" 属性,像这样:

<Button x:Name="MyButton" 
        Visibility="{Binding MyInner.ButtonVisibility, 
                             RelativeSource={RelativeSource TemplatedParent}}"/>

就像@james 提到的那样,您必须使用 RelativeSource 绑定到 TemplatedParent 或可视化树中的任何类型,方法是指定如下类型:

<Button x:Name="MyButton" Content="MyButton" 
       Visibility="{Binding Path=MyInner.ButtonVisibility, 
                            RelativeSource={RelativeSource FindAncestor,
                                           AncestorType={x:Type controls:MainControl}}}"/>