Di WPF, bagaimana saya menerapkan beberapa gaya ke FrameworkElement
? Misalnya, saya memiliki kontrol yang sudah memiliki gaya. Saya juga memiliki gaya terpisah yang ingin saya tambahkan tanpa menghilangkan yang pertama. Gaya memiliki TargetTypes berbeda, jadi saya tidak bisa hanya memperpanjang satu dengan yang lain.
153
Jawaban:
Saya pikir jawaban sederhana adalah bahwa Anda tidak dapat melakukan (paling tidak dalam versi WPF) apa yang Anda coba lakukan.
Yaitu, untuk elemen tertentu hanya satu Gaya yang dapat diterapkan.
Namun, seperti yang orang lain katakan di atas, mungkin Anda bisa menggunakan
BasedOn
untuk membantu Anda. Lihatlah bagian xaml longgar berikut ini. Di dalamnya Anda akan melihat bahwa saya memiliki gaya dasar yang menetapkan properti yang ada di kelas dasar elemen yang ingin saya terapkan dua gaya. Dan, dalam gaya kedua yang didasarkan pada gaya dasar, saya mengatur properti lain.Jadi, idenya di sini ... adalah jika Anda dapat memisahkan properti yang ingin Anda atur ... sesuai dengan hierarki warisan elemen yang ingin Anda atur beberapa gaya ... Anda mungkin memiliki solusinya.
Semoga ini membantu.
catatan:
Satu hal khusus yang perlu diperhatikan. Jika Anda mengubah
TargetType
gaya kedua (pada xaml set pertama di atas)ButtonBase
, kedua Gaya tidak diterapkan. Namun, periksa xaml berikut di bawah ini untuk mengatasi pembatasan itu. Pada dasarnya, itu berarti Anda perlu memberi Style sebuah kunci dan merujuknya dengan kunci itu.sumber
derivedStyle
harus datang setelahbaseStyle
Bea Stollnitz memiliki posting blog yang bagus tentang menggunakan ekstensi markup untuk ini, di bawah judul "Bagaimana saya bisa mengatur beberapa gaya di WPF?"
Blog itu sudah mati sekarang, jadi saya mereproduksi posting di sini
WPF dan Silverlight keduanya menawarkan kemampuan untuk mendapatkan Gaya dari Gaya lain melalui properti "BasedOn". Fitur ini memungkinkan pengembang untuk mengatur gaya mereka menggunakan hierarki yang mirip dengan warisan kelas. Pertimbangkan gaya berikut:
Dengan sintaks ini, sebuah Tombol yang menggunakan RedButtonStyle akan memiliki properti Foreground diatur ke Red dan properti Margin-nya diatur ke 10.
Fitur ini sudah ada di WPF sejak lama, dan ini baru di Silverlight 3.
Bagaimana jika Anda ingin mengatur lebih dari satu gaya pada elemen? Baik WPF maupun Silverlight tidak memberikan solusi untuk masalah ini di luar kebiasaan. Untungnya ada cara untuk menerapkan perilaku ini di WPF, yang akan saya bahas di posting blog ini.
WPF dan Silverlight menggunakan ekstensi markup untuk menyediakan properti dengan nilai-nilai yang memerlukan beberapa logika untuk diperoleh. Ekstensi markup mudah dikenali dengan adanya kurung keriting yang mengelilinginya di XAML. Misalnya, ekstensi markup {Binding} berisi logika untuk mengambil nilai dari sumber data dan memperbaruinya ketika terjadi perubahan; ekstensi markup {StaticResource} berisi logika untuk mengambil nilai dari kamus sumber daya berdasarkan kunci. Untungnya bagi kami, WPF memungkinkan pengguna untuk menulis ekstensi markup kustom mereka sendiri. Fitur ini belum ada di Silverlight, jadi solusi di blog ini hanya berlaku untuk WPF.
Yang lain telah menulis solusi hebat untuk menggabungkan dua gaya menggunakan ekstensi markup. Namun, saya menginginkan solusi yang memberikan kemampuan untuk menggabungkan jumlah gaya yang tidak terbatas, yang sedikit lebih rumit.
Menulis ekstensi markup sangat mudah. Langkah pertama adalah membuat kelas yang berasal dari MarkupExtension, dan gunakan atribut MarkupExtensionReturnType untuk menunjukkan bahwa Anda bermaksud nilai yang dikembalikan dari ekstensi markup Anda menjadi tipe Style.
Menentukan input untuk ekstensi markup
Kami ingin memberi pengguna ekstensi markup kami cara mudah untuk menentukan gaya yang akan digabungkan. Pada dasarnya ada dua cara di mana pengguna dapat menentukan input ke ekstensi markup. Pengguna dapat mengatur properti atau meneruskan parameter ke konstruktor. Karena dalam skenario ini pengguna memerlukan kemampuan untuk menentukan jumlah gaya yang tidak terbatas, pendekatan pertama saya adalah membuat konstruktor yang mengambil sejumlah string menggunakan kata kunci "params":
Tujuan saya adalah untuk dapat menulis input sebagai berikut:
Perhatikan koma yang memisahkan tombol gaya yang berbeda. Sayangnya, ekstensi markup kustom tidak mendukung sejumlah parameter konstruktor yang tidak terbatas, sehingga pendekatan ini menghasilkan kesalahan kompilasi. Jika saya tahu sebelumnya berapa banyak gaya yang ingin saya gabungkan, saya bisa menggunakan sintaks XAML yang sama dengan konstruktor yang mengambil jumlah string yang diinginkan:
Sebagai solusinya, saya memutuskan untuk meminta parameter konstruktor mengambil string tunggal yang menentukan nama gaya yang dipisahkan oleh spasi. Sintaksnya tidak terlalu buruk:
Menghitung output ekstensi markup
Untuk menghitung output dari ekstensi markup, kita perlu mengganti metode dari MarkupExtension yang disebut "ProvidValue". Nilai yang dikembalikan dari metode ini akan ditetapkan dalam target ekstensi markup.
Saya mulai dengan membuat metode ekstensi untuk Gaya yang tahu cara menggabungkan dua gaya. Kode untuk metode ini cukup sederhana:
Dengan logika di atas, gaya pertama dimodifikasi untuk memasukkan semua informasi dari yang kedua. Jika ada konflik (misalnya kedua gaya memiliki setter untuk properti yang sama), gaya kedua menang. Perhatikan bahwa selain menyalin gaya dan pemicu, saya juga memperhitungkan nilai TargetType dan BasedOn serta sumber daya apa pun yang mungkin dimiliki gaya kedua. Untuk TargetType dari gaya gabungan, saya menggunakan tipe yang lebih diturunkan. Jika gaya kedua memiliki gaya BasedOn, saya menggabungkan hierarki gaya secara rekursif. Jika memiliki sumber daya, saya menyalinnya ke gaya pertama. Jika sumber daya tersebut dirujuk menggunakan {StaticResource}, sumber daya tersebut diselesaikan secara statis sebelum kode gabungan ini dieksekusi, dan karenanya tidak perlu memindahkannya. Saya menambahkan kode ini jika kami menggunakan DynamicResources.
Metode ekstensi yang ditunjukkan di atas memungkinkan sintaks berikut:
Sintaks ini berguna asalkan saya memiliki contoh kedua gaya dalam ProvidValue. Ya saya tidak. Yang saya dapatkan dari konstruktor adalah daftar kunci string untuk gaya tersebut. Jika ada dukungan untuk params di parameter konstruktor, saya bisa menggunakan sintaks berikut untuk mendapatkan contoh gaya aktual:
Tapi itu tidak berhasil. Dan bahkan jika batasan params tidak ada, kita mungkin akan menemukan batasan lain dari ekstensi markup, di mana kita harus menggunakan sintaks properti-elemen alih-alih sintaks atribut untuk menentukan sumber daya statis, yang verbose dan rumit (saya jelaskan ini bug lebih baik di posting blog sebelumnya ). Dan bahkan jika kedua keterbatasan itu tidak ada, saya masih lebih suka menulis daftar gaya hanya dengan menggunakan nama mereka - lebih pendek dan lebih mudah dibaca daripada StaticResource untuk masing-masing.
Solusinya adalah membuat StaticResourceExtension menggunakan kode. Diberi kunci gaya string tipe dan penyedia layanan, saya bisa menggunakan StaticResourceExtension untuk mengambil contoh gaya aktual. Berikut ini sintaksnya:
Sekarang kita memiliki semua bagian yang diperlukan untuk menulis metode ProvidValue:
Berikut ini adalah contoh lengkap penggunaan ekstensi markup MultiStyle:
sumber
Tetapi Anda dapat memperluas dari yang lain .. lihatlah properti BasedOn
sumber
WPF / XAML tidak menyediakan fungsionalitas ini secara asli, tetapi memang memberikan ekstensibilitas untuk memungkinkan Anda melakukan apa yang Anda inginkan.
Kami bertemu dengan kebutuhan yang sama, dan akhirnya membuat Ekstensi XAML Markup kami sendiri (yang kami sebut "MergedStylesExtension") untuk memungkinkan kami membuat Gaya baru dari dua gaya lain (yang, jika perlu, mungkin dapat digunakan beberapa kali dalam suatu baris untuk mewarisi dari lebih banyak gaya).
Karena bug WPF / XAML, kita perlu menggunakan sintaks elemen properti untuk menggunakannya, tetapi selain itu tampaknya berfungsi ok. Misalnya,
Baru-baru ini saya menulis tentang hal ini di sini: http://swdeveloper.wordpress.com/2009/01/03/wpf-xaml-multiple-style-inheritance-and-markup-extensions/
sumber
Ini dimungkinkan dengan membuat kelas pembantu untuk menggunakan dan membungkus gaya Anda. CompoundStyle yang disebutkan di sini menunjukkan cara melakukannya. Ada beberapa cara, tetapi yang paling mudah adalah dengan melakukan yang berikut:
Semoga itu bisa membantu.
sumber
Gunakan
AttachedProperty
untuk mengatur beberapa gaya seperti kode berikut:Usege:
Hasil:
sumber
jika Anda tidak menyentuh properti tertentu, Anda bisa mendapatkan semua properti dasar dan umum dengan gaya yang tipe targetnya adalah FrameworkElement. kemudian, Anda dapat membuat rasa khusus untuk setiap jenis target yang Anda butuhkan, tanpa perlu menyalin semua properti umum itu lagi.
sumber
Anda mungkin bisa mendapatkan sesuatu yang serupa jika menerapkan ini ke koleksi item dengan menggunakan StyleSelector, saya telah menggunakan ini untuk mendekati masalah yang sama dalam menggunakan gaya yang berbeda pada TreeViewItems tergantung pada jenis objek terikat di pohon. Anda mungkin harus memodifikasi sedikit kelas di bawah ini untuk menyesuaikan dengan pendekatan khusus Anda, tetapi mudah-mudahan ini akan membantu Anda memulai
Anda kemudian menerapkannya seperti ini
sumber
Terkadang Anda bisa mendekati ini dengan panel bersarang. Katakanlah Anda memiliki Style yang mengubah Foreground dan perubahan lainnya FontSize, Anda dapat menerapkan yang terakhir pada TextBlock, dan meletakkannya di Grid yang Style-nya adalah yang pertama. Ini mungkin membantu dan mungkin cara termudah dalam beberapa kasus, meskipun tidak akan menyelesaikan semua masalah.
sumber
Ketika Anda mengganti SelectStyle Anda bisa mendapatkan properti GroupBy melalui refleksi seperti di bawah ini:
sumber
Jika Anda mencoba menerapkan gaya unik hanya ke satu elemen tunggal sebagai tambahan gaya dasar, ada cara yang sama sekali berbeda untuk melakukan ini yaitu IMHO jauh lebih baik untuk kode yang dapat dibaca dan dipelihara.
Sangat umum untuk perlu mengubah parameter per elemen individu. Menentukan gaya kamus hanya untuk digunakan pada satu elemen sangat rumit untuk mempertahankan atau membuat masuk akal. Untuk menghindari membuat gaya hanya untuk tweak elemen sekali saja, baca jawaban saya untuk pertanyaan saya sendiri di sini di sini:
https://stackoverflow.com/a/54497665/1402498
sumber