Gambaran umum properti terlampir (WPF .NET)

Properti terlampir adalah konsep Extensible Application Markup Language (XAML). Properti terlampir memungkinkan pasangan properti/nilai tambahan diatur pada elemen XAML apa pun yang berasal dari DependencyObject, meskipun elemen tidak menentukan properti tambahan tersebut dalam model objeknya. Properti tambahan dapat diakses secara global. Properti terlampir biasanya didefinisikan sebagai bentuk khusus properti dependensi yang tidak memiliki pembungkus properti konvensional.

Penting

Dokumentasi Panduan Desktop untuk .NET 7 dan .NET 6 sedang dibangun.

Prasyarat

Artikel ini mengasumsikan pengetahuan dasar tentang properti dependensi, dan bahwa Anda telah membaca gambaran umum properti Dependensi. Untuk mengikuti contoh dalam artikel ini, ini membantu jika Anda terbiasa dengan XAML dan tahu cara menulis aplikasi Windows Presentation Foundation (WPF).

Mengapa menggunakan properti terlampir

Properti terlampir memungkinkan elemen turunan menentukan nilai unik untuk properti yang ditentukan dalam elemen induk. Skenario umum adalah elemen turunan yang menentukan bagaimana elemen tersebut harus dirender di UI oleh elemen induknya. Misalnya, DockPanel.Dock adalah properti terlampir karena diatur pada elemen turunan dari DockPanel, bukan properti itu DockPanel sendiri. Kelas DockPanel mendefinisikan bidang statis DependencyProperty , bernama DockProperty, lalu menyediakan GetDock dan SetDock metode sebagai aksesor publik untuk properti terlampir.

Properti terlampir di XAML

Di XAML, Anda mengatur properti terlampir dengan menggunakan sintaks <attached property provider type>.<property name>, di mana penyedia properti terlampir adalah kelas yang menentukan properti terlampir. Contoh berikut menunjukkan bagaimana elemen turunan DockPanel dapat mengatur DockPanel.Dock nilai properti.

<DockPanel>
    <TextBox DockPanel.Dock="Top">Enter text</TextBox>
</DockPanel>

Penggunaannya mirip dengan properti statis di mana Anda mereferensikan jenis yang memiliki dan mendaftarkan properti terlampir (misalnya, DockPanel), bukan nama instans.

Saat Anda menentukan properti terlampir menggunakan atribut XAML, hanya tindakan yang ditetapkan yang berlaku. Anda tidak bisa langsung mendapatkan nilai properti melalui XAML, meskipun ada beberapa mekanisme tidak langsung untuk membandingkan nilai, seperti pemicu dalam gaya.

Properti terlampir di WPF

Properti terlampir adalah konsep XAML, properti dependensi adalah konsep WPF. Di WPF, sebagian besar properti terlampir terkait UI pada jenis WPF diimplementasikan sebagai properti dependensi. Properti terlampir WPF yang diimplementasikan sebagai properti dependensi mendukung konsep properti dependensi, seperti metadata properti termasuk nilai default dari metadata.

Model penggunaan properti terlampir

Meskipun objek apa pun dapat mengatur nilai properti terlampir, itu tidak berarti pengaturan nilai akan menghasilkan hasil nyata atau nilai akan digunakan oleh objek lain. Tujuan utama properti terlampir adalah untuk menyediakan cara bagi objek dari berbagai hierarki kelas dan hubungan logis untuk melaporkan informasi umum ke jenis yang menentukan properti terlampir. Penggunaan properti terlampir biasanya mengikuti salah satu model ini:

  • Jenis yang menentukan properti terlampir adalah induk elemen yang mengatur nilai untuk properti terlampir. Jenis induk menguraikan objek turunannya melalui logika internal yang bertindak pada struktur pohon objek, mendapatkan nilai, dan bertindak pada nilai-nilai tersebut dengan cara tertentu.
  • Jenis yang mendefinisikan properti terlampir digunakan sebagai elemen turunan untuk berbagai elemen induk dan con mode tenda ls yang mungkin.
  • Jenis yang menentukan properti terlampir mewakili layanan. Jenis lain mengatur nilai untuk properti terlampir. Kemudian, ketika elemen yang mengatur properti dievaluasi dalam konteks layanan, nilai properti terlampir diperoleh melalui logika internal kelas layanan.

Contoh properti terlampir yang ditentukan induk

Skenario umum di mana WPF mendefinisikan properti terlampir adalah ketika elemen induk mendukung pengumpulan elemen turunan, dan elemen induk mengimplementasikan perilaku berdasarkan data yang dilaporkan oleh setiap elemen turunannya.

DockPanelDockPanel.Dock menentukan properti terlampir. DockPanel memiliki kode tingkat kelas, khususnya MeasureOverride dan ArrangeOverride, itu adalah bagian dari logika penyajiannya. DockPanel Instans memeriksa apakah salah satu elemen turunan langsungnya telah menetapkan nilai untuk DockPanel.Dock. Jika demikian, nilai-nilai tersebut menjadi input ke logika penyajian yang diterapkan ke setiap elemen turunan. Meskipun secara teoritis mungkin bagi properti terlampir untuk memengaruhi elemen di luar induk langsung, perilaku yang ditentukan untuk instans berlapis DockPanel adalah hanya berinteraksi dengan koleksi elemen turunan langsungnya. Jadi, jika Anda mengatur DockPanel.Dock elemen yang tidak DockPanel memiliki induk, tidak ada kesalahan atau pengecualian yang akan dimunculkan dan Anda akan membuat nilai properti global yang tidak akan dikonsumsi oleh .DockPanel

Properti terlampir dalam kode

Properti terlampir di WPF tidak memiliki metode CLR get dan set pembungkus umum karena properti mungkin diatur dari luar namespace CLR. Untuk mengizinkan prosesor XAML mengatur nilai-nilai tersebut saat mengurai XAML, kelas yang menentukan properti terlampir harus menerapkan metode aksesor khusus dalam bentuk Get<property name> dan Set<property name>.

Anda juga dapat menggunakan metode aksesor khusus untuk mendapatkan dan mengatur properti terlampir dalam kode, seperti yang ditunjukkan dalam contoh berikut. Dalam contoh, myTextBox adalah instans TextBox kelas .

DockPanel myDockPanel = new();
TextBox myTextBox = new();
myTextBox.Text = "Enter text";

// Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox);

// Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top);
Dim myDockPanel As DockPanel = New DockPanel()
Dim myTextBox As TextBox = New TextBox()
myTextBox.Text = "Enter text"

' Add child element to the DockPanel.
myDockPanel.Children.Add(myTextBox)

' Set the attached property value.
DockPanel.SetDock(myTextBox, Dock.Top)

Jika Anda tidak menambahkan myTextBox sebagai elemen turunan , myDockPanelpanggilan SetDock tidak akan menimbulkan pengecualian atau memiliki efek apa pun. Hanya nilai yang DockPanel.Dock ditetapkan pada elemen anak dari yang DockPanel dapat memengaruhi penyajian, dan penyajian akan sama apakah Anda mengatur nilai sebelum atau sesudah menambahkan elemen turunan ke DockPanel.

Dari perspektif kode, properti terlampir seperti bidang backing yang memiliki aksesor metode alih-alih aksesor properti, dan dapat diatur pada objek apa pun tanpa harus terlebih dahulu didefinisikan pada objek tersebut.

Metadata properti terlampir

Metadata untuk properti terlampir umumnya tidak berbeda dari untuk properti dependensi. Saat mendaftarkan properti terlampir, gunakan FrameworkPropertyMetadata untuk menentukan karakteristik properti, seperti apakah properti memengaruhi penyajian atau pengukuran. Saat Anda menentukan nilai default dengan menimpa metadata properti terlampir, nilai tersebut menjadi default untuk properti terlampir implisit pada instans kelas penimpaan. Jika nilai properti terlampir tidak diatur, nilai default dilaporkan saat properti dikueri dengan menggunakan Get<property name> aksesor dengan instans kelas tempat Anda menentukan metadata.

Untuk mengaktifkan pewarisan nilai properti pada properti, gunakan properti terlampir alih-alih properti dependensi yang tidak terpasang. Untuk informasi selengkapnya, lihat Pewarisan nilai properti.

Properti terlampir kustom

Kapan harus membuat properti terlampir

Membuat properti terlampir berguna saat:

  • Anda memerlukan mekanisme pengaturan properti yang tersedia untuk kelas selain kelas yang menentukan. Skenario umum adalah untuk tata letak UI, misalnya DockPanel.Dock, , Panel.ZIndex, dan Canvas.Top semua contoh properti tata letak yang ada. Dalam skenario tata letak, elemen turunan dari elemen pengontrol tata letak dapat mengekspresikan persyaratan tata letak ke induk tata letaknya dan untuk menetapkan nilai untuk properti terlampir yang ditentukan oleh induk.

  • Salah satu kelas Anda mewakili layanan, dan Anda ingin kelas lain mengintegrasikan layanan secara lebih transparan.

  • Anda ingin dukungan Visual Studio WPF Designer, seperti kemampuan untuk mengedit properti melalui jendela Properti . Untuk informasi selengkapnya, lihat Gambaran umum penulisan kontrol.

  • Anda ingin menggunakan pewarisan nilai properti.

Cara membuat properti terlampir

Jika kelas Anda mendefinisikan properti terlampir hanya untuk digunakan oleh jenis lain, kelas Anda tidak perlu berasal dari DependencyObject. Jika tidak, ikuti model WPF untuk memiliki properti terlampir juga menjadi properti dependensi, dengan mengambil kelas Anda dari DependencyObject.

Tentukan properti terlampir Anda sebagai dependensi di kelas yang menentukan dengan mendeklarasikan public static readonly bidang jenis DependencyProperty. Kemudian, tetapkan nilai RegisterAttached pengembalian metode ke bidang , yang juga dikenal sebagai pengidentifikasi properti dependensi. Ikuti konvensi penamaan properti WPF yang membedakan bidang dari properti yang diwakilinya, dengan memberi nama bidang <property name>Propertypengidentifikasi . Selain itu, berikan metode statis Get<property name> dan Set<property name> aksesor, yang memungkinkan sistem properti mengakses properti terlampir Anda.

Contoh berikut menunjukkan cara mendaftarkan properti dependensi menggunakan RegisterAttached metode , dan cara menentukan metode aksesor. Dalam contoh, nama properti terlampir adalah HasFish, sehingga bidang pengidentifikasi diberi nama HasFishProperty, dan metode aksesor diberi nama GetHasFish dan SetHasFish.

public class Aquarium : UIElement
{
    // Register an attached dependency property with the specified
    // property name, property type, owner type, and property metadata.
    public static readonly DependencyProperty HasFishProperty = 
        DependencyProperty.RegisterAttached(
      "HasFish",
      typeof(bool),
      typeof(Aquarium),
      new FrameworkPropertyMetadata(defaultValue: false,
          flags: FrameworkPropertyMetadataOptions.AffectsRender)
    );

    // Declare a get accessor method.
    public static bool GetHasFish(UIElement target) =>
        (bool)target.GetValue(HasFishProperty);

    // Declare a set accessor method.
    public static void SetHasFish(UIElement target, bool value) =>
        target.SetValue(HasFishProperty, value);
}
Public Class Aquarium
    Inherits UIElement

    ' Register an attached dependency property with the specified
    ' property name, property type, owner type, and property metadata.
    Public Shared ReadOnly HasFishProperty As DependencyProperty =
        DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium),
            New FrameworkPropertyMetadata(defaultValue:=False,
                flags:=FrameworkPropertyMetadataOptions.AffectsRender))

    ' Declare a get accessor method.
    Public Shared Function GetHasFish(target As UIElement) As Boolean
        Return target.GetValue(HasFishProperty)
    End Function

    ' Declare a set accessor method.
    Public Shared Sub SetHasFish(target As UIElement, value As Boolean)
        target.SetValue(HasFishProperty, value)
    End Sub

End Class

Dapatkan aksesor

Tanda get tangan metode aksesor adalah public static object Get<property name>(DependencyObject target), di mana:

  • target adalah tempat DependencyObject properti terlampir dibaca. Jenisnya target bisa lebih spesifik daripada DependencyObject. Misalnya, DockPanel.GetDock metode aksesor mengetik target sebagai UIElement karena properti terlampir dimaksudkan untuk diatur pada UIElement instans. UiElement secara tidak langsung berasal dari DependencyObject.
  • Jenis pengembalian bisa lebih spesifik daripada object. Misalnya, GetDock metode mengetikkan nilai yang dikembalikan karena Dock nilai yang dikembalikan harus menjadi Dock enumerasi.

Catatan

Aksesor get untuk properti terlampir diperlukan untuk dukungan pengikatan data dalam alat desain, seperti Visual Studio atau Blend untuk Visual Studio.

Atur aksesor

Tanda set tangan metode aksesor adalah public static void Set<property name>(DependencyObject target, object value), di mana:

  • target adalah tempat DependencyObject properti terlampir ditulis. Jenisnya target bisa lebih spesifik daripada DependencyObject. Misalnya, SetDock metode mengetik target sebagai UIElement karena properti terlampir dimaksudkan untuk diatur pada UIElement instans. UiElement secara tidak langsung berasal dari DependencyObject.
  • Jenisnya value bisa lebih spesifik daripada object. Misalnya, SetDock metode ini memerlukan Dock nilai. Pemuat XAML harus dapat menghasilkan value jenis dari string markup yang mewakili nilai properti terlampir. Jadi, harus ada konversi jenis, serializer nilai, atau dukungan ekstensi markup untuk jenis yang Anda gunakan.

Atribut properti terlampir

WPF mendefinisikan beberapa atribut .NET yang menyediakan informasi tentang properti terlampir ke proses refleksi dan juga kepada konsumen informasi refleksi dan properti, seperti desainer. Desainer menggunakan atribut .NET yang ditentukan WPF untuk membatasi properti yang ditunjukkan di jendela properti, untuk menghindari pengguna yang kewalahan dengan daftar global semua properti terlampir. Anda mungkin mempertimbangkan untuk menerapkan atribut ini ke properti terlampir kustom Anda sendiri. Tujuan dan sintaks atribut .NET dijelaskan dalam halaman referensi ini:

Pelajari lebih lanjut

  • Untuk informasi selengkapnya tentang membuat properti terlampir, lihat Mendaftarkan properti terlampir.
  • Untuk skenario penggunaan tingkat lanjut lainnya untuk properti dependensi dan properti terlampir, lihat Properti dependensi kustom.
  • Anda dapat mendaftarkan properti sebagai properti terlampir dan properti dependensi, dan menyertakan pembungkus properti konvensional. Dengan cara ini, properti dapat diatur pada elemen dengan menggunakan pembungkus properti, dan juga pada elemen lain dengan menggunakan sintaks properti terlampir XAML. Misalnya, lihat FrameworkElement.FlowDirection.

Baca juga