Bagikan melalui


Pedoman untuk Merancang Kontrol Bergaya

Dokumen ini meringkas serangkaian praktik terbaik yang perlu dipertimbangkan saat merancang kontrol yang ingin Anda buat agar mudah bergaya dan dapat di-templat. Kami datang ke serangkaian praktik terbaik ini melalui banyak percobaan dan kesalahan saat mengerjakan gaya kontrol tema untuk set kontrol WPF bawaan. Kami belajar bahwa gaya yang sukses adalah fungsi dari model objek yang dirancang dengan baik seperti gaya itu sendiri. Audiens yang dimaksudkan untuk dokumen ini adalah pembuat kontrol, bukan penulis gaya.

Terminologi

"Gaya dan templat" mengacu pada rangkaian teknologi yang memungkinkan penulis kontrol untuk menunda aspek visual kontrol ke gaya dan templat kontrol. Rangkaian teknologi ini meliputi:

  • Gaya (termasuk setter properti, pemicu, dan papan cerita).

  • Sumber daya.

  • Templat kontrol.

  • Templat data.

Untuk pengenalan gaya dan templat, lihat Gaya dan Templat.

Sebelum Memulai: Memahami kontrol Anda

Sebelum Anda melompat ke pedoman ini, penting untuk memahami dan telah menentukan penggunaan umum kontrol Anda. Gaya mengekspos serangkaian kemungkinan yang tidak dapat diatur. Kontrol yang ditulis untuk digunakan secara luas (dalam banyak aplikasi, oleh banyak pengembang) menghadapi tantangan bahwa gaya dapat digunakan untuk membuat perubahan yang jauh mencapai tampilan visual kontrol. Bahkan, kontrol bergaya bahkan mungkin tidak menyerupai niat pembuat kontrol. Karena fleksibilitas yang ditawarkan oleh gaya pada dasarnya tidak terbatas, Anda dapat menggunakan gagasan penggunaan umum untuk membantu Anda mencakup keputusan Anda.

Untuk memahami penggunaan umum kontrol Anda, ada baiknya untuk memikirkan proposisi nilai kontrol. Apa yang dibawa kontrol Anda ke tabel yang tidak dapat ditawarkan kontrol lain? Penggunaan umum tidak menyiratkan tampilan visual tertentu, melainkan filosofi kontrol dan serangkaian harapan yang wajar tentang penggunaannya. Pemahaman ini memungkinkan Anda membuat beberapa asumsi tentang model komposisi dan perilaku kontrol yang ditentukan gaya dalam kasus umum. Dalam kasus ComboBox, misalnya, memahami penggunaan umum tidak akan memberi Anda wawasan tentang apakah tertentu ComboBox memiliki sudut bulat, tetapi akan memberi Anda wawasan tentang fakta bahwa ComboBox mungkin membutuhkan jendela pop-up dan beberapa cara untuk beralih apakah itu terbuka.

Panduan Umum

  • Jangan memberlakukan kontrak templat secara ketat. Kontrak templat kontrol mungkin terdiri dari elemen, perintah, pengikatan, pemicu, atau bahkan pengaturan properti yang diperlukan atau diharapkan agar kontrol berfungsi dengan baik.

    • Minimalkan kontrak sebanyak mungkin.

    • Desain di sekitar harapan bahwa selama waktu desain (yaitu, saat menggunakan alat desain) adalah umum bagi templat kontrol untuk berada dalam keadaan tidak lengkap. WPF tidak menawarkan infrastruktur status "menyusun", sehingga kontrol harus dibangun dengan harapan bahwa status seperti itu mungkin valid.

    • Jangan melemparkan pengecualian ketika aspek apa pun dari kontrak templat tidak diikuti. Sepanjang garis-garis ini, panel tidak boleh melemparkan pengecualian jika mereka memiliki terlalu banyak atau terlalu sedikit anak.

  • Fungsionalitas periferal faktor ke dalam elemen pembantu templat. Setiap kontrol harus difokuskan pada fungsionalitas inti dan proposisi nilai sebenarnya dan ditentukan oleh penggunaan umum kontrol. Untuk itu, gunakan elemen komposisi dan pembantu dalam templat untuk mengaktifkan perilaku dan visualisasi periferal, yaitu perilaku dan visualisasi yang tidak berkontribusi pada fungsionalitas inti kontrol. Elemen pembantu termasuk dalam tiga kategori:

    • Jenis pembantu mandiri adalah kontrol publik dan dapat digunakan kembali atau primitif yang digunakan "secara anonim" dalam templat, yang berarti bahwa tidak ada elemen pembantu atau kontrol bergaya yang menyadari yang lain. Secara teknis, elemen apa pun dapat menjadi jenis anonim, tetapi dalam konteks ini istilah menjelaskan jenis-jenis yang merangkum fungsionalitas khusus untuk mengaktifkan skenario yang ditargetkan.

    • Elemen pembantu berbasis jenis adalah jenis baru yang merangkum fungsionalitas khusus. Elemen-elemen ini biasanya dirancang dengan rentang fungsionalitas yang lebih sempit daripada kontrol atau primitif umum. Tidak seperti elemen pembantu mandiri, elemen pembantu berbasis jenis mengetahui konteks tempat elemen tersebut digunakan dan biasanya harus berbagi data dengan kontrol ke templat tempat mereka berada.

    • Elemen pembantu bernama adalah kontrol umum atau primitif yang diharapkan oleh kontrol untuk ditemukan dalam templatnya berdasarkan nama. Elemen-elemen ini diberi nama terkenal dalam templat, memungkinkan kontrol untuk menemukan elemen dan berinteraksi dengannya secara terprogram. Hanya ada satu elemen dengan nama tertentu dalam templat apa pun.

    Tabel berikut menunjukkan elemen pembantu yang digunakan oleh gaya kontrol hari ini (daftar ini tidak lengkap):

    Elemen Jenis Digunakan oleh
    ContentPresenter Berbasis jenis Button, , CheckBoxRadioButton, Frame, dan sebagainya (semua ContentControl jenis)
    ItemsPresenter Berbasis jenis ListBox, , ComboBoxMenu, dan sebagainya (semua ItemsControl jenis)
    ToolBarOverflowPanel Dinamai ToolBar
    Popup Mandiri ComboBox, , ToolBarMenu, ToolTip, dan sebagainya
    RepeatButton Dinamai Slider, , ScrollBardan sebagainya
    ScrollBar Dinamai ScrollViewer
    ScrollViewer Mandiri ListBox, , ComboBoxMenu, Frame, dan sebagainya
    TabPanel Mandiri TabControl
    TextBox Dinamai ComboBox
    TickBar Berbasis jenis Slider
  • Minimalkan pengikatan yang ditentukan pengguna atau pengaturan properti yang diperlukan pada elemen pembantu. Adalah umum bagi elemen pembantu untuk memerlukan pengikatan atau pengaturan properti tertentu agar berfungsi dengan baik dalam templat kontrol. Elemen pembantu dan kontrol templat harus, sebanyak mungkin, menetapkan pengaturan ini. Saat mengatur properti atau membuat pengikatan, perhatian harus diambil untuk tidak mengambil alih nilai yang ditetapkan oleh pengguna. Praktik terbaik tertentu adalah sebagai berikut:

    • Elemen pembantu bernama harus diidentifikasi oleh induk dan induk harus menetapkan pengaturan yang diperlukan pada elemen pembantu.

    • Elemen pembantu berbasis jenis harus menetapkan pengaturan yang diperlukan langsung pada diri mereka sendiri. Melakukan ini mungkin memerlukan elemen pembantu untuk mengkueri konteks informasi tempat elemen tersebut digunakan, termasuk TemplatedParent (jenis kontrol templat tempatnya digunakan). Misalnya, ContentPresenter secara otomatis mengikat Content properti propertinya TemplatedParentContent saat digunakan dalam ContentControl jenis turunan.

    • Elemen pembantu mandiri tidak dapat dioptimalkan dengan cara ini karena, menurut definisi, baik elemen pembantu maupun induk tidak tahu tentang yang lain.

  • Gunakan properti Nama untuk menandai elemen dalam templat. Kontrol yang perlu menemukan elemen dalam gayanya untuk mengaksesnya secara terprogram harus melakukannya menggunakan Name properti dan FindName paradigma. Kontrol tidak boleh melemparkan pengecualian ketika elemen tidak ditemukan, tetapi menonaktifkan fungsionalitas secara diam-diam dan anggun yang memerlukan elemen tersebut.

  • Gunakan praktik terbaik untuk mengekspresikan status kontrol dan perilaku dalam gaya. Berikut ini adalah daftar praktik terbaik yang diurutkan untuk mengekspresikan perubahan dan perilaku status kontrol dalam gaya. Anda harus menggunakan item pertama pada daftar yang mengaktifkan skenario Anda.

    1. Pengikatan properti. Contoh: mengikat antara ComboBox.IsDropDownOpen dan ToggleButton.IsChecked.

    2. Perubahan properti yang dipicu atau animasi properti. Contoh: status hover dari Button.

    3. Perintah. Contoh: LineUpCommand / LineDownCommand di ScrollBar.

    4. Elemen pembantu mandiri. Contoh: TabPanel di TabControl.

    5. Jenis pembantu berbasis jenis. Contoh: ContentPresenter dalam Button, TickBar di Slider.

    6. Elemen pembantu bernama. Contoh: TextBox di ComboBox.

    7. Peristiwa gelembung dari jenis pembantu bernama. Jika Anda mendengarkan peristiwa gelembung dari elemen gaya, Anda harus mengharuskan elemen yang menghasilkan peristiwa dapat diidentifikasi secara unik. Contoh: Thumb di ToolBar.

    8. Perilaku kustom OnRender . Contoh: ButtonChrome di Button.

  • Gunakan pemicu gaya (dibandingkan dengan pemicu templat) dengan hemat. Pemicu yang memengaruhi properti pada elemen dalam templat harus dideklarasikan dalam templat. Pemicu yang memengaruhi properti pada kontrol (tidak ) TargetNamedapat dideklarasikan dalam gaya kecuali Anda tahu bahwa mengubah templat juga harus menghancurkan pemicu.

  • Konsisten dengan pola gaya yang ada. Sering kali ada beberapa cara untuk menyelesaikan masalah. Waspadalah dan, jika memungkinkan, konsisten dengan pola gaya kontrol yang ada. Ini sangat penting untuk kontrol yang berasal dari jenis dasar yang sama (misalnya, , ContentControlItemsControl, RangeBase, dan sebagainya).

  • Mengekspos properti untuk mengaktifkan skenario kustomisasi umum tanpa melakukan retemplating. WPF tidak mendukung bagian yang dapat dicolokkan/dapat disesuaikan, sehingga pengguna kontrol hanya dibiarkan dengan dua metode penyesuaian: mengatur properti secara langsung atau mengatur properti menggunakan gaya. Dengan mengingat hal itu, adalah tepat untuk memunculkan sejumlah properti terbatas yang ditargetkan pada skenario kustomisasi yang sangat umum dan berprioritas tinggi yang jika tidak akan memerlukan retemplating. Berikut adalah praktik terbaik kapan dan cara mengaktifkan skenario kustomisasi:

    • Penyesuaian yang sangat umum harus diekspos sebagai properti pada kontrol dan digunakan oleh templat.

    • Penyesuaian yang kurang umum (meskipun tidak jarang) harus diekspos sebagai properti terlampir dan dikonsumsi oleh templat.

    • Ini dapat diterima untuk penyesuaian yang diketahui tetapi langka untuk memerlukan retemplating.

Pertimbangan Tema

  • Gaya tema harus mencoba memiliki semantik properti yang konsisten di semua tema, tetapi tidak menjamin. Sebagai bagian dari dokumentasinya, kontrol Anda harus memiliki dokumen yang menjelaskan semantik properti kontrol, yaitu, "arti" properti untuk kontrol. Misalnya, ComboBox kontrol harus menentukan arti Background properti dalam ComboBox. Gaya default untuk kontrol Anda harus mencoba mengikuti semantik yang ditentukan dalam dokumen tersebut di semua tema. Mengontrol pengguna, di sisi lain, harus menyadari bahwa semantik properti dapat berubah dari tema ke tema. Dalam kasus tertentu, properti tertentu mungkin tidak dapat diekspresikan di bawah batasan visual yang diperlukan oleh tema tertentu. (Tema Klasik, misalnya, tidak memiliki satu batas yang Thickness dapat diterapkan untuk banyak kontrol.)

  • Gaya tema tidak perlu memiliki semantik pemicu yang konsisten di semua tema. Perilaku yang diekspos oleh gaya kontrol melalui pemicu atau animasi dapat bervariasi dari tema ke tema. Pengguna kontrol harus menyadari bahwa kontrol tidak akan selalu menggunakan mekanisme yang sama untuk mencapai perilaku tertentu di semua tema. Satu tema, misalnya, dapat menggunakan animasi untuk mengekspresikan perilaku hover di mana tema lain menggunakan pemicu. Ini dapat mengakibatkan inkonsistensi dalam pelestarian perilaku pada kontrol yang disesuaikan. (Mengubah properti latar belakang, misalnya, mungkin tidak memengaruhi status hover kontrol jika status tersebut dinyatakan menggunakan pemicu. Namun, jika status hover diimplementasikan menggunakan animasi, mengubah ke latar belakang dapat merusak animasi secara tidak dapat diperbandingkan dan oleh karena itu transisi status.)

  • Gaya tema tidak perlu memiliki semantik "tata letak" yang konsisten di semua tema. Misalnya, gaya default tidak perlu menjamin bahwa kontrol akan menempati jumlah ukuran yang sama di semua tema atau menjamin bahwa kontrol akan memiliki margin / padding konten yang sama di semua tema.

Baca juga