扩展器

使用扩展器控件,可以显示或隐藏与一段始终可见的主要内容相关的重要内容。 标头中包含的项始终可见。 用户可以通过与标头交互,展开和折叠显示次要内容的内容区域。 内容区域展开后,会使其他 UI 元素跳出;它不会覆盖其他 UI。 Expander 可以向上或向下展开。

HeaderContent 区域均可包含从简单文本到复杂 UI 布局的任何内容。 例如,可以使用控件显示项的其他选项。

先展开后折叠的折叠式展开器。标题中的文字为“此文本位于标题中”,内容中的文字为“此文本位于内容中”。

这是正确的控件吗?

如果某些主要内容应始终可见,但相关的次要内容可能在需要之前都处于隐藏状态,则使用 Expander。 显示空间有限并且信息或选项可以组合在一起时,通常使用此 UI。 在有需要之前隐藏次要内容还有助于将用户的注意力放在应用最重要的部分。

UWP 和 WinUI 2

重要

本文中的信息和示例是针对使用 Windows App SDKWinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请查看 UWP API 参考。

本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。

用于 UWP 应用的 Expander 需要 WinUI 2。 有关详细信息(包括安装说明),请参阅 WinUI 2。 此控件的 API 存在于 Microsoft.UI.Xaml.Controls 命名空间中。

要将本文中的代码与 WinUI 2 配合使用,请使用 XAML 中的别名(我们使用 muxc)来表示项目中包含的 Windows UI 库 API。 有关详细信息,请参阅 WinUI 2 入门

xmlns:muxc="using:Microsoft.UI.Xaml.Controls"

<muxc:Expander />

创建扩展器

WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码

本示例演示如何使用默认样式创建简单的扩展器标头属性定义始终可见的元素。 内容属性定义可以折叠和展开的元素。 此示例创建与上图类似的 Expander

<Expander Header="This text is in the header"
               Content="This is in the content"/>

扩展器内容

Expander内容属性可以是任何类型的对象,但通常为字符串或 UIElement。 有关设置 Content 属性的更多详细信息,请参阅 ContentControl 类的“备注”部分。

可以使用复杂的交互式 UI 作为 Expander 的内容,包括父级 Expander 内容中嵌套的 Expander 控件,如下所示。

一个打开的 Expander,其内容中嵌套了四个 Expander 控件。每个嵌套的 Expander 控件都有一个单选按钮,其标题中包含文本

内容对齐

可以通过设置 Expander 控件上的 HorizontalContentAlignmentVerticalContentAlignment 属性来对齐内容。 设置这些属性时,对齐方式仅适用于扩展的内容,而不适用于标题。

控制扩展器的大小

默认情况下,标头内容区域会自动调整大小以适应其内容。 务必使用正确的方法来控制 Expander 的大小,以避免不良的外观或行为。

宽度

如果内容的宽度大于标题,则在展开时,标题宽度将增加以与内容区域匹配,并在内容区域折叠时缩小。 要防止控件宽度在展开或折叠时更改,可以设置显式宽度;如果控件是面板的子控件,则将 HorizontalAlignment 设置为“拉伸”,并让布局面板控制大小。

在这里,一系列相关的 Expander 控件放置在 StackPanel 中。 其中HorizontalAlignment每个Expander元素StackPanel都设置为Stretch使用资源中的StackPanel样式,并且控件的宽度StackPanel决定了控件的Expander宽度。

<StackPanel x:Name="ExpanderStack" MaxWidth="600">
    <StackPanel.Resources>
        <Style TargetType="Expander">
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </StackPanel.Resources>
    <Expander Header="Choose your crust"> ... </Expander>
    <Expander Header="Choose your sauce"> ... </Expander>
    <Expander Header="Choose your toppings"> ... </Expander>
 </StackPanel>

三个垂直堆叠的 Expander 控件,宽度相同

Height

不要在 Expander 上指定高度。 如果执行此操作,即使内容区域处于折叠状态,控件也会保留该空间,这会破坏 Expander 的用途。 要指定展开内容区域的大小,请设置 Expander 的内容的大小维度。 如果需要,可以限制内容的 Height,并使内容可滚动。

可滚动内容

如果内容对于内容区域来说太大,可以将内容包装为 ScrollViewer,使内容区域可滚动。 Expander 控件不自动提供滚动功能。

Expander 内容中放置 ScrollViewer 时,请将 ScrollViewer 控件的高度设置为内容区域所需的高度。 如果改为对 ScrollViewer 中的内容设置高度维度,则 ScrollViewer 不会识别此设置,因此不会提供可滚动内容。

下面的示例演示如何创建一个 Expander 控件,该控件包含可滚动文本作为其内容。

<Expander Header="Expander with scrollable content">
    <ScrollViewer MaxHeight="200">
        <Grid>
            <TextBlock TextWrapping="Wrap">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, 
                sed do eiusmod tempor incididunt ut labore et dolore magna
                aliqua. Ut enim ad minim veniam, quis nostrud exercitation
                ullamco laboris nisi ut aliquip ex ea commodo consequat.
                Duis aute irure dolor in reprehenderit in voluptate velit
                esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
                occaecat cupidatat non proident, sunt in culpa qui officia
                deserunt mollit anim id est laborum.
            </TextBlock>
        </Grid>
    </ScrollViewer>
</Expander>

内容为可滚动文本的 Expander

展开和折叠内容区域

默认情况下,扩展器处于折叠状态,可以向下展开。

<Expander IsExpanded="True" ExpandDirection="Up">

通过设置IsExpanded属性或与Header属互,以编程方式展开或折叠一个 Expander ;它不能被轻消除。

提示

单击或点击暂时性 UI(例如 FlyoutComboBox 的开放式下拉菜单)的外部时,它会关闭。 这称为轻型消除Expander 的内容区域不被视为是暂时性的,并且不会覆盖其他 UI,因此它不支持轻型消除。

还可以处理展开折叠事件,以便在显示或隐藏内容时执行操作。 下面是这些事件的一些示例。

展开事件

本示例中你有一组扩展器,并且只希望一次打开其中一个。 用户打开 Expander 时,将处理展开事件,并折叠组中除用户单击的控件以外的所有 Expander 控件。

注意

取决于应用和用户体验,在用户展开其他控件时,可能会自动折叠 Expander 控件。 但是,这也会使用户失去控制权。 如果此行为可能会很有用,请考虑使其成为用户可以轻松设置的选项。

<StackPanel x:Name="ExpanderStack">
    <Expander Header="Choose your crust"
                   Expanding="Expander_Expanding"> ... </Expander>
    <Expander Header="Choose your sauce"
                   Expanding="Expander_Expanding"> ... </Expander>
    <Expander Header="Choose your toppings"
                   Expanding="Expander_Expanding"> ... </Expander>
 </StackPanel>
// Let the user opt out of custom behavior.
private bool _autoCollapse = true;

private void Expander_Expanding(muxc.Expander sender, 
                                muxc.ExpanderExpandingEventArgs args)
{
    if (_autoCollapse == true)
    {
        foreach (muxc.Expander ex in ExpanderStack.Children)
        {
            if (ex != sender && ex.IsExpanded)
                ex.IsExpanded = false;
        }
    }
}

折叠事件

本示例中,你将处理折叠事件,并使用在 Content 中选择的选项概述填充 Header

此图显示 Expander 的内容已展开并选择了选项。

展开的 Expander 控件,其中包含内容区域中所示的选定选项

折叠后,所选选项将在标头中汇总,因此用户仍可以在不打开 Expander 的情况下查看它们。

已折叠的 Expander 控件,其中包含标题中汇总的选定选项

<Expander IsExpanded="True"
        Expanding="Expander_Expanding"
        Collapsed="Expander_Collapsed">
    <Expander.Header>
        <Grid>
            <TextBlock Text="Choose your crust"/>
            <TextBlock x:Name="tbCrustSelections"
                       HorizontalAlignment="Right"
                       Style="{StaticResource CaptionTextBlockStyle}"/>
        </Grid>
    </Expander.Header>
    <StackPanel Orientation="Horizontal">
        <RadioButtons x:Name="rbCrustType" SelectedIndex="0">
            <x:String>Classic</x:String>
            <x:String>Whole wheat</x:String>
            <x:String>Gluten free</x:String>
        </RadioButtons>
        <RadioButtons x:Name="rbCrustStyle" SelectedIndex="0" 
                           Margin="48,0,0,0">
            <x:String>Regular</x:String>
            <x:String>Thin</x:String>
            <x:String>Pan</x:String>
            <x:String>Stuffed</x:String>
        </RadioButtons>
    </StackPanel>
</Expander>
private void Expander_Collapsed(muxc.Expander sender, 
                                muxc.ExpanderCollapsedEventArgs args)
{
    // Update the header with options selected in the content.
    tbCrustSelections.Text = rbCrustType.SelectedItem.ToString() +
        ", " + rbCrustStyle.SelectedItem.ToString();
}

轻型样式

可以修改默认 StyleControlTemplate 以使控件具有唯一的外观。 请参阅扩展器 API 文档的“控件样式和模板”部分,查看可用主题资源的列表。 有关详细信息,请参阅设置控件样式一文中的轻量级样式设置部分

建议

  • 在显示空间有限时使用 Expander,可能会导致某些次要内容在用户请求它之前处于隐藏状态。

代码示例

此 XAML 创建本文中其他部分所示的 Expander 控件组。 ExpandingCollapsed 事件处理程序的代码也显示在前面的部分中。

<StackPanel x:Name="ExpanderStack" MaxWidth="600">
    <StackPanel.Resources>
        <Style TargetType="Expander">
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </StackPanel.Resources>
    <Expander IsExpanded="True"
                   Expanding="Expander_Expanding"
                   Collapsed="Expander_Collapsed">
        <Expander.Header>
            <Grid>
                <TextBlock Text="Choose your crust"/>
                <TextBlock x:Name="tbCrustSelections" 
                           HorizontalAlignment="Right"
        Style="{StaticResource CaptionTextBlockStyle}"/>
            </Grid>
        </Expander.Header>
        <StackPanel Orientation="Horizontal">
            <RadioButtons x:Name="rbCrustType" SelectedIndex="0">
                <x:String>Classic</x:String>
                <x:String>Whole wheat</x:String>
                <x:String>Gluten free</x:String>
            </RadioButtons>
            <RadioButtons x:Name="rbCrustStyle" SelectedIndex="0" 
                   Margin="48,0,0,0">
                <x:String>Regular</x:String>
                <x:String>Thin</x:String>
                <x:String>Pan</x:String>
                <x:String>Stuffed</x:String>
            </RadioButtons>
        </StackPanel>
    </Expander>
    
    <Expander Header="Choose your sauce" Margin="24"
            Expanding="Expander_Expanding">
        <RadioButtons SelectedIndex="0" MaxColumns="2">
            <x:String>Classic red</x:String>
            <x:String>Garlic</x:String>
            <x:String>Pesto</x:String>
            <x:String>Barbecue</x:String>
        </RadioButtons>
    </Expander>

    <Expander Header="Choose your toppings"
                   Expanding="Expander_Expanding">
        <StackPanel>
            <Expander>
                <Expander.Header>
                    <RadioButton GroupName="Toppings" Content="House special"/>
                </Expander.Header>
                <TextBlock Text="Cheese, pepperoni, sausage, black olives, mushrooms"
                           TextWrapping="WrapWholeWords"/>
            </Expander>
            <Expander>
                <Expander.Header>
                    <RadioButton GroupName="Toppings" Content="Vegetarian"/>
                </Expander.Header>
                <TextBlock Text="Cheese, mushrooms, black olives, green peppers, artichoke hearts"
                           TextWrapping="WrapWholeWords"/>
            </Expander>
            <Expander>
                <Expander.Header>
                    <RadioButton GroupName="Toppings" Content="All meat"/>
                </Expander.Header>
                <TextBlock Text="Cheese, pepperoni, sausage, ground beef, salami"
                           TextWrapping="WrapWholeWords"/>
            </Expander>
            <Expander>
                <Expander.Header>
                    <RadioButton GroupName="Toppings" Content="Choose your own"/>
                </Expander.Header>
                <StackPanel Orientation="Horizontal">
                    <StackPanel>
                        <CheckBox Content="Cheese"/>
                        <CheckBox Content="Pepperoni"/>
                        <CheckBox Content="Sausage"/>
                    </StackPanel>
                    <StackPanel>
                        <CheckBox Content="Ground beef"/>
                        <CheckBox Content="Salami"/>
                        <CheckBox Content="Mushroom"/>
                    </StackPanel>
                    <StackPanel>
                        <CheckBox Content="Black olives"/>
                        <CheckBox Content="Green peppers"/>
                        <CheckBox Content="Artichoke hearts"/>
                    </StackPanel>
                </StackPanel>
            </Expander>
        </StackPanel>
    </Expander>
</StackPanel>