Home > Back-end >  How to change visibility of child control in my customized Control?
How to change visibility of child control in my customized Control?

Time:04-01

I inherited my Control for HeaderedContentControl. I need to hide the child control when user clicked the parent control, but I do not know how to access its child control.

Here is my code.

public class MyHeaderedContentControl : HeaderedContentControl
{
    public static readonly DependencyProperty ClickToHideProperty =
        DependencyProperty.Register("ClickToHide", typeof(bool), typeof(MyHeaderedContentControl),
            new PropertyMetadata(null));

    public bool ClickToHide
    {
        get => (bool)GetValue(ClickToHideProperty);
        set => SetValue(ClickToHideProperty, value);
    }

    protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
    {
        base.OnPreviewMouseLeftButtonDown(e);

        //TODO Hide one child control when user clicked the parent control

        e.Handled = true;
    }
}

CodePudding user response:

You could set the Visibility of the child control, which is the Content of the control.

protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
   base.OnPreviewMouseLeftButtonDown(e);

   // Only a click on this control is handled, not children.
   if (!e.Source.Equals(this))
      return;

   // The content must be at least a UI element in order to access the Visibility property.
   if (Content is UIElement uiElement)
   {
      // If the child (Content) is visible, collapse it, if it is collapsed, make it visible.
      uiElement.Visibility = uiElement.Visibility == Visibility.Collapsed
         ? Visibility.Visible
         : Visibility.Collapsed;
   }

   e.Handled = true;
}

If you create a custom control, you could alternatively specify a TemplatePart for a ContentPresenter. Then you can always show and hide the ContentPresenter which shows the Content, instead of depending on the actual child controls. This would also work for non-UIElement children like a string.

[TemplatePart(Name = "PART_ContentPresenter", Type = typeof(ContentPresenter))]
public class MyHeaderedContentControl : HeaderedContentControl
{
   private ContentPresenter _contentPresenter;

   public static readonly DependencyProperty ClickToHideProperty =
      DependencyProperty.Register("ClickToHide", typeof(bool), typeof(MyHeaderedContentControl),
         new PropertyMetadata(null));

   public bool ClickToHide
   {
      get => (bool)GetValue(ClickToHideProperty);
      set => SetValue(ClickToHideProperty, value);
   }

   public override void OnApplyTemplate()
   {
      base.OnApplyTemplate();
      _contentPresenter = GetTemplateChild("PART_ContentPresenter") as ContentPresenter;
   }

   protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
   {
      base.OnPreviewMouseLeftButtonDown(e);

      // Only a click on this control is handled, not children.
      if (_contentPresenter is null || !e.Source.Equals(this))
         return;

      // If the child (Content) is visible, collapse it, if it is collapsed, make it visible.
      _contentPresenter.Visibility = _contentPresenter.Visibility == Visibility.Collapsed
            ? Visibility.Visible
            : Visibility.Collapsed;

      e.Handled = true;
   }
}

The only requirement would be that your control template contains this part.

<Style TargetType="{x:Type local:MyHeaderedContentControl}">
   <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type local:MyHeaderedContentControl}">
            <ContentPresenter x:Name="PART_ContentPresenter"/>
         </ControlTemplate>
      </Setter.Value>
   </Setter>
</Style>

See Creating a Control That Has a Customizable Appearance for reference.

  • Related