Bind control property from the inner control

114 views Asked by At

I have a control that contains another control. InnerControl contains some property like ButtonVisibility. The simplified InnerControl code sample is below

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

This is the code of MainControl which contains InnerControl as a Dependency Property

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)
    {
        //...
    }
}

I have two different templates for this controls in the 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>

This is the way how could I use this controls

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

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

I need to change the state of my MainControl after button's click. That's why it is located in MainControl template.

So, could any body gives me an advise how to bind ButtonVisibility from the MyInner to the MyButton on MainControl?

3

There are 3 answers

2
James Harcourt On BEST ANSWER

You need to bind directly to the "ButtonVisibility" property of InnerControl, like this:

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

WPF AttachedProperty helps to change the state of your main control from your inner control.

1
Nitin On

Like @james mentioned, you will have to use RelativeSource to bind to either TemplatedParent or to any Type in the visual tree by specifying type like:

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