Vytváření stylů aplikací pomocí XAML

Aplikace .NET Multi-Platform App UI (.NET MAUI) často obsahují více ovládacích prvků, které mají stejný vzhled. Aplikace může mít například více Label instancí se stejnými možnostmi písma a možnostmi rozložení:

<Label Text="These labels"
       HorizontalOptions="Center"
       VerticalOptions="Center"
       FontSize="18" />
<Label Text="are not"
       HorizontalOptions="Center"
       VerticalOptions="Center"
       FontSize="18" />
<Label Text="using styles"
       HorizontalOptions="Center"
       VerticalOptions="Center"
       FontSize="18" />

V tomto příkladu má každý Label objekt identické hodnoty vlastností pro řízení vzhledu textu zobrazeného objektem Label. Nastavení vzhledu jednotlivých ovládacích prvků ale může být opakované a náchylné k chybám. Místo toho je možné vytvořit styl, který definuje vzhled a pak se použije u požadovaných ovládacích prvků.

Úvod do stylů

Aplikaci lze stylizovat pomocí Style třídy k seskupení kolekce hodnot vlastností do jednoho objektu, který lze použít pro více vizuálních prvků. To pomáhá snížit opakované značky a umožňuje snadnější změny vzhledu aplikací.

I když jsou styly navržené primárně pro aplikace založené na XAML, dají se také vytvořit v jazyce C#:

  • Style objekty vytvořené v JAZYCE XAML jsou obvykle definovány v ResourceDictionary kolekci Resources ovládacího prvku, stránky nebo Resources kolekce aplikace.
  • Style objekty vytvořené v jazyce C# jsou obvykle definovány ve třídě stránky nebo ve třídě, ke které lze globálně přistupovat.

Volba místa, kde se má definovat Style dopad, kde se dá použít:

  • Style instance definované na úrovni řízení lze použít pouze pro ovládací prvek a jeho podřízené položky.
  • Style instance definované na úrovni stránky lze použít pouze na stránku a na její podřízené položky.
  • Style Instance definované na úrovni aplikace je možné použít v celé aplikaci.

Každý Style objekt obsahuje kolekci jednoho nebo více Setter objektů, přičemž každý SetterProperty a a Value. Je Property název bindable vlastnost elementu, na který je styl použit, a Value je hodnota, která je použita na vlastnost.

Každý Style objekt může být explicitní nebo implicitní:

  • ExplicitníStyleobjekt je definován zadáním TargetType a x:Key hodnoty a nastavením vlastnosti cílového prvku Style na x:Key odkaz. Další informace naleznete v tématu Explicitní styly.
  • Implicitní Style objekt je definován zadáním pouze .TargetType Objekt Style se pak automaticky použije u všech prvků tohoto typu. Podtřídy TargetType těchto tříd však nemají automaticky použitou Style . Další informace naleznete v tématu Implicitní styly.

Při vytváření StyleTargetType je vlastnost vždy vyžadována. Následující příklad ukazuje explicitní styl:

<Style x:Key="labelStyle" TargetType="Label">
    <Setter Property="HorizontalOptions" Value="Center" />
    <Setter Property="VerticalOptions" Value="Center" />
    <Setter Property="FontSize" Value="18" />
</Style>

Chcete-li použít Styleobjekt , musí být cílový objekt, VisualElement který odpovídá TargetType hodnotě Stylevlastnosti :

<Label Text="Demonstrating an explicit style" Style="{StaticResource labelStyle}" />

Styly nižší v hierarchii zobrazení mají přednost před těmi, které jsou definovány výše. Například nastavení Style , které se nastaví Label.TextColor na Red úrovni aplikace, se přepíše stylem na úrovni stránky, který se nastaví Label.TextColor na Green. Podobně se styl na úrovni stránky přepíše stylem na úrovni ovládacího prvku. Kromě toho platí, že pokud Label.TextColor je nastavena přímo u vlastnosti ovládacího prvku, má přednost před všemi styly.

Styly nereagují na změny vlastností a po dobu trvání aplikace zůstávají beze změny. Aplikace ale můžou reagovat na změny stylu dynamicky za běhu pomocí dynamických prostředků. Další informace naleznete v tématu Dynamické styly.

Explicitní styly

Chcete-li vytvořit Style stránku na úrovni stránky, ResourceDictionary musí být přidána na stránku a pak lze do ní ResourceDictionaryzahrnout jednu nebo více Style deklarací . A Style je explicitníposkytnutím jeho deklarace x:Key atributu, který mu dává popisný klíč v objektu ResourceDictionary. Explicitní styly se pak musí použít u konkrétních vizuálních prvků nastavením jejich Style vlastností.

Následující příklad ukazuje explicitní styly stránky ResourceDictionarya použité na objekty stránky Label :

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="labelRedStyle"
               TargetType="Label">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="TextColor" Value="Red" />
        </Style>
        <Style x:Key="labelGreenStyle"
               TargetType="Label">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="TextColor" Value="Green" />
        </Style>
        <Style x:Key="labelBlueStyle"
               TargetType="Label">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="FontSize" Value="18" />
            <Setter Property="TextColor" Value="Blue" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <Label Text="These labels"
               Style="{StaticResource labelRedStyle}" />
        <Label Text="are demonstrating"
               Style="{StaticResource labelGreenStyle}" />
        <Label Text="explicit styles,"
               Style="{StaticResource labelBlueStyle}" />
        <Label Text="and an explicit style override"
               Style="{StaticResource labelBlueStyle}"
               TextColor="Teal" />
    </StackLayout>
</ContentPage>

V tomto příkladu ResourceDictionary definuje tři styly, které jsou explicitně nastaveny na objekty stránky Label . Každý z nich Style slouží k zobrazení textu v jiné barvě a zároveň nastavení velikosti písma a možností vodorovného a svislého rozložení. Každý Style se použije na jiný Label nastavením jeho Style vlastností pomocí StaticResource rozšíření značek. Kromě toho, zatímco final Label má nastaveno Style na něj, přepíše TextColor také vlastnost na jinou Color hodnotu.

Implicitní styly

Chcete-li vytvořit Style stránku na úrovni stránky, ResourceDictionary musí být přidána na stránku a pak lze do ní ResourceDictionaryzahrnout jednu nebo více Style deklarací . A Style je implicitnízadáním atributux:Key. Styl se pak použije v elementech vizuálu TargetType oboru, které přesně odpovídají prvkům, ale ne na prvky odvozené z TargetType hodnoty.

Následující příklad kódu ukazuje implicitní styl stránky ResourceDictionarya použitý na objekty stránkyEntry:

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="Entry">
            <Setter Property="HorizontalOptions" Value="Fill" />
            <Setter Property="VerticalOptions" Value="Center" />
            <Setter Property="BackgroundColor" Value="Yellow" />
            <Setter Property="FontAttributes" Value="Italic" />
            <Setter Property="TextColor" Value="Blue" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <Entry Text="These entries" />
        <Entry Text="are demonstrating" />
        <Entry Text="implicit styles," />
        <Entry Text="and an implicit style override"
               BackgroundColor="Lime"
               TextColor="Red" />
        <local:CustomEntry Text="Subclassed Entry is not receiving the style" />
    </StackLayout>
</ContentPage>

V tomto příkladu ResourceDictionary definuje jeden implicitní styl, který je implicitně nastaven na objekty stránky Entry . Slouží Style k zobrazení modrého textu na žlutém pozadí a zároveň k nastavení dalších možností vzhledu. Přidá Style se na stránku ResourceDictionary bez zadání atributu x:Key . Proto se použije na všechny Entry objekty implicitně tak, Style jak odpovídají TargetType vlastnosti Style přesně. Nicméně, Style není použita na CustomEntry objekt, což je podtřídě Entry. Kromě toho čtvrtý Entry přepisuje BackgroundColor a TextColor vlastnosti stylu na různé Color hodnoty.

Použití stylu u odvozených typů

Vlastnost Style.ApplyToDerivedTypes umožňuje použití stylu u ovládacích prvků odvozených od základního typu odkazovaného vlastností TargetType . Proto nastavení této vlastnosti true umožňuje jeden styl cílit na více typů za předpokladu, že typy jsou odvozeny od základního typu zadaného TargetType ve vlastnosti.

Následující příklad ukazuje implicitní styl, který nastaví barvu Button pozadí instancí na červenou:

<Style TargetType="Button"
       ApplyToDerivedTypes="True">
    <Setter Property="BackgroundColor"
            Value="Red" />
</Style>

Umístění tohoto stylu na úrovni ResourceDictionary stránky způsobí použití u všech Button objektů na stránce a také u všech ovládacích prvků odvozených z Button. Pokud ApplyToDerivedTypes však vlastnost zůstala bez sady, styl by se použil pouze na Button objekty.

Globální styly

Styly je možné definovat globálně tak, že je přidáte do slovníku prostředků aplikace. Tyto styly se pak dají využívat v celé aplikaci a pomáhají vyhnout se duplikaci stylu napříč stránkami a ovládacími prvky.

Následující příklad ukazuje Style definovaný na úrovni aplikace:


<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Styles"
             x:Class="Styles.App">
    <Application.Resources>        
        <Style x:Key="buttonStyle" TargetType="Button">
            <Setter Property="HorizontalOptions"
                        Value="Center" />
            <Setter Property="VerticalOptions"
                        Value="CenterAndExpand" />
            <Setter Property="BorderColor"
                        Value="Lime" />
            <Setter Property="CornerRadius"
                        Value="5" />
            <Setter Property="BorderWidth"
                        Value="5" />
            <Setter Property="WidthRequest"
                        Value="200" />
            <Setter Property="TextColor"
                        Value="Teal" />
        </Style>
    </Application.Resources>
</Application>

V tomto příkladu ResourceDictionary definuje jeden explicitní styl, buttonStylekterý se použije k nastavení vzhledu Button objektů.

Poznámka:

Globální styly můžou být explicitní nebo implicitní.

Následující příklad ukazuje stránku, která buttonStyle využívá objekty stránky Button :

<ContentPage ...>
    <StackLayout>
        <Button Text="These buttons"
                Style="{StaticResource buttonStyle}" />
        <Button Text="are demonstrating"
                Style="{StaticResource buttonStyle}" />
        <Button Text="application styles"
                Style="{StaticResource buttonStyle}" />
    </StackLayout>
</ContentPage>

Dědičnost stylů

Styly můžou dědit z jiných stylů, aby se snížila duplicita a povolila opakované použití. Toho dosáhnete nastavením Style.BasedOn vlastnosti na existující Style. V JAZYCE XAML toho lze dosáhnout nastavením BasedOn vlastnosti na StaticResource rozšíření značek, které odkazuje na dříve vytvořené Style.

Styly, které dědí ze základního stylu, můžou zahrnovat Setter instance pro nové vlastnosti nebo je použít k přepsání setter ze základního stylu. Kromě toho styly, které dědí ze základního stylu, musí cílit na stejný typ nebo typ odvozený od typu, na který cílí základní styl. Pokud například základní styl cílí View na objekty, styly založené na základním stylu mohou cílit View na objekty nebo typy odvozené z View třídy, jako Label jsou a Button objekty.

Styl může dědit pouze ze stylů na stejné úrovni nebo vyšší v hierarchii zobrazení. To znamená, že:

  • Styl na úrovni aplikace může dědit pouze z jiných stylů na úrovni aplikace.
  • Styl na úrovni stránky může dědit ze stylů na úrovni aplikace a dalších stylů na úrovni stránky.
  • Styl na úrovni ovládacího prvku může dědit ze stylů na úrovni aplikace, stylů na úrovni stránky a dalších stylů na úrovni ovládacího prvku.

Následující příklad ukazuje explicitní dědičnost stylu:

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="baseStyle"
               TargetType="View">
            <Setter Property="HorizontalOptions" Value="Center" />
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <StackLayout.Resources>
            <Style x:Key="labelStyle"
                   TargetType="Label"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="FontSize" Value="18" />
                <Setter Property="FontAttributes" Value="Italic" />
                <Setter Property="TextColor" Value="Teal" />
            </Style>
            <Style x:Key="buttonStyle"
                   TargetType="Button"
                   BasedOn="{StaticResource baseStyle}">
                <Setter Property="BorderColor" Value="Lime" />
                <Setter Property="CornerRadius" Value="5" />
                <Setter Property="BorderWidth" Value="5" />
                <Setter Property="WidthRequest" Value="200" />
                <Setter Property="TextColor" Value="Teal" />
            </Style>
        </StackLayout.Resources>
        <Label Text="This label uses style inheritance"
               Style="{StaticResource labelStyle}" />
        <Button Text="This button uses style inheritance"
                Style="{StaticResource buttonStyle}" />
    </StackLayout>
</ContentPage>

V tomto příkladu baseStyle cílí View objekty a nastaví HorizontalOptions a VerticalOptions vlastnosti. Není baseStyle nastavena přímo na žádné ovládací prvky. labelStyle Místo toho a buttonStyle dědí z něj nastavení dalších hodnot vazebných vlastností. Objekty labelStyle a objekty jsou pak nastaveny na a LabelButton.buttonStyle

Důležité

Implicitní styl lze odvodit z explicitního stylu, ale explicitní styl nelze odvodit z implicitního stylu.

Dynamické styly

Styly nereagují na změny vlastností a po dobu trvání aplikace zůstávají beze změny. Například po přiřazení elementu vizuálu Style , pokud je některý z Setter objektů změněn, odebrán nebo přidán nový Setter , změny se u elementu vizuálu nepoužijí. Aplikace ale můžou reagovat na změny stylu dynamicky za běhu pomocí dynamických prostředků.

Rozšíření DynamicResource značek je podobné StaticResource rozšíření značek v tom, že obě používají klíč slovníku k načtení hodnoty z objektu ResourceDictionary. I když se StaticResource ale provede jedno vyhledávání slovníku, DynamicResource udržuje odkaz na klíč slovníku. Proto pokud je položka slovníku přidružená ke klíči nahrazena, změna se použije u vizuálního prvku. To umožňuje provádět změny stylu modulu runtime v aplikaci.

Následující příklad ukazuje dynamické styly:

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="baseStyle"
               TargetType="View">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
        <Style x:Key="blueSearchBarStyle"
               TargetType="SearchBar"
               BasedOn="{StaticResource baseStyle}">
            <Setter Property="FontAttributes" Value="Italic" />
            <Setter Property="PlaceholderColor" Value="Blue" />
        </Style>
        <Style x:Key="greenSearchBarStyle"
               TargetType="SearchBar">
            <Setter Property="FontAttributes" Value="None" />
            <Setter Property="PlaceholderColor" Value="Green" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <SearchBar Placeholder="SearchBar demonstrating dynamic styles"
                   Style="{DynamicResource blueSearchBarStyle}" />
    </StackLayout>
</ContentPage>

V tomto příkladu objekt používá DynamicResource rozšíření značek k nastavení pojmenovaného StyleblueSearchBarStyle.SearchBar Potom SearchBar může mít jeho Style definici aktualizovanou v kódu:

Resources["blueSearchBarStyle"] = Resources["greenSearchBarStyle"];

V tomto příkladu blueSearchBarStyle se definice aktualizuje tak, aby používala hodnoty z greenSearchBarStyle definice. Při spuštění tohoto kódu se aktualizuje tak, SearchBar aby používal Setter objekty definované v greenSearchBarStyle.

Dynamická dědičnost stylu

Odvozování stylu z dynamického stylu nelze dosáhnout pomocí Style.BasedOn vlastnosti. Style Místo toho třída obsahuje BaseResourceKey vlastnost, kterou lze nastavit na klíč slovníku, jehož hodnota se může dynamicky měnit.

Následující příklad ukazuje dědičnost dynamického stylu:

<ContentPage ...>
    <ContentPage.Resources>
        <Style x:Key="baseStyle"
               TargetType="View">
            <Setter Property="VerticalOptions" Value="Center" />
        </Style>
        <Style x:Key="blueSearchBarStyle"
               TargetType="SearchBar"
               BasedOn="{StaticResource baseStyle}">
            <Setter Property="FontAttributes" Value="Italic" />
            <Setter Property="TextColor" Value="Blue" />
        </Style>
        <Style x:Key="greenSearchBarStyle"
               TargetType="SearchBar">
            <Setter Property="FontAttributes" Value="None" />
            <Setter Property="TextColor" Value="Green" />
        </Style>
        <Style x:Key="tealSearchBarStyle"
               TargetType="SearchBar"
               BaseResourceKey="blueSearchBarStyle">
            <Setter Property="BackgroundColor" Value="Teal" />
            <Setter Property="CancelButtonColor" Value="White" />
        </Style>
    </ContentPage.Resources>
    <StackLayout>
        <SearchBar Text="SearchBar demonstrating dynamic style inheritance"
                   Style="{StaticResource tealSearchBarStyle}" />
    </StackLayout>
</ContentPage>

V tomto příkladu objekt používá StaticResource rozšíření značek odkazovat na pojmenovaný tealSearchBarStyleStyle .SearchBar Tím Style se nastaví některé další vlastnosti a tato vlastnost se použije BaseResourceKey k odkazu blueSearchBarStyle. DynamicResource Rozšíření značek není povinné, protože tealSearchBarStyle se nezmění, s výjimkou Style odvozených z. tealSearchBarStyle Proto udržuje odkaz na blueSearchBarStyle základní styl a aktualizuje se při změně základního stylu.

Definici blueSearchBarStyle je možné aktualizovat v kódu:

Resources["blueSearchBarStyle"] = Resources["greenSearchBarStyle"];

V tomto příkladu blueSearchBarStyle se definice aktualizuje tak, aby používala hodnoty z greenSearchBarStyle definice. Při spuštění tohoto kódu se aktualizuje tak, SearchBar aby používal Setter objekty definované v greenSearchBarStyle.

Třídy stylů

Třídy stylů umožňují použití více stylů u ovládacího prvku, aniž by se uchýlily k dědičnosti stylu.

Třídu stylu lze vytvořit nastavením Class vlastnosti na Stylestring hodnotu, která představuje název třídy. Výhodou této nabídky je, že při definování explicitního stylu pomocí atributu x:Key lze použít VisualElementvíce tříd stylů .

Důležité

Více stylů může sdílet stejný název třídy za předpokladu, že cílí na různé typy. To umožňuje více tříd stylů, které jsou identicky pojmenované, aby cílily na různé typy.

Následující příklad ukazuje tři BoxView třídy stylu a VisualElement třídu stylu:

<ContentPage ...>
    <ContentPage.Resources>
        <Style TargetType="BoxView"
               Class="Separator">
            <Setter Property="BackgroundColor"
                    Value="#CCCCCC" />
            <Setter Property="HeightRequest"
                    Value="1" />
        </Style>

        <Style TargetType="BoxView"
               Class="Rounded">
            <Setter Property="BackgroundColor"
                    Value="#1FAECE" />
            <Setter Property="HorizontalOptions"
                    Value="Start" />
            <Setter Property="CornerRadius"
                    Value="10" />
        </Style>    

        <Style TargetType="BoxView"
               Class="Circle">
            <Setter Property="BackgroundColor"
                    Value="#1FAECE" />
            <Setter Property="WidthRequest"
                    Value="100" />
            <Setter Property="HeightRequest"
                    Value="100" />
            <Setter Property="HorizontalOptions"
                    Value="Start" />
            <Setter Property="CornerRadius"
                    Value="50" />
        </Style>

        <Style TargetType="VisualElement"
               Class="Rotated"
               ApplyToDerivedTypes="true">
            <Setter Property="Rotation"
                    Value="45" />
        </Style>        
    </ContentPage.Resources>
</ContentPage>

V tomto příkladu Separatortřídy , Roundeda Circle styl každé set BoxView vlastnosti na konkrétní hodnoty. Třída Rotated stylu má typ TargetTypeVisualElement, což znamená, že lze použít pouze na VisualElement instance. Jeho ApplyToDerivedTypes vlastnost je však nastavena na true, což zajišťuje, že jej lze použít na všechny ovládací prvky odvozené , VisualElementnapříklad BoxView. Další informace o použití stylu u odvozeného typu naleznete v tématu Použití stylu u odvozených typů.

Třídy stylu lze využívat nastavením StyleClass vlastnosti ovládacího prvku, který je typu IList<string>, na seznam názvů tříd stylů. Třídy stylů budou použity za předpokladu, že typ ovládacího prvku odpovídá TargetType třídám stylu.

Následující příklad ukazuje tři BoxView instance, z nichž každá je nastavená na různé třídy stylů:

<ContentPage ...>
    <ContentPage.Resources>
        ...
    </ContentPage.Resources>
    <StackLayout>
        <BoxView StyleClass="Separator" />       
        <BoxView WidthRequest="100"
                 HeightRequest="100"
                 HorizontalOptions="Center"
                 StyleClass="Rounded, Rotated" />
        <BoxView HorizontalOptions="Center"
                 StyleClass="Circle" />
    </StackLayout>
</ContentPage>    

V tomto příkladu má první BoxView styl oddělovač čar, zatímco třetí BoxView je kruhový. Druhá BoxView má dvě třídy stylu použité na něj, které dávají zaoblené rohy a otočí 45 stupňů:

Screenshot of BoxViews styled with style classes.

Důležité

U ovládacího prvku lze použít více tříd stylu, protože StyleClass vlastnost je typu IList<string>. V takovém případě se třídy stylů použijí ve vzestupném pořadí seznamu. Pokud tedy více tříd stylů nastaví stejné vlastnosti, bude mít přednost vlastnost ve třídě stylů, která je na nejvyšší pozici seznamu.