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 keResources
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 eksplisit Style didefinisikan dengan menentukan
TargetType
nilai danx:Key
, dan dengan mengatur properti elemen Style target kex:Key
referensi. Untuk informasi selengkapnya, lihat Gaya eksplisit. - Objek implisit Style ditentukan dengan hanya
TargetType
menentukan . Objek kemudian akan secara otomatis diterapkan ke semua elemen jenis tersebut Style . Namun, subkelasTargetType
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 Style implisit 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 Style blueSearchBarStyle
. 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 Style tealSearchBarStyle
.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 Style string
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, Separator
kelas 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:
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.