原生的 HeaderedContentControl 并不支持我们的需求,所以我们需要继承它并响应点击事件。在用户点击时,将Content的Visibility由 Visible 设置为 Collapsed 。对目前的我,最大的难点是如何在自定义控件里面访问子控件。

通过参考文章中的方法,控件+模板的配合实现。

<Style TargetType="control:MyHeaderedContentControl">
    <!-- 此处的Margin的bottom是针对下个同级Control的 -->
    <Setter Property="Margin" Value="0,0,0,0" />
    <Setter Property="IsTabStop" Value="False" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="control:MyHeaderedContentControl">
                <StackPanel>
                    <!-- Header -->
                    <StackPanel Orientation="Horizontal" Margin="13,6,0,6" Height="40">
                            <TextBlock Width="6" Background="{DynamicResource SystemControlBackgroundAccentBrush}"/>
                            <TextBlock Text="{TemplateBinding Header}" FontSize="14" Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
                                       Style="{DynamicResource BaseTextBlockStyle}"
                                       HorizontalAlignment="Center" VerticalAlignment="Center"
                                       Margin="6,0,0,0"/>
                    </StackPanel>
                    <!-- Content -->
                    <ContentPresenter x:Name="PART_Content" Content="{TemplateBinding Content}"/>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

定义Control

[TemplatePart(Name = "PART_Content", 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_Content") 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;
    <control:MyHeaderedContentControl Header="管理通知" 
                                      VerticalAlignment="Top" 
                                      ClickToHide="True"
                                      Grid.Row="0" >
</Grid>
  • How to change visibility of child control in my customized Control?
  • Creating a Control That Has a Customizable Appearance
  • 分类:
    前端
    标签: