• WPF中Expander的用法和控件模板详解


    一、Expander的用法

      在WPF中,Expander是一个很实用的复合控件,可以很方便的实现下拉菜单和导航栏等功能。先介绍简单的用法,而后分析他的控件模板。

    <Window.Resources>
            <ResourceDictionary>
                <Style x:Key="Expander.StackPanel.Style" TargetType="FrameworkElement">
                    <Setter Property="MaxWidth" Value="80"></Setter>
                    <Setter Property="MinWidth" Value="50"></Setter>
                    <Setter Property="HorizontalAlignment" Value="Left"></Setter>
                </Style>
            </ResourceDictionary>
        </Window.Resources>
        <Grid>
            
            <Expander Style="{DynamicResource ExpanderStyle}" Header="头部">
                <StackPanel>
                    <Button Style="{StaticResource Expander.StackPanel.Style}">内容1</Button>
                    <RadioButton Style="{StaticResource Expander.StackPanel.Style}">内容2</RadioButton>
                    <TextBox Style="{StaticResource Expander.StackPanel.Style}">内容3</TextBox>
                    <TextBlock Style="{StaticResource Expander.StackPanel.Style}">内容4</TextBlock>
                </StackPanel>
            </Expander>
        </Grid>

    可以看到Expander主要分为头部和内容两部分,展开时才显示内容,而内容部分可以存放丰富的内容

    效果图:

    二、控件模板

      如何获取控件本身默认的控件模板请看我的另一篇文章:https://www.cnblogs.com/xiaomengshan/p/11446436.html

      因为控件模板比较复杂,先看大概的构成:

    再看看主样式部分(ExpanderSytle)的构成:

    再看向下展开时头部的样式构成:

    如下为我标注了注释的完整控件模板代码:

    <SolidColorBrush x:Key="Expander.MouseOver.Circle.Stroke" Color="#FF5593FF"/>
                <SolidColorBrush x:Key="Expander.MouseOver.Circle.Fill" Color="#FFF3F9FF"/>
                <SolidColorBrush x:Key="Expander.MouseOver.Arrow.Stroke" Color="#FF000000"/>
                <SolidColorBrush x:Key="Expander.Pressed.Circle.Stroke" Color="#FF3C77DD"/>
                <SolidColorBrush x:Key="Expander.Pressed.Circle.Fill" Color="#FFD9ECFF"/>
                <SolidColorBrush x:Key="Expander.Pressed.Arrow.Stroke" Color="#FF000000"/>
                <SolidColorBrush x:Key="Expander.Disabled.Circle.Stroke" Color="#FFBCBCBC"/>
                <SolidColorBrush x:Key="Expander.Disabled.Circle.Fill" Color="#FFE6E6E6"/>
                <SolidColorBrush x:Key="Expander.Disabled.Arrow.Stroke" Color="#FF707070"/>
                <SolidColorBrush x:Key="Expander.Static.Circle.Fill" Color="#FFFFFFFF"/>
                <SolidColorBrush x:Key="Expander.Static.Circle.Stroke" Color="#FF333333"/>
                <SolidColorBrush x:Key="Expander.Static.Arrow.Stroke" Color="#FF333333"/>
                <!--ExpandDirection=Right,即向右展开时的头部样式-->
                <Style x:Key="ExpanderRightHeaderStyle" TargetType="{x:Type ToggleButton}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <Border Padding="{TemplateBinding Padding}">
                                    <Grid Background="Transparent" SnapsToDevicePixels="False">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="19"/>
                                            <RowDefinition Height="*"/>
                                        </Grid.RowDefinitions>
                                        <Grid>
                                            <Grid.LayoutTransform>
                                                <TransformGroup>
                                                    <TransformGroup.Children>
                                                        <TransformCollection>
                                                            <RotateTransform Angle="-90"/>
                                                        </TransformCollection>
                                                    </TransformGroup.Children>
                                                </TransformGroup>
                                            </Grid.LayoutTransform>
                                            <Ellipse x:Name="circle" Fill="Yellow" HorizontalAlignment="Center" Height="19" Stroke="Yellow" VerticalAlignment="Center" Width="19"/>
                                            <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                        </Grid>
                                        <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                    </Grid>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked" Value="true">
                                        <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                    </Trigger>
                                    <Trigger Property="IsMouseOver" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsPressed" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                        <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="false">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <!--ExpandDirection=Up,即向上展开时的头部样式-->
                <Style x:Key="ExpanderUpHeaderStyle" TargetType="{x:Type ToggleButton}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <Border Padding="{TemplateBinding Padding}">
                                    <Grid Background="Transparent" SnapsToDevicePixels="False">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="19"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <Grid>
                                            <Grid.LayoutTransform>
                                                <TransformGroup>
                                                    <TransformGroup.Children>
                                                        <TransformCollection>
                                                            <RotateTransform Angle="180"/>
                                                        </TransformCollection>
                                                    </TransformGroup.Children>
                                                </TransformGroup>
                                            </Grid.LayoutTransform>
                                            <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                            <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                        </Grid>
                                        <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                    </Grid>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked" Value="true">
                                        <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                    </Trigger>
                                    <Trigger Property="IsMouseOver" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsPressed" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                        <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="false">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <!--ExpandDirection=Left,即向左展开时的头部样式-->
                <Style x:Key="ExpanderLeftHeaderStyle" TargetType="{x:Type ToggleButton}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <Border Padding="{TemplateBinding Padding}">
                                    <Grid Background="Transparent" SnapsToDevicePixels="False">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="19"/>
                                            <RowDefinition Height="*"/>
                                        </Grid.RowDefinitions>
                                        <Grid>
                                            <Grid.LayoutTransform>
                                                <TransformGroup>
                                                    <TransformGroup.Children>
                                                        <TransformCollection>
                                                            <RotateTransform Angle="90"/>
                                                        </TransformCollection>
                                                    </TransformGroup.Children>
                                                </TransformGroup>
                                            </Grid.LayoutTransform>
                                            <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                            <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                        </Grid>
                                        <ContentPresenter HorizontalAlignment="Center" Margin="0,4,0,0" Grid.Row="1" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Top"/>
                                    </Grid>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsChecked" Value="true">
                                        <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                    </Trigger>
                                    <Trigger Property="IsMouseOver" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsPressed" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                        <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="false">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <!--ExpandDirection=Down,即向下展开时的头部样式(一般默认向下展开)-->
                <Style x:Key="ExpanderDownHeaderStyle" TargetType="{x:Type ToggleButton}">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ToggleButton}">
                                <Border Padding="{TemplateBinding Padding}">
                                    <Grid Background="Transparent" SnapsToDevicePixels="False">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="19"/>
                                            <ColumnDefinition Width="*"/>   <!--可变部分自适应存放文字-->
                                        </Grid.ColumnDefinitions>
                                        <!--下拉头部(Ellipse和Path组成圆圈箭头图标 ContentPresenter为文字)-->
                                        <Ellipse x:Name="circle" Fill="{StaticResource Expander.Static.Circle.Fill}" HorizontalAlignment="Center" Height="19" Stroke="{StaticResource Expander.Static.Circle.Stroke}" VerticalAlignment="Center" Width="19"/>
                                        <Path x:Name="arrow" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Center" SnapsToDevicePixels="false" Stroke="{StaticResource Expander.Static.Arrow.Stroke}" StrokeThickness="2" VerticalAlignment="Center"/>
                                        <ContentPresenter Grid.Column="1" HorizontalAlignment="Left" Margin="4,0,0,0" RecognizesAccessKey="True" SnapsToDevicePixels="True" VerticalAlignment="Center"/>
                                    </Grid>
                                </Border>
                                <ControlTemplate.Triggers>
                                    <!--选中时向下箭头变为为向上箭头-->
                                    <Trigger Property="IsChecked" Value="true">
                                        <Setter Property="Data" TargetName="arrow" Value="M 1,4.5  L 4.5,1  L 8,4.5"/>
                                    </Trigger>
                                    <Trigger Property="IsMouseOver" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.MouseOver.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.MouseOver.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsPressed" Value="true">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Stroke}"/>
                                        <Setter Property="StrokeThickness" TargetName="circle" Value="1.5"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Pressed.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Pressed.Arrow.Stroke}"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="false">
                                        <Setter Property="Stroke" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Stroke}"/>
                                        <Setter Property="Fill" TargetName="circle" Value="{StaticResource Expander.Disabled.Circle.Fill}"/>
                                        <Setter Property="Stroke" TargetName="arrow" Value="{StaticResource Expander.Disabled.Arrow.Stroke}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <!--键盘焦点样式-->
                <Style x:Key="ExpanderHeaderFocusVisual">
                    <Setter Property="Control.Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Border>
                                    <Rectangle Margin="0" SnapsToDevicePixels="true" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2"/>
                                </Border>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <!--Expander样式-->
                <Style x:Key="ExpanderStyle" TargetType="{x:Type Expander}">
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                    <Setter Property="Background" Value="Transparent"/>
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                    <Setter Property="BorderBrush" Value="Transparent"/>
                    <Setter Property="BorderThickness" Value="1"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <!--控件模板-->
                            <ControlTemplate TargetType="{x:Type Expander}">
                                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="3" SnapsToDevicePixels="true">
                                    <DockPanel>
                                        <!--头部标题-->
                                        <ToggleButton x:Name="HeaderSite" ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}" Content="{TemplateBinding Header}" DockPanel.Dock="Top" Foreground="{TemplateBinding Foreground}" FontWeight="{TemplateBinding FontWeight}" FocusVisualStyle="{StaticResource ExpanderHeaderFocusVisual}" FontStyle="{TemplateBinding FontStyle}" FontStretch="{TemplateBinding FontStretch}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" MinWidth="0" MinHeight="0" Padding="{TemplateBinding Padding}" Style="{StaticResource ExpanderDownHeaderStyle}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                        <!--下拉内容-->
                                        <ContentPresenter x:Name="ExpandSite" DockPanel.Dock="Bottom" Focusable="false" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                    </DockPanel>
                                </Border>
                                <!--触发器-->
                                <ControlTemplate.Triggers>
                                    <!--内容展开则显示隐藏内容-->
                                    <Trigger Property="IsExpanded" Value="true">
                                        <Setter Property="Visibility" TargetName="ExpandSite" Value="Visible"/>
                                    </Trigger>
                                    <!--向左、右、上展开修改DockPanel中标题和内容布局方式实现-->
                                    <Trigger Property="ExpandDirection" Value="Right">
                                        <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Right"/>
                                        <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Left"/>
                                        <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderRightHeaderStyle}"/>
                                    </Trigger>
                                    <Trigger Property="ExpandDirection" Value="Up">
                                        <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Top"/>
                                        <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Bottom"/>
                                        <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderUpHeaderStyle}"/>
                                    </Trigger>
                                    <Trigger Property="ExpandDirection" Value="Left">
                                        <Setter Property="DockPanel.Dock" TargetName="ExpandSite" Value="Left"/>
                                        <Setter Property="DockPanel.Dock" TargetName="HeaderSite" Value="Right"/>
                                        <Setter Property="Style" TargetName="HeaderSite" Value="{StaticResource ExpanderLeftHeaderStyle}"/>
                                    </Trigger>
                                    <Trigger Property="IsEnabled" Value="false">
                                        <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>

      知道了Expander默认控件模板的构成就可以根据需要修改,轻松构建自定义的导航栏等功能(建议只修改需要修改的部分)。

  • 相关阅读:
    HDU Number Sequence
    HDU Wolf and Rabbit
    HDU Fire Net
    C# QQ weather
    Jquery 随窗口改变大小不会影响浏览位置,DIV可以在绝对的位置不变.菜单相对位置不变
    C# 验证中国电话号码,电子邮件,网址,身份证号码等等
    C# Image Download
    Csharp 两个DataTable或DataView互换,可以用来加密解密
    C# Windows Forms TreeView SelectedNode(VS2008)
    C# 获取源代码
  • 原文地址:https://www.cnblogs.com/xiaomengshan/p/11487342.html
Copyright © 2020-2023  润新知