SettingsExpander

SettingsExpander może być używany do grupowania wielu elementów SettingsCard w jedną zwijaną grupę.

Element SettingsExpander może mieć własną zawartość do wyświetlania ustawienia po prawej stronie, podobnie jak SettingsCard, ale dodatkowo może zawierać dowolną liczbę elementów Items, które będą uwzględniane jako dodatkowe ustawienia. Te elementy same są elementami SettingsCard, co oznacza, że można łatwo przenieść ustawienie do kontrolki Expander lub z niej, po prostu wycinając i wklejając ich kod XAML!

<!--  Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information.  -->
<Page x:Class="SettingsControlsExperiment.Samples.SettingsExpanderSample"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:controls="using:CommunityToolkit.WinUI.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:ui="using:CommunityToolkit.WinUI"
      mc:Ignorable="d">

    <controls:SettingsExpander x:Name="settingsCard"
                               VerticalAlignment="Top"
                               Description="The SettingsExpander has the same properties as a Card, and you can set SettingsCard as part of the Items collection."
                               Header="SettingsExpander"
                               HeaderIcon="{ui:FontIcon Glyph=}"
                               IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}"
                               IsExpanded="{x:Bind IsCardExpanded, Mode=OneWay}">
        <!--  TODO: This should be TwoWay bound but throws compile error in Uno.  -->
        <ComboBox SelectedIndex="0">
            <ComboBoxItem>Option 1</ComboBoxItem>
            <ComboBoxItem>Option 2</ComboBoxItem>
            <ComboBoxItem>Option 3</ComboBoxItem>
        </ComboBox>

        <controls:SettingsExpander.Items>
            <controls:SettingsCard Header="A basic SettingsCard within an SettingsExpander">
                <Button Content="Button" />
            </controls:SettingsCard>
            <controls:SettingsCard Description="SettingsCard within an Expander can be made clickable too!"
                                   Header="This item can be clicked"
                                   IsClickEnabled="True" />

            <controls:SettingsCard ContentAlignment="Left">
                <CheckBox Content="Here the ContentAlignment is set to Left. This is great for e.g. CheckBoxes or RadioButtons." />
            </controls:SettingsCard>

            <controls:SettingsCard HorizontalContentAlignment="Left"
                                   ContentAlignment="Vertical"
                                   Description="You can also align your content vertically. Make sure to set the HorizontalAlignment to Left when you do!"
                                   Header="Vertically aligned">
                <GridView SelectedIndex="1">
                    <GridViewItem>
                        <Border Width="64"
                                Height="64"
                                Background="#0078D4"
                                CornerRadius="4" />
                    </GridViewItem>
                    <GridViewItem>
                        <Border Width="64"
                                Height="64"
                                Background="#005EB7"
                                CornerRadius="4" />
                    </GridViewItem>
                    <GridViewItem>
                        <Border Width="64"
                                Height="64"
                                Background="#003D92"
                                CornerRadius="4" />
                    </GridViewItem>
                    <GridViewItem>
                        <Border Width="64"
                                Height="64"
                                Background="#001968"
                                CornerRadius="4" />
                    </GridViewItem>
                </GridView>
            </controls:SettingsCard>
            <controls:SettingsCard Description="You can override the Left indention of a SettingsCard by overriding the SettingsCardLeftIndention"
                                   Header="Customization">
                <controls:SettingsCard.Resources>
                    <x:Double x:Key="SettingsCardLeftIndention">40</x:Double>
                </controls:SettingsCard.Resources>
            </controls:SettingsCard>
        </controls:SettingsExpander.Items>
    </controls:SettingsExpander>
</Page>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace SettingsControlsExperiment.Samples;

[ToolkitSampleBoolOption("IsCardExpanded", false, Title = "Is Expanded")]
[ToolkitSampleBoolOption("IsCardEnabled", true, Title = "Is Enabled")]
[ToolkitSample(id: nameof(SettingsExpanderSample), "SettingsExpander", description: "The SettingsExpander can be used to group settings. SettingsCards can be customized in terms of alignment and content.")]
public sealed partial class SettingsExpanderSample : Page
{
    public SettingsExpanderSample()
    {
        this.InitializeComponent();
    }
}

Niektóre właściwości można łatwo zastąpić, aby tworzyć środowiska niestandardowe. Możesz na przykład dostosować ContentAlignment elementu SettingsCard, aby wyrównać zawartość do prawej (domyślnie), do lewej (ukrywając HeaderIcon, Header i Description) lub pionowo (zwykle najlepiej w połączeniu ze zmianą HorizontalContentAlignment na Stretch).

SettingsExpander jest również elementem ItemsControl, więc jego elementy mogą być określane przez kolekcję i właściwość ItemsSource. Możesz użyć elementu ItemTemplate, aby określić, w jaki sposób obiekt danych jest reprezentowany jako SettingsCard, jak pokazano poniżej. Właściwość ItemsHeader i ItemsFooter może służyć do hostowania zawartości niestandardowej na początku lub na końcu listy elementów.

<!--  Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information.  -->
<Page x:Class="SettingsControlsExperiment.Samples.SettingsExpanderItemsSourceSample"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:controls="using:CommunityToolkit.WinUI.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="using:SettingsControlsExperiment.Samples"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
      xmlns:ui="using:CommunityToolkit.WinUI"
      mc:Ignorable="d">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ms-appx:///CommunityToolkit.WinUI.Controls.SettingsControls/SettingsExpander/SettingsExpander.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    <StackPanel Spacing="4">
        <controls:SettingsExpander Description="The SettingsExpander can use ItemsSource to define its Items."
                                   Header="Settings Expander with ItemsSource"
                                   HeaderIcon="{ui:FontIcon Glyph=}"
                                   ItemsSource="{x:Bind MyDataSet}">
            <controls:SettingsExpander.ItemTemplate>
                <DataTemplate x:DataType="local:MyDataModel">
                    <controls:SettingsCard Description="{x:Bind Info}"
                                           Header="{x:Bind Name}">
                        <HyperlinkButton Content="{x:Bind LinkDescription}"
                                         NavigateUri="{x:Bind Url}" />
                    </controls:SettingsCard>
                </DataTemplate>
            </controls:SettingsExpander.ItemTemplate>
            <controls:SettingsExpander.ItemsHeader>
                <muxc:InfoBar Title="This is the ItemsHeader"
                              BorderThickness="0"
                              CornerRadius="0"
                              IsIconVisible="False"
                              IsOpen="True"
                              Severity="Success">
                    <muxc:InfoBar.ActionButton>
                        <HyperlinkButton Content="It can host custom content" />
                    </muxc:InfoBar.ActionButton>
                </muxc:InfoBar>
            </controls:SettingsExpander.ItemsHeader>
            <controls:SettingsExpander.ItemsFooter>
                <controls:SettingsCard Header="This is the ItemsFooter"
                                       Style="{StaticResource DefaultSettingsExpanderItemStyle}">
                    <Button Content="Add a device" />
                </controls:SettingsCard>
            </controls:SettingsExpander.ItemsFooter>
        </controls:SettingsExpander>

        <controls:SettingsExpander Description="SettingsExpander can use a DataTemplate, DataTemplateSelector, or IElementFactory for its ItemTemplate."
                                   Header="Settings Expander with a custom ItemTemplate"
                                   HeaderIcon="{ui:FontIcon Glyph=}"
                                   ItemsSource="{x:Bind MyDataSet}">
            <controls:SettingsExpander.ItemTemplate>
                <local:MyDataModelTemplateSelector>
                    <local:MyDataModelTemplateSelector.ButtonTemplate>
                        <DataTemplate x:DataType="local:MyDataModel">
                            <controls:SettingsCard Description="{x:Bind ItemType}"
                                                   Header="{x:Bind Name}">
                                <Button Click="Button_Click"
                                        Content="{x:Bind LinkDescription}" />
                            </controls:SettingsCard>
                        </DataTemplate>
                    </local:MyDataModelTemplateSelector.ButtonTemplate>

                    <local:MyDataModelTemplateSelector.LinkButtonTemplate>
                        <DataTemplate x:DataType="local:MyDataModel">
                            <controls:SettingsCard Description="{x:Bind ItemType}"
                                                   Header="{x:Bind Name}">
                                <HyperlinkButton Content="{x:Bind LinkDescription}"
                                                 NavigateUri="{x:Bind Url}" />
                            </controls:SettingsCard>
                        </DataTemplate>
                    </local:MyDataModelTemplateSelector.LinkButtonTemplate>

                    <local:MyDataModelTemplateSelector.NoButtonTemplate>
                        <DataTemplate x:DataType="local:MyDataModel">
                            <controls:SettingsCard Description="{x:Bind ItemType}"
                                                   Header="{x:Bind Name}" />
                        </DataTemplate>
                    </local:MyDataModelTemplateSelector.NoButtonTemplate>
                </local:MyDataModelTemplateSelector>
            </controls:SettingsExpander.ItemTemplate>
        </controls:SettingsExpander>
    </StackPanel>
</Page>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Windows.System;

namespace SettingsControlsExperiment.Samples;

[ToolkitSample(id: nameof(SettingsExpanderItemsSourceSample), "SettingsExpanderItemsSource", description: "The SettingsExpander can also be filled with items based on a collection.")]
public sealed partial class SettingsExpanderItemsSourceSample : Page
{

    public ObservableCollection<MyDataModel> MyDataSet = new() {
        new()
        {
            Name = "First Item",
            Info = "More about first item.",
            ItemType = "Item type: Button",
            LinkDescription = "Click here for more on first item.",
            Url = "https://microsoft.com/",
        },
        new()
        {
            Name = "Second Item",
            Info = "More about second item.",
            ItemType = "Item type: Link button",
            LinkDescription = "Click here for more on second item.",
            Url = "https://xbox.com/",
        },
        new()
        {
            Name = "Third Item",
            Info = "More about third item.",
            ItemType = "Item type: No button",
            LinkDescription = "Click here for more on third item.",
            Url = "https://toolkitlabs.dev/",
        },
    };

    public SettingsExpanderItemsSourceSample()
    {
        this.InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        _ = await Launcher.LaunchUriAsync(new("https://microsoft.com/"));
    }
}

public class MyDataModel
{
    public string? Name { get; set; }

    public string? Info { get; set; }

    public string? ItemType { get; set; }

    public string? LinkDescription { get; set; }

    public string? Url { get; set; }
}

public partial class MyDataModelTemplateSelector : DataTemplateSelector
{
    public DataTemplate? ButtonTemplate { get; set; }
    public DataTemplate? LinkButtonTemplate { get; set; }
    public DataTemplate? NoButtonTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        var itm = (MyDataModel)item;
        if (itm.ItemType?.EndsWith("Button") == true)
        {
            return ButtonTemplate!;
        }
        else if (itm.ItemType?.EndsWith("Link button") == true)
        {
            return LinkButtonTemplate!;
        }
        else
        {
            return NoButtonTemplate!;
        }
    }
}

UWAGA: Ze względu na usterkę związaną z elementem ItemsRepeater używanym w SettingsExpander, mogą występować zakłócenia wizualne za każdym razem, gdy SettingsExpander się rozszerza, a element MaxWidth jest ustawiony na nadrzędnym elemencie StackPanel. Jako obejście tego problemu element StackPanel (z ustawionym parametrem MaxWidth) można opakować w elemencie Grid. Zobacz SettingsPageExample, aby zobaczyć fragment kodu.

Przykład strony Ustawień

Poniższy przykład zawiera typową stronę projektową, postępując zgodnie z poprawnymi specyfikacjami projektu systemu Windows 11 dotyczącymi takich elementów jak odstępy, nagłówki sekcji i animacje.

<!--  Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information.  -->
<Page x:Class="SettingsControlsExperiment.Samples.SettingsPageExample"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:controls="using:CommunityToolkit.WinUI.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:ui="using:CommunityToolkit.WinUI"
      xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      mc:Ignorable="d">
    <Page.Resources>
        <!--  These styles can be referenced to create a consistent SettingsPage layout  -->

        <!--  Spacing between cards  -->
        <x:Double x:Key="SettingsCardSpacing">4</x:Double>

        <!--  Style (inc. the correct spacing) of a section header  -->
        <Style x:Key="SettingsSectionHeaderTextBlockStyle"
               BasedOn="{StaticResource BodyStrongTextBlockStyle}"
               TargetType="TextBlock">
            <Style.Setters>
                <Setter Property="Margin" Value="1,30,0,6" />
            </Style.Setters>
        </Style>
    </Page.Resources>
    <ScrollViewer>
        <Grid>
            <StackPanel MaxWidth="1000"
                        HorizontalAlignment="Stretch"
                        Spacing="{StaticResource SettingsCardSpacing}">
                <win:StackPanel.ChildrenTransitions>
                    <win:EntranceThemeTransition FromVerticalOffset="50" />
                    <win:RepositionThemeTransition IsStaggeringEnabled="False" />
                </win:StackPanel.ChildrenTransitions>
                <TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
                           Text="Section 1" />
                <controls:SettingsCard Description="This is a default card, with the Header, HeaderIcon, Description and Content set"
                                       Header="This is the Header"
                                       HeaderIcon="{ui:FontIcon Glyph=}">
                    <ToggleSwitch IsOn="True" />
                </controls:SettingsCard>

                <controls:SettingsExpander Description="The SettingsExpander has the same properties as a SettingsCard"
                                           Header="SettingsExpander"
                                           HeaderIcon="{ui:FontIcon Glyph=}">
                    <Button Content="Content"
                            Style="{StaticResource AccentButtonStyle}" />

                    <controls:SettingsExpander.Items>
                        <controls:SettingsCard Header="A basic SettingsCard within an SettingsExpander">
                            <Button Content="Button" />
                        </controls:SettingsCard>
                        <controls:SettingsCard Description="SettingsCard within an Expander can be made clickable too!"
                                               Header="This item can be clicked"
                                               IsClickEnabled="True" />

                        <controls:SettingsCard ContentAlignment="Left">
                            <CheckBox Content="Here the ContentAlignment is set to Left. This is great for e.g. CheckBoxes or RadioButtons" />
                        </controls:SettingsCard>
                    </controls:SettingsExpander.Items>
                </controls:SettingsExpander>

                <TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
                           Text="Section 2" />
                <controls:SettingsCard Description="Another card to show grouping of cards"
                                       Header="Another SettingsCard"
                                       HeaderIcon="{ui:FontIcon Glyph=}">
                    <ComboBox SelectedIndex="0">
                        <ComboBoxItem>Option 1</ComboBoxItem>
                        <ComboBoxItem>Option 2</ComboBoxItem>
                        <ComboBoxItem>Option 3</ComboBoxItem>
                    </ComboBox>
                </controls:SettingsCard>

                <controls:SettingsCard Description="Another card to show grouping of cards"
                                       Header="Yet another SettingsCard"
                                       HeaderIcon="{ui:FontIcon Glyph=}">
                    <Button Content="Content" />
                </controls:SettingsCard>

                <!--  Example 'About' section  -->
                <TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
                           Text="About" />

                <controls:SettingsExpander Description="© 2023. All rights reserved."
                                           Header="Community Toolkit Gallery"
                                           HeaderIcon="{ui:BitmapIcon Source=ms-appx:///Assets/AppTitleBar.scale-200.png}">
                    <TextBlock win:IsTextSelectionEnabled="True"
                               Foreground="{ThemeResource TextFillColorSecondaryBrush}"
                               Text="Version 8.0.0" />
                    <controls:SettingsExpander.Items>
                        <controls:SettingsCard HorizontalContentAlignment="Left"
                                               ContentAlignment="Left">
                            <StackPanel Margin="-12,0,0,0"
                                        Orientation="Vertical">
                                <HyperlinkButton Content="Link 1" />
                                <HyperlinkButton Content="Link 2" />
                                <HyperlinkButton Content="Link 3" />
                            </StackPanel>
                        </controls:SettingsCard>
                    </controls:SettingsExpander.Items>
                </controls:SettingsExpander>
                <HyperlinkButton Margin="0,8,0,0"
                                 Content="Send feedback" />
            </StackPanel>
        </Grid>
    </ScrollViewer>
</Page>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace SettingsControlsExperiment.Samples;

[ToolkitSample(id: nameof(SettingsPageExample), "Settings Page Example", description: "A complete settings page example.")]
public sealed partial class SettingsPageExample : Page
{
    public SettingsPageExample()
    {
        this.InitializeComponent();
    }
}