Bagikan melalui


Aplikasi gaya menggunakan XAML

Aplikasi .NET Multi-platform App UI (.NET MAUI) sering berisi beberapa kontrol yang memiliki tampilan yang identik. Misalnya, aplikasi mungkin memiliki beberapa Label instans yang memiliki opsi font dan opsi tata letak yang sama:

<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" />

Dalam contoh ini, setiap Label objek memiliki nilai properti yang identik untuk mengontrol tampilan teks yang ditampilkan oleh Label. Namun, mengatur tampilan setiap kontrol individu dapat berulang dan rawan kesalahan. Sebagai gantinya, gaya dapat dibuat yang menentukan tampilan, lalu diterapkan ke kontrol yang diperlukan.

Pengantar gaya

Aplikasi dapat ditata dengan menggunakan Style kelas untuk mengelompokkan kumpulan nilai properti ke dalam satu objek yang kemudian dapat diterapkan ke beberapa elemen visual. Ini membantu mengurangi markup berulang, dan memungkinkan tampilan aplikasi menjadi lebih mudah diubah.

Meskipun gaya dirancang terutama untuk aplikasi berbasis XAML, gaya juga dapat dibuat di C#:

  • Style Objek yang dibuat di XAML biasanya didefinisikan dalam ResourceDictionary yang ditetapkan ke Resources kumpulan kontrol, halaman, atau ke Resources koleksi aplikasi.
  • Style objek yang dibuat di C# biasanya didefinisikan di kelas halaman, atau di kelas yang dapat diakses secara global.

Memilih tempat untuk menentukan Style dampak di mana dampaknya dapat digunakan:

  • Style instans yang ditentukan pada tingkat kontrol hanya dapat diterapkan ke kontrol dan ke turunannya.
  • Style instans yang ditentukan di tingkat halaman hanya dapat diterapkan ke halaman dan ke turunannya.
  • Style instans yang ditentukan di tingkat aplikasi dapat diterapkan di seluruh aplikasi.

Setiap Style objek berisi kumpulan satu atau beberapa Setter objek, dengan masing-masing Setter memiliki Property dan Value. Property adalah nama properti yang dapat diikat dari elemen tempat gaya diterapkan, dan Value adalah nilai yang diterapkan ke properti .

Setiap Style objek dapat eksplisit, atau implisit:

  • Objek eksplisitStyle didefinisikan dengan menentukan TargetType nilai dan x:Key , dan dengan mengatur properti elemen Style target ke x:Key referensi. Untuk informasi selengkapnya, lihat Gaya eksplisit.
  • Objek implisitStyle ditentukan dengan hanya TargetTypemenentukan . Objek kemudian akan secara otomatis diterapkan ke semua elemen jenis tersebut Style . Namun, subkelas TargetType tidak secara otomatis Style menerapkannya. Untuk informasi selengkapnya, lihat Gaya implisit.

Saat membuat Style, TargetType properti selalu diperlukan. Contoh berikut menunjukkan gaya eksplisit :

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

Untuk menerapkan Style, objek target haruslah yang VisualElement cocok dengan TargetType nilai properti dari Style:

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

Gaya yang lebih rendah dalam hierarki tampilan lebih diutamakan daripada yang ditentukan lebih tinggi. Misalnya, mengatur Style yang diatur Label.TextColor ke Red di tingkat aplikasi akan ditimpa oleh gaya tingkat halaman yang diatur Label.TextColor ke Green. Demikian pula, gaya tingkat halaman akan ditimpa oleh gaya tingkat kontrol. Selain itu, jika Label.TextColor diatur langsung pada properti kontrol, ini lebih diutamakan daripada gaya apa pun.

Gaya tidak merespons perubahan properti, dan tetap tidak berubah selama durasi aplikasi. Namun, aplikasi dapat menanggapi perubahan gaya secara dinamis saat runtime dengan menggunakan sumber daya dinamis. Untuk informasi selengkapnya, lihat Gaya dinamis.

Gaya eksplisit

Untuk membuat Style di tingkat halaman, harus ResourceDictionary ditambahkan ke halaman lalu satu atau beberapa Style deklarasi dapat disertakan dalam ResourceDictionary. Style dibuat eksplisit dengan memberikan atribut deklarasinyax:Key, yang memberinya kunci deskriptif di ResourceDictionary. Gaya eksplisit kemudian harus diterapkan ke elemen visual tertentu dengan mengatur propertinya Style .

Contoh berikut menunjukkan gaya eksplisit di halaman ResourceDictionary, dan diterapkan ke objek halaman 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>

Dalam contoh ini, ResourceDictionary menentukan tiga gaya yang secara eksplisit diatur pada objek halaman Label . Masing-masing Style digunakan untuk menampilkan teks dalam warna yang berbeda, sekaligus mengatur ukuran font, dan opsi tata letak horizontal dan vertikal. Masing-masing Style diterapkan ke yang berbeda Label dengan mengatur propertinya Style menggunakan StaticResource ekstensi markup. Selain itu, sementara final Label memiliki set Style di atasnya, ia juga mengambil alih TextColor properti ke nilai yang berbeda Color .

Gaya implisit

Untuk membuat Style di tingkat halaman, harus ResourceDictionary ditambahkan ke halaman lalu satu atau beberapa Style deklarasi dapat disertakan dalam ResourceDictionary. dibuat Styleimplisit dengan tidak menentukan x:Key atribut. Gaya kemudian akan diterapkan ke dalam elemen visual cakupan yang cocok TargetType dengan persis, tetapi tidak ke elemen yang berasal dari TargetType nilai .

Contoh kode berikut menunjukkan gaya implisit dalam halaman ResourceDictionary, dan diterapkan ke objek halaman Entry :

<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>

Dalam contoh ini, mendefinisikan satu gaya implisit yang secara implisit diatur pada objek halamanEntry.ResourceDictionary Style digunakan untuk menampilkan teks biru pada latar belakang kuning, sekaligus mengatur opsi penampilan lainnya. Style ditambahkan ke halaman ResourceDictionary tanpa menentukan x:Key atribut. Oleh karena itu, Style diterapkan ke semua Entry objek secara implisit karena cocok dengan TargetType properti yang Style tepat. Namun, Style tidak diterapkan ke CustomEntry objek , yang merupakan subkelas Entry. Selain itu, keempat Entry mengambil BackgroundColor alih properti dan TextColor gaya ke nilai yang berbeda Color .

Menerapkan gaya ke jenis turunan

Properti Style.ApplyToDerivedTypes memungkinkan gaya diterapkan ke kontrol yang berasal dari jenis dasar yang dirujuk oleh TargetType properti . Oleh karena itu, mengatur properti ini untuk true memungkinkan satu gaya untuk menargetkan beberapa jenis, asalkan jenis berasal dari jenis dasar yang ditentukan dalam TargetType properti.

Contoh berikut menunjukkan gaya implisit yang mengatur warna Button latar belakang instans menjadi merah:

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

Menempatkan gaya ini dalam tingkat ResourceDictionary halaman akan mengakibatkannya diterapkan ke semua Button objek di halaman, dan juga ke kontrol apa pun yang berasal dari Button. Namun, jika ApplyToDerivedTypes properti tetap tidak diatur, gaya hanya akan diterapkan ke Button objek.

Gaya global

Gaya dapat ditentukan secara global dengan menambahkannya ke kamus sumber daya aplikasi. Gaya ini kemudian dapat digunakan di seluruh aplikasi, dan membantu menghindari duplikasi gaya di seluruh halaman dan kontrol.

Contoh berikut menunjukkan yang Style ditentukan di tingkat aplikasi:


<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>

Dalam contoh ini, ResourceDictionary mendefinisikan satu gaya eksplisit , buttonStyle, yang akan digunakan untuk mengatur tampilan Button objek.

Catatan

Gaya global bisa eksplisit atau implisit.

Contoh berikut menunjukkan halaman yang menggunakan buttonStyle objek halaman 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>

Warisan gaya

Gaya dapat mewarisi dari gaya lain untuk mengurangi duplikasi dan mengaktifkan penggunaan kembali. Ini dicapai dengan mengatur Style.BasedOn properti ke yang sudah ada Style. Di XAML, ini dapat dicapai dengan mengatur BasedOn properti ke StaticResource ekstensi markup yang mereferensikan yang dibuat Stylesebelumnya .

Gaya yang mewarisi dari gaya dasar dapat menyertakan Setter instans untuk properti baru, atau menggunakannya untuk mengambil alih setter dari gaya dasar. Selain itu, gaya yang mewarisi dari gaya dasar harus menargetkan jenis yang sama, atau jenis yang berasal dari jenis yang ditargetkan oleh gaya dasar. Misalnya, jika gaya dasar menargetkan View objek, gaya yang didasarkan pada gaya dasar dapat menargetkan View objek atau jenis yang berasal dari View kelas, seperti Label objek dan Button .

Gaya hanya dapat mewarisi dari gaya pada tingkat yang sama, atau di atasnya, dalam hierarki tampilan. Ini berarti bahwa:

  • Gaya tingkat aplikasi hanya dapat mewarisi dari gaya tingkat aplikasi lainnya.
  • Gaya tingkat halaman dapat mewarisi dari gaya tingkat aplikasi, dan gaya tingkat halaman lainnya.
  • Gaya tingkat kontrol dapat mewarisi dari gaya tingkat aplikasi, gaya tingkat halaman, dan gaya tingkat kontrol lainnya.

Contoh berikut menunjukkan pewarisan gaya eksplisit :

<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>

Dalam contoh ini, baseStyle target View objek, dan mengatur HorizontalOptions properti dan VerticalOptions . baseStyle tidak diatur langsung pada kontrol apa pun. Sebagai gantinya, labelStyle dan buttonStyle mewarisinya, mengatur nilai properti tambahan yang dapat diikat. Objek labelStyle dan buttonStyle kemudian diatur pada Label dan Button.

Penting

Gaya implisit dapat berasal dari gaya eksplisit, tetapi gaya eksplisit tidak dapat berasal dari gaya implisit.

Gaya dinamis

Gaya tidak merespons perubahan properti, dan tetap tidak berubah selama durasi aplikasi. Misalnya, setelah menetapkan Style ke elemen visual, jika salah Setter satu objek dimodifikasi, dihapus, atau baru Setter ditambahkan, perubahan tidak akan diterapkan ke elemen visual. Namun, aplikasi dapat menanggapi perubahan gaya secara dinamis saat runtime dengan menggunakan sumber daya dinamis.

Ekstensi DynamicResource markup mirip StaticResource dengan ekstensi markup karena keduanya menggunakan kunci kamus untuk mengambil nilai dari ResourceDictionary. Namun, saat StaticResource melakukan pencarian kamus tunggal, DynamicResource mempertahankan tautan ke kunci kamus. Oleh karena itu, jika entri kamus yang terkait dengan kunci diganti, perubahan diterapkan ke elemen visual. Ini memungkinkan perubahan gaya runtime dilakukan di aplikasi.

Contoh berikut menunjukkan gaya dinamis :

<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>

Dalam contoh ini, SearchBar objek menggunakan DynamicResource ekstensi markup untuk mengatur bernama StyleblueSearchBarStyle. Kemudian SearchBar dapat memperbarui definisinya Style dalam kode:

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

Dalam contoh ini, definisi diperbarui blueSearchBarStyle untuk menggunakan nilai dari greenSearchBarStyle definisi. Ketika kode ini dijalankan, SearchBar akan diperbarui untuk menggunakan objek yang Setter ditentukan dalam greenSearchBarStyle.

Pewarisan gaya dinamis

Mendapatkan gaya dari gaya dinamis tidak dapat dicapai menggunakan Style.BasedOn properti . Sebaliknya, Style kelas menyertakan BaseResourceKey properti , yang dapat diatur ke kunci kamus yang nilainya mungkin berubah secara dinamis.

Contoh berikut menunjukkan pewarisan gaya dinamis :

<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>

Dalam contoh ini, objek menggunakan StaticResource ekstensi markup untuk mereferensikan bernama StyletealSearchBarStyle.SearchBar Ini Style mengatur beberapa properti tambahan dan menggunakan BaseResourceKey properti untuk mereferensikan blueSearchBarStyle. Ekstensi DynamicResource markup tidak diperlukan karena tealSearchBarStyle tidak akan berubah, kecuali dari Style yang berasal. Oleh karena itu, tealSearchBarStyle mempertahankan tautan ke blueSearchBarStyle dan diperbarui saat gaya dasar berubah.

Definisi blueSearchBarStyle dapat diperbarui dalam kode:

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

Dalam contoh ini, definisi diperbarui blueSearchBarStyle untuk menggunakan nilai dari greenSearchBarStyle definisi. Ketika kode ini dijalankan, SearchBar akan diperbarui untuk menggunakan objek yang Setter ditentukan dalam greenSearchBarStyle.

Kelas gaya

Kelas gaya memungkinkan beberapa gaya diterapkan ke kontrol, tanpa menggunakan pewarisan gaya.

Kelas gaya dapat dibuat dengan mengatur Class properti pada ke Stylestring yang mewakili nama kelas. Keuntungan dari penawaran ini, daripada mendefinisikan gaya eksplisit menggunakan x:Key atribut , adalah bahwa beberapa kelas gaya dapat diterapkan ke VisualElement.

Penting

Beberapa gaya dapat berbagi nama kelas yang sama, asalkan menargetkan berbagai jenis. Ini memungkinkan beberapa kelas gaya, yang diberi nama identik, untuk menargetkan berbagai jenis.

Contoh berikut menunjukkan tiga BoxView kelas gaya, dan VisualElement kelas gaya:

<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>

Dalam contoh ini, Separatorkelas gaya , Rounded, dan Circle mengatur BoxView setiap properti ke nilai tertentu. Kelas Rotated gaya memiliki TargetType dari VisualElement, yang berarti hanya dapat diterapkan ke VisualElement instans. Namun, propertinya ApplyToDerivedTypes diatur ke true, yang memastikan bahwa properti dapat diterapkan ke kontrol apa pun yang berasal dari VisualElement, seperti BoxView. Untuk informasi selengkapnya tentang menerapkan gaya ke jenis turunan, lihat Menerapkan gaya ke jenis turunan.

Kelas gaya dapat dikonsumsi dengan mengatur StyleClass properti kontrol, yang berjenis IList<string>, ke daftar nama kelas gaya. Kelas gaya akan diterapkan, asalkan jenis kontrol cocok dengan TargetType kelas gaya.

Contoh berikut menunjukkan tiga BoxView instans, masing-masing diatur ke kelas gaya yang berbeda:

<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>    

Dalam contoh ini, yang pertama BoxView ditata menjadi pemisah garis, sedangkan yang ketiga BoxView melingkar. Yang kedua BoxView memiliki dua kelas gaya yang diterapkan padanya, yang memberinya sudut bulat dan memutarnya 45 derajat:

Screenshot of BoxViews styled with style classes.

Penting

Beberapa kelas gaya dapat diterapkan ke kontrol karena StyleClass properti berjenis IList<string>. Ketika ini terjadi, kelas gaya diterapkan dalam urutan daftar naik. Oleh karena itu, ketika beberapa kelas gaya menetapkan properti yang identik, properti di kelas gaya yang berada di posisi daftar tertinggi akan diutamakan.