Bagikan melalui


Gambaran umum peristiwa yang dirutekan (WPF .NET)

Pengembang aplikasi dan penulis komponen Windows Presentation Foundation (WPF) dapat menggunakan peristiwa yang dirutekan untuk menyebarkan peristiwa melalui pohon elemen, dan memanggil penanganan aktivitas pada beberapa pendengar di pohon. Fitur-fitur ini tidak ditemukan dalam peristiwa runtime bahasa umum (CLR). Beberapa peristiwa WPF adalah peristiwa yang dirutekan, seperti ButtonBase.Click. Artikel ini membahas konsep peristiwa dasar yang dirutekan dan menawarkan panduan tentang kapan dan cara merespons peristiwa yang dirutekan.

Penting

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

Prasyarat

Artikel ini mengasumsikan pengetahuan dasar tentang runtime bahasa umum (CLR), pemrograman berorientasi objek, dan bagaimana tata letak elemen WPF dapat dikonsep sebagai pohon. Untuk mengikuti contoh dalam artikel ini, ini membantu jika Anda terbiasa dengan Extensible Application Markup Language (XAML) dan tahu cara menulis aplikasi WPF.

Apa itu peristiwa yang dirutekan?

Anda dapat mempertimbangkan peristiwa yang dirutekan dari perspektif fungsional atau implementasi:

  • Dari perspektif fungsional, peristiwa yang dirutekan adalah jenis peristiwa yang dapat memanggil handler pada beberapa pendengar di pohon elemen, bukan hanya pada sumber peristiwa. Pendengar peristiwa adalah elemen tempat penanganan aktivitas dilampirkan dan dipanggil. Sumber peristiwa adalah elemen atau objek yang awalnya memunculkan peristiwa.

  • Dari perspektif implementasi, peristiwa yang dirutekan adalah peristiwa yang terdaftar dengan sistem peristiwa WPF, didukung oleh instans RoutedEvent kelas, dan diproses oleh sistem peristiwa WPF. Biasanya, peristiwa yang dirutekan diimplementasikan dengan "pembungkus" peristiwa CLR untuk memungkinkan penghandel pemasangan di XAML dan di belakang kode seperti yang Anda lakukan pada peristiwa CLR.

Aplikasi WPF biasanya berisi banyak elemen, yang dideklarasikan dalam XAML atau dibuat dalam kode. Elemen aplikasi ada di dalam pohon elemennya. Bergantung pada bagaimana peristiwa yang dirutekan ditentukan, ketika peristiwa dinaikkan pada elemen sumber:

  • Gelembung melalui pohon elemen dari elemen sumber ke elemen akar, yang biasanya merupakan halaman atau jendela.
  • Terowongan turun melalui pohon elemen dari elemen akar ke elemen sumber.
  • Tidak berjalan melalui pohon elemen, dan hanya terjadi pada elemen sumber.

Pertimbangkan pohon elemen parsial berikut:

<Border Height="30" Width="200" BorderBrush="Gray" BorderThickness="1">
    <StackPanel Background="LightBlue" Orientation="Horizontal" Button.Click="YesNoCancelButton_Click">
        <Button Name="YesButton">Yes</Button>
        <Button Name="NoButton">No</Button>
        <Button Name="CancelButton">Cancel</Button>
    </StackPanel>
</Border>

Pohon elemen merender seperti yang ditunjukkan:

Yes, No, and Cancel buttons.

Masing-masing dari tiga tombol adalah sumber peristiwa potensial Click . Ketika salah satu tombol diklik, tombol akan menaikkan Click peristiwa yang menggelegak dari tombol ke elemen akar. Elemen Button dan Border tidak memiliki penanganan aktivitas yang terpasang, tetapi StackPanel tidak. Mungkin elemen lain lebih tinggi di pohon yang tidak ditampilkan juga memiliki Click penanganan aktivitas yang terpasang. Click Ketika peristiwa mencapai StackPanel elemen , sistem peristiwa WPF memanggil YesNoCancelButton_Click handler yang melekat padanya. Rute peristiwa untuk Click peristiwa dalam contoh adalah: Button ->StackPanel ->Border -> elemen induk berturut-turut.

Catatan

Elemen yang awalnya menaikkan peristiwa yang dirutekan diidentifikasi sebagai RoutedEventArgs.Source dalam parameter penanganan aktivitas. Pendengar peristiwa adalah elemen tempat penanganan aktivitas dilampirkan dan dipanggil, dan diidentifikasi sebagai pengirim dalam parameter penanganan aktivitas.

Skenario tingkat atas untuk peristiwa yang dirutekan

Berikut adalah beberapa skenario yang memotivasi konsep peristiwa yang dirutekan, dan membedakannya dari peristiwa CLR yang khas:

  • Komposisi kontrol dan enkapulasi: Berbagai kontrol dalam WPF memiliki kon mode tenda l yang kaya. Misalnya, Anda dapat menempatkan gambar di dalam Button, yang secara efektif memperluas pohon visual tombol. Tetapi, gambar yang ditambahkan tidak boleh merusak perilaku uji klik tombol, yang perlu merespons saat pengguna mengklik piksel gambar.

  • Titik lampiran handler tunggal: Anda dapat mendaftarkan handler untuk setiap peristiwa tombol Click , tetapi dengan peristiwa yang dirutekan, Anda dapat melampirkan satu handler seperti yang ditunjukkan pada contoh XAML sebelumnya. Ini memungkinkan Anda mengubah pohon elemen di bawah handler tunggal, seperti menambahkan atau menghapus lebih banyak tombol, tanpa harus mendaftarkan setiap peristiwa tombol Click . Click Ketika peristiwa dinaikkan, logika handler dapat menentukan dari mana peristiwa berasal. Handler berikut, yang ditentukan dalam pohon elemen XAML yang ditampilkan sebelumnya, berisi logika tersebut:

    private void YesNoCancelButton_Click(object sender, RoutedEventArgs e)
    {
        FrameworkElement sourceFrameworkElement = e.Source as FrameworkElement;
        switch (sourceFrameworkElement.Name)
        {
            case "YesButton":
                // YesButton logic.
                break;
            case "NoButton":
                // NoButton logic.
                break;
            case "CancelButton":
                // CancelButton logic.
                break;
        }
        e.Handled = true;
    }
    
    Private Sub YesNoCancelButton_Click(sender As Object, e As RoutedEventArgs)
        Dim frameworkElementSource As FrameworkElement = TryCast(e.Source, FrameworkElement)
    
        Select Case frameworkElementSource.Name
            Case "YesButton"
                ' YesButton logic.
            Case "NoButton"
                ' NoButton logic.
            Case "CancelButton"
                ' CancelButton logic.
        End Select
    
        e.Handled = True
    End Sub
    
  • Penanganan kelas: Peristiwa yang dirutekan mendukung penanganan aktivitas kelas yang Anda tentukan di kelas. Handler kelas menangani peristiwa sebelum handler instans apa pun untuk peristiwa yang sama pada instans kelas apa pun.

  • Mereferensikan peristiwa tanpa refleksi: Setiap peristiwa yang dirutekan membuat RoutedEvent pengidentifikasi bidang untuk menyediakan teknik identifikasi peristiwa yang kuat yang tidak memerlukan refleksi statis atau run-time untuk mengidentifikasi peristiwa.

Bagaimana peristiwa yang dirutekan diterapkan

Peristiwa yang dirutekan adalah peristiwa yang terdaftar dengan sistem peristiwa WPF, didukung oleh instans RoutedEvent kelas, dan diproses oleh sistem peristiwa WPF. Instans RoutedEvent , yang diperoleh dari pendaftaran, biasanya disimpan sebagai public static readonly anggota kelas yang mendaftarkannya. Kelas tersebut disebut sebagai kelas "pemilik" peristiwa. Biasanya, peristiwa yang dirutekan mengimplementasikan peristiwa CLR bernama "wrapper" yang identik. Pembungkus peristiwa CLR berisi add dan remove aksesor untuk mengaktifkan penghandel pemasangan di XAML dan di code-behind melalui sintaks peristiwa khusus bahasa. remove Dan add aksesor mengambil alih implementasi CLR mereka dan memanggil peristiwa AddHandler dan RemoveHandler metode yang dirutekan. Mekanisme dukungan peristiwa dan koneksi yang dirutekan secara konseptual mirip dengan bagaimana properti dependensi adalah properti CLR yang didukung oleh DependencyProperty kelas dan terdaftar di sistem properti WPF.

Contoh berikut mendaftarkan peristiwa yang dirutekan Tap , menyimpan instans yang dikembalikan RoutedEvent , dan mengimplementasikan pembungkus peristiwa CLR.

// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
    name: "Tap",
    routingStrategy: RoutingStrategy.Bubble,
    handlerType: typeof(RoutedEventHandler),
    ownerType: typeof(CustomButton));

// Provide CLR accessors for adding and removing an event handler.
public event RoutedEventHandler Tap
{
    add { AddHandler(TapEvent, value); }
    remove { RemoveHandler(TapEvent, value); }
}
' Register a custom routed event using the Bubble routing strategy.
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
    name:="Tap",
    routingStrategy:=RoutingStrategy.Bubble,
    handlerType:=GetType(RoutedEventHandler),
    ownerType:=GetType(CustomButton))

' Provide CLR accessors for adding and removing an event handler.
Public Custom Event Tap As RoutedEventHandler
    AddHandler(value As RoutedEventHandler)
        [AddHandler](TapEvent, value)
    End AddHandler

    RemoveHandler(value As RoutedEventHandler)
        [RemoveHandler](TapEvent, value)
    End RemoveHandler

    RaiseEvent(sender As Object, e As RoutedEventArgs)
        [RaiseEvent](e)
    End RaiseEvent
End Event

Strategi perutean

Peristiwa yang dirutekan menggunakan salah satu dari tiga strategi perutean:

  • Gelembung: Awalnya, penanganan aktivitas pada sumber peristiwa dipanggil. Peristiwa yang dirutekan kemudian merutekan ke elemen induk berturut-turut, memanggil penanganan aktivitas mereka secara bergantian, hingga mencapai akar pohon elemen. Sebagian besar peristiwa yang dirutekan menggunakan strategi perutean yang menggelegak. Peristiwa yang dirutekan gelembung umumnya digunakan untuk melaporkan perubahan input atau status dari kontrol komposit atau elemen UI lainnya.

  • Tunneling: Awalnya, penanganan aktivitas di akar pohon elemen dipanggil. Peristiwa yang dirutekan kemudian merutekan ke elemen anak berturut-turut, memanggil penanganan aktivitas mereka secara bergantian, hingga mencapai sumber peristiwa. Peristiwa yang mengikuti rute penerowongan juga disebut sebagai peristiwa Pratinjau . Peristiwa input WPF umumnya diimplementasikan sebagai pratinjau dan pasangan gelembung.

  • Langsung: Hanya penanganan aktivitas pada sumber peristiwa yang dipanggil. Strategi non-perutean ini dianalogikan dengan Formulir Windows peristiwa kerangka kerja UI, yang merupakan peristiwa CLR standar. Tidak seperti peristiwa CLR, peristiwa yang dirutekan langsung mendukung penanganan kelas dan dapat digunakan oleh EventSetters dan EventTriggers.

Mengapa menggunakan peristiwa yang dirutekan?

Sebagai pengembang aplikasi, Anda tidak selalu perlu mengetahui atau peduli bahwa peristiwa yang Anda tangani diimplementasikan sebagai peristiwa yang dirutekan. Peristiwa yang dirutekan memiliki perilaku khusus, tetapi perilaku tersebut sebagian besar tidak terlihat jika Anda menangani peristiwa pada elemen yang mengangkatnya. Namun, peristiwa yang dirutekan relevan ketika Anda ingin melampirkan penanganan aktivitas ke elemen induk untuk menangani peristiwa yang dimunculkan oleh elemen turunan, seperti dalam kontrol komposit.

Pendengar peristiwa yang dirutekan tidak memerlukan peristiwa yang dirutekan yang mereka tangani untuk menjadi anggota kelas mereka. Apa pun UIElement atau ContentElement dapat menjadi pendengar peristiwa untuk setiap peristiwa yang dirutekan. Karena elemen visual berasal dari UIElement atau ContentElement, Anda dapat menggunakan peristiwa yang dirutekan sebagai "antarmuka" konseptual yang mendukung pertukaran informasi peristiwa antara elemen yang berbeda dalam aplikasi. Konsep "antarmuka" untuk peristiwa yang dirutekan terutama berlaku untuk peristiwa input.

Peristiwa yang dirutekan mendukung pertukaran informasi peristiwa antar elemen di sepanjang rute peristiwa karena setiap pendengar memiliki akses ke instans data peristiwa yang sama. Jika satu elemen mengubah sesuatu dalam data peristiwa, perubahan tersebut terlihat oleh elemen berikutnya dalam rute peristiwa.

Terlepas dari aspek perutean, Anda dapat memilih untuk menerapkan peristiwa yang dirutekan alih-alih peristiwa CLR standar karena alasan ini:

  • Beberapa fitur gaya dan templat WPF, seperti EventSetters dan EventTriggers, mengharuskan peristiwa yang direferensikan menjadi peristiwa yang dirutekan.

  • Peristiwa yang dirutekan mendukung penanganan aktivitas kelas yang menangani peristiwa di depan handler instans apa pun untuk peristiwa yang sama pada instans kelas pendengar apa pun. Fitur ini berguna dalam desain kontrol karena handler kelas Anda dapat memberlakukan perilaku kelas berbasis peristiwa yang tidak dapat ditekan secara tidak sengaja oleh handler instans.

Melampirkan dan mengimplementasikan penanganan aktivitas yang dirutekan

Di XAML, Anda melampirkan penanganan aktivitas ke elemen dengan mendeklarasikan nama peristiwa sebagai atribut pada elemen pendengar peristiwa. Nilai atribut adalah nama metode handler Anda. Metode handler harus diimplementasikan di kelas parsial code-behind untuk halaman XAML. Pendengar peristiwa adalah elemen tempat penanganan aktivitas dilampirkan dan dipanggil.

Untuk peristiwa yang merupakan anggota (diwarisi atau dinyatakan lain) dari kelas pendengar, Anda dapat melampirkan handler sebagai berikut:

<Button Name="Button1" Click="Button_Click">Click me</Button>

Jika peristiwa bukan anggota kelas pendengar, Anda harus menggunakan nama peristiwa yang memenuhi syarat dalam bentuk <owner type>.<event name>. Misalnya, karena StackPanel kelas tidak mengimplementasikan Click peristiwa, untuk melampirkan handler ke StackPanel untuk Click peristiwa yang menggelegak hingga elemen tersebut, Anda harus menggunakan sintaks nama peristiwa yang memenuhi syarat:

<StackPanel Name="StackPanel1" Button.Click="Button_Click">
    <Button>Click me</Button>
</StackPanel>

Tanda tangan metode penanganan aktivitas di code-behind harus cocok dengan jenis delegasi untuk peristiwa yang dirutekan. Parameter senderRoutedEventHandler delegasi untuk Click peristiwa menentukan elemen tempat penanganan aktivitas dilampirkan. Parameter argsRoutedEventHandler delegasi berisi data peristiwa. Implementasi code-behind yang Button_Click kompatibel untuk penanganan aktivitas mungkin:

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Click event logic.
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    ' Click event logic.
End Sub

Meskipun RoutedEventHandler merupakan delegasi penanganan aktivitas rute dasar, beberapa skenario kontrol atau implementasi memerlukan delegasi yang berbeda yang mendukung data peristiwa yang lebih khusus. Sebagai contoh, untuk peristiwa yang dirutekan DragEnter , handler Anda harus mengimplementasikan DragEventHandler delegasi. Dengan demikian, kode handler Anda dapat mengakses DragEventArgs.Data properti dalam data peristiwa, yang berisi payload clipboard dari operasi seret.

Sintaks XAML untuk menambahkan penanganan aktivitas yang dirutekan sama dengan untuk penanganan aktivitas CLR standar. Untuk informasi selengkapnya tentang menambahkan penanganan aktivitas di XAML, lihat XAML di WPF. Untuk contoh lengkap tentang cara melampirkan penanganan aktivitas ke elemen menggunakan XAML, lihat Cara menangani peristiwa yang dirutekan.

Untuk melampirkan penanganan aktivitas untuk peristiwa yang dirutekan ke elemen menggunakan kode, Anda umumnya memiliki dua opsi:

  • Langsung panggil metode .AddHandler Penanganan aktivitas yang dirutekan selalu dapat dilampirkan dengan cara ini. Contoh ini melampirkan Click penanganan aktivitas ke tombol menggunakan AddHandler metode :

    Button1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
    
    Button1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
    

    Untuk melampirkan handler untuk peristiwa tombol Click ke elemen yang berbeda dalam rute peristiwa, seperti bernama StackPanelStackPanel1:

    StackPanel1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
    
    StackPanel1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
    
  • Jika peristiwa yang dirutekan mengimplementasikan pembungkus peristiwa CLR, gunakan sintaks peristiwa khusus bahasa untuk menambahkan penanganan aktivitas seperti yang Anda lakukan untuk peristiwa CLR standar. Sebagian besar peristiwa rute WPF yang ada mengimplementasikan pembungkus CLR, sehingga memungkinkan sintaks peristiwa khusus bahasa. Contoh ini melampirkan Click penanganan aktivitas ke tombol menggunakan sintaksis khusus bahasa:

    Button1.Click += Button_Click;
    
    AddHandler Button1.Click, AddressOf Button_Click
    

Untuk contoh cara melampirkan penanganan aktivitas dalam kode, lihat Cara menambahkan penanganan aktivitas menggunakan kode. Jika Anda mengodekan di Visual Basic, Anda juga dapat menggunakan Handles kata kunci untuk menambahkan handler sebagai bagian dari deklarasi handler. Untuk informasi selengkapnya, lihat Penanganan peristiwa Visual Basic dan WPF.

Konsep yang ditangani

Semua peristiwa yang dirutekan berbagi kelas dasar umum untuk data peristiwa, yang merupakan RoutedEventArgs kelas. Kelas RoutedEventArgs mendefinisikan properti boolean Handled . Tujuan properti Handled adalah untuk membiarkan penanganan aktivitas di sepanjang rute peristiwa untuk menandai peristiwa yang dirutekan sebagai ditangani. Untuk menandai peristiwa sebagai ditangani, atur nilai Handled ke true dalam kode penanganan aktivitas.

Nilai Handled memengaruhi bagaimana peristiwa yang dirutekan diproses saat berjalan di sepanjang rute peristiwa. Jika Handled berada true dalam data peristiwa bersama dari peristiwa yang dirutekan, maka handler yang dilampirkan ke elemen lain lebih lanjut di sepanjang rute peristiwa biasanya tidak akan dipanggil untuk instans peristiwa tertentu tersebut. Untuk skenario handler yang paling umum, menandai peristiwa sebagai ditangani secara efektif menghentikan handler berikutnya di sepanjang rute peristiwa, baik penangan instans atau kelas, dari merespons instans peristiwa tertentu. Namun, dalam kasus yang jarang terjadi di mana Anda memerlukan penanganan aktivitas untuk merespons peristiwa rute yang telah ditandai sebagai ditangani, Anda dapat:

Konsep Handled mungkin memengaruhi cara Anda merancang aplikasi dan mengodekan penanganan aktivitas Anda. Anda dapat mengkonsep sebagai Handled protokol sederhana untuk memproses peristiwa yang dirutekan. Cara Anda menggunakan protokol ini terserah Anda, tetapi penggunaan parameter yang Handled diharapkan adalah:

  • Jika peristiwa yang dirutekan ditandai sebagai ditangani, maka peristiwa tersebut tidak perlu ditangani lagi oleh elemen lain di sepanjang rute.

  • Jika peristiwa yang dirutekan tidak ditandai sebagai ditangani, maka pendengar sebelumnya di rute peristiwa tidak memiliki handler untuk peristiwa tersebut, atau tidak ada penangan terdaftar yang merespons peristiwa dengan cara yang menjurus pada penandaan peristiwa sebagai ditangani. Handler pada listener saat ini memiliki tiga kemungkinan tindakan:

    • Jangan ambil tindakan apa-apa. Peristiwa tetap tidak tertangani dan rute ke pendengar berikutnya di pohon.

    • Jalankan kode sebagai respons terhadap peristiwa, tetapi tidak sejauh yang menghalalkan menandai peristiwa sebagai ditangani. Peristiwa tetap tidak tertangani dan rute ke pendengar berikutnya di pohon.

    • Jalankan kode sebagai respons terhadap peristiwa, sejauh yang menghalalkan menandai peristiwa sebagai ditangani. Tandai peristiwa sebagai ditangani dalam data peristiwa. Acara masih merutekan ke pendengar berikutnya di pohon, tetapi sebagian besar pendengar tidak akan memanggil handler lebih lanjut. Pengecualiannya adalah listener dengan handler yang secara khusus terdaftar dengan handledEventsToo diatur ke true.

Untuk informasi selengkapnya tentang menangani peristiwa yang dirutekan, lihat Menandai peristiwa yang dirutekan sebagai ditangani, dan penanganan kelas.

Meskipun pengembang yang hanya menangani peristiwa bergelombang yang dirutekan pada objek yang memunculkannya mungkin tidak khawatir tentang pendengar lain, ada baiknya menandai peristiwa sebagai ditangani. Melakukannya mencegah efek samping yang tidak terduga jika elemen lebih jauh di sepanjang rute peristiwa memiliki handler untuk peristiwa yang dirutekan yang sama.

Penangan kelas

Penanganan aktivitas yang dirutekan dapat berupa handler instans atau handler kelas . Handler kelas untuk kelas tertentu dipanggil sebelum handler instans apa pun merespons peristiwa yang sama pada instans kelas tersebut. Karena perilaku ini, ketika peristiwa yang dirutekan ditandai sebagai ditangani, peristiwa tersebut sering ditandai seperti itu dalam penangan kelas. Ada dua jenis penangan kelas:

  • Penanganan aktivitas kelas statis, yang didaftarkan dengan memanggil RegisterClassHandler metode dalam konstruktor kelas statis.
  • Ambil alih penanganan aktivitas kelas, yang didaftarkan dengan mengambil alih metode peristiwa virtual kelas dasar. Metode peristiwa virtual kelas dasar terutama ada untuk peristiwa input, dan memiliki nama yang dimulai dengan Nama peristiwa On<dan nama>> peristiwa OnPreview.<

Beberapa kontrol WPF memiliki penanganan kelas yang melekat untuk peristiwa tertentu yang dirutekan. Penanganan kelas mungkin memberikan penampilan keluar bahwa peristiwa yang dirutekan tidak pernah dinaikkan, tetapi pada kenyataannya itu ditandai sebagai ditangani oleh penangan kelas. Jika Anda memerlukan penanganan aktivitas untuk merespons peristiwa yang ditangani, Anda dapat mendaftarkan handler Anda dengan handledEventsToo diatur ke true. Untuk informasi selengkapnya, baik tentang menerapkan penanganan kelas Anda sendiri atau mengatasi penanganan kelas yang tidak diinginkan, lihat Menandai peristiwa yang dirutekan sebagai ditangani, dan penanganan kelas.

Kejadian terlampir di WPF

Bahasa XAML juga mendefinisikan jenis peristiwa khusus yang disebut peristiwa terlampir. Peristiwa terlampir dapat digunakan untuk menentukan peristiwa rute baru di kelas non-elemen dan menaikkan peristiwa tersebut pada elemen apa pun di pohon Anda. Untuk melakukannya, Anda harus mendaftarkan peristiwa terlampir sebagai peristiwa yang dirutekan dan menyediakan kode pendukung tertentu yang mendukung fungsionalitas peristiwa terlampir. Karena peristiwa terlampir didaftarkan sebagai peristiwa yang dirutekan, ketika dinaikkan pada elemen yang mereka sebarkan melalui pohon elemen.

Dalam sintaks XAML, peristiwa terlampir ditentukan oleh nama peristiwa dan jenis pemiliknya, dalam bentuk <owner type>.<event name>. Karena nama peristiwa memenuhi syarat dengan nama jenis pemiliknya, sintaks memungkinkan peristiwa dilampirkan ke elemen apa pun yang dapat diinstansiasi. Sintaks ini juga berlaku untuk handler untuk peristiwa rute reguler yang melekat pada elemen arbitrer di sepanjang rute peristiwa. Anda juga dapat melampirkan handler untuk peristiwa terlampir dalam kode di belakang dengan memanggil AddHandler metode pada objek yang harus dilampirkan oleh handler.

Sistem input WPF menggunakan peristiwa terlampir secara ekstensif. Namun, hampir semua peristiwa terlampir tersebut muncul sebagai peristiwa rute yang tidak terpasang yang setara melalui elemen dasar. Anda jarang menggunakan atau menangani peristiwa terlampir secara langsung. Misalnya, lebih mudah untuk menangani peristiwa terlampir Mouse.MouseDown yang mendasar pada UIElement melalui peristiwa yang dirutekan yang setara UIElement.MouseDown daripada dengan menggunakan sintaks peristiwa terlampir di XAML atau code-behind.

Untuk informasi selengkapnya tentang peristiwa terlampir di WPF, lihat Gambaran umum peristiwa terlampir.

Nama peristiwa yang memenuhi syarat di XAML

Sintaks <owner type>.<event name> memenuhi syarat nama peristiwa dengan nama jenis pemiliknya. Sintaks ini memungkinkan peristiwa dilampirkan ke elemen apa pun, bukan hanya elemen yang mengimplementasikan peristiwa sebagai anggota kelas mereka. Sintaksis berlaku saat melampirkan handler di XAML untuk peristiwa terlampir atau peristiwa yang dirutekan pada elemen arbitrer di sepanjang rute peristiwa. Pertimbangkan skenario di mana Anda ingin melampirkan handler ke elemen induk untuk menangani peristiwa rute yang dinaikkan pada elemen turunan. Jika elemen induk tidak memiliki peristiwa yang dirutekan sebagai anggota, Anda harus menggunakan sintaks nama peristiwa yang memenuhi syarat. Contohnya:

<StackPanel Name="StackPanel1" Button.Click="Button_Click">
    <Button>Click me</Button>
</StackPanel>

Dalam contoh, pendengar elemen induk tempat penanganan aktivitas ditambahkan adalah StackPanel. Namun, peristiwa yang Click dirutekan diimplementasikan dan dinaikkan pada ButtonBase kelas, dan tersedia untuk Button kelas melalui warisan. Button Meskipun kelas "memiliki" Click peristiwa, sistem peristiwa yang dirutekan mengizinkan penangan untuk setiap peristiwa yang dirutekan untuk dilampirkan ke pendengar apa pun UIElement atau ContentElement instans yang dapat memiliki handler untuk peristiwa CLR. Namespace layanan default xmlns untuk nama atribut peristiwa yang memenuhi syarat ini biasanya merupakan namespace layanan WPF xmlns default, tetapi Anda juga dapat menentukan namespace awalan untuk peristiwa yang dirutekan kustom. Untuk informasi selengkapnya tentang xmlns, lihat namespace XAML dan pemetaan namespace layanan untuk WPF XAML.

Peristiwa input WPF

Salah satu aplikasi sering peristiwa yang dirutekan dalam platform WPF adalah untuk peristiwa input. Menurut konvensi, WPF merutekan peristiwa yang mengikuti rute penerowongan memiliki nama yang diawali dengan "Pratinjau". Prefiks Pratinjau menandakan bahwa peristiwa pratinjau selesai sebelum peristiwa gelembung yang dipasangkan dimulai. Peristiwa input sering datang berpasangan, dengan satu menjadi peristiwa pratinjau dan yang lain peristiwa rute yang menggelegak. Misalnya, PreviewKeyDown dan KeyDown. Pasangan peristiwa berbagi instans data peristiwa yang sama, yang untuk PreviewKeyDown dan KeyDown berjenis KeyEventArgs. Terkadang, peristiwa input hanya memiliki versi gelembung, atau hanya versi yang dirutekan langsung. Dalam dokumentasi API, topik peristiwa yang dirutekan merujuk silang pasangan peristiwa yang dirutekan dan mengklarifikasi strategi perutean untuk setiap peristiwa yang dirutekan.

Peristiwa input WPF yang datang berpasangan diimplementasikan sehingga satu tindakan pengguna dari perangkat input, seperti penekanan tombol mouse, akan meningkatkan pratinjau dan menggelegak peristiwa yang dirutekan secara berurutan. Pertama, peristiwa pratinjau dinaikkan dan menyelesaikan rutenya. Setelah menyelesaikan peristiwa pratinjau, peristiwa gelembung dinaikkan dan menyelesaikan rutenya. Panggilan RaiseEvent metode di kelas penerapan yang meningkatkan peristiwa gelembung menggunakan kembali data peristiwa dari peristiwa pratinjau untuk peristiwa gelembung.

Peristiwa input pratinjau yang ditandai sebagai ditangani tidak akan memanggil penanganan aktivitas yang biasanya terdaftar untuk sisa rute pratinjau, dan peristiwa gelembung yang dipasangkan tidak akan dinaikkan. Perilaku penanganan ini berguna untuk perancang kontrol komposit yang ingin peristiwa input berbasis hit-test atau peristiwa input berbasis fokus dilaporkan di tingkat atas kontrol mereka. Elemen tingkat atas kontrol memiliki kesempatan untuk menangani kelas peristiwa pratinjau dari subkomponen kontrol untuk "mengganti" mereka dengan peristiwa khusus kontrol tingkat atas.

Untuk mengilustrasikan cara kerja pemrosesan peristiwa input, pertimbangkan contoh peristiwa input berikut. Dalam ilustrasi pohon berikut, leaf element #2 adalah sumber dari PreviewMouseDown peristiwa yang dipasangkan dan MouseDown :

Event routing diagram.

Urutan pemrosesan peristiwa setelah tindakan mouse-down pada elemen daun #2 adalah:

  1. PreviewMouseDown peristiwa penerowongan pada elemen akar.
  2. PreviewMouseDown peristiwa penerowongan pada elemen perantara #1.
  3. PreviewMouseDown peristiwa penerowongan pada elemen daun #2, yang merupakan elemen sumber.
  4. MouseDown peristiwa gelembung pada elemen daun #2, yang merupakan elemen sumber.
  5. MouseDown peristiwa gelembung pada elemen perantara #1.
  6. MouseDown peristiwa gelembung pada elemen akar.

Delegasi penanganan aktivitas yang dirutekan menyediakan referensi ke objek yang menaikkan peristiwa dan objek tempat handler dipanggil. Objek yang awalnya menaikkan peristiwa dilaporkan oleh Source properti dalam data peristiwa. Objek tempat handler dipanggil dilaporkan oleh parameter pengirim . Untuk instans peristiwa yang dirutekan tertentu, objek yang menaikkan peristiwa tidak berubah saat peristiwa berjalan melalui pohon elemen, tetapi sender tidak. Dalam langkah 3 dan 4 dari diagram sebelumnya, Source dan sender merupakan objek yang sama.

Jika penanganan aktivitas input Anda menyelesaikan logika khusus aplikasi yang diperlukan untuk mengatasi peristiwa, Anda harus menandai peristiwa input sebagai ditangani. Biasanya, setelah peristiwa input ditandai Handled, handler lebih jauh di sepanjang rute peristiwa tidak dipanggil. Namun, handler peristiwa input yang terdaftar dengan handledEventsToo parameter yang diatur ke true akan dipanggil bahkan ketika peristiwa ditandai sebagai ditangani. Untuk informasi selengkapnya, lihat Mempratinjau peristiwa dan Menandai peristiwa yang dirutekan sebagai ditangani, dan penanganan kelas.

Konsep pratinjau dan pasangan peristiwa gelembung, dengan data peristiwa bersama dan peningkatan berurutan peristiwa pratinjau kemudian peristiwa gelembung, hanya berlaku untuk beberapa peristiwa input WPF dan tidak untuk semua peristiwa yang dirutekan. Jika Anda menerapkan peristiwa input Anda sendiri untuk mengatasi skenario lanjutan, pertimbangkan untuk mengikuti pendekatan pasangan peristiwa input WPF.

Jika Anda menerapkan kontrol komposit Anda sendiri yang merespons peristiwa input, pertimbangkan untuk menggunakan peristiwa pratinjau untuk menekan dan mengganti peristiwa input yang dinaikkan pada subkomponen dengan peristiwa tingkat atas yang mewakili kontrol lengkap. Untuk informasi selengkapnya, lihat Menandai peristiwa yang dirutekan sebagai ditangani, dan penanganan kelas.

Untuk informasi selengkapnya tentang sistem input WPF dan bagaimana input dan peristiwa berinteraksi dalam skenario aplikasi umum, lihat Gambaran umum input.

EventSetters dan EventTriggers

Dalam gaya markup, Anda dapat menyertakan sintaks penanganan peristiwa XAML yang telah dideklarasikan sebelumnya dengan menggunakan EventSetter. Saat XAML diproses, handler yang direferensikan ditambahkan ke instans bergaya. Anda hanya dapat mendeklarasikan EventSetter untuk peristiwa yang dirutekan. Dalam contoh berikut, metode penanganan aktivitas yang direferensikan ApplyButtonStyle diimplementasikan dalam kode di belakang.

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="{x:Type Button}">
            <EventSetter Event="Click" Handler="ApplyButtonStyle"/>
        </Style>
    </StackPanel.Resources>
    <Button>Click me</Button>
    <Button Click="Button_Click">Click me</Button>
</StackPanel>

Kemungkinan simpul Style sudah berisi informasi gaya lain yang berkaitan dengan kontrol jenis yang ditentukan, dan memiliki bagian dari gaya tersebut EventSetter mempromosikan penggunaan kembali kode bahkan pada tingkat markup. Selain itu, EventSetter abstrak nama metode untuk handler menjauh dari aplikasi umum dan markup halaman.

Sintaksis khusus lainnya yang menggabungkan fitur peristiwa dan animasi WPF yang dirutekan adalah EventTrigger. Seperti halnya EventSetter, Anda hanya dapat mendeklarasikan EventTrigger untuk peristiwa yang dirutekan. Biasanya, EventTrigger dideklarasikan sebagai bagian dari gaya, tetapi EventTrigger dapat dideklarasikan pada elemen tingkat halaman sebagai bagian Triggers dari koleksi, atau dalam ControlTemplate. Memungkinkan EventTrigger Anda menentukan Storyboard yang berjalan setiap kali peristiwa yang dirutekan mencapai elemen dalam rutenya yang mendeklarasikan EventTrigger untuk peristiwa tersebut. Keuntungan dari EventTrigger lebih hanya menangani peristiwa dan menyebabkannya memulai papan cerita yang ada adalah bahwa memberikan kontrol yang EventTrigger lebih baik atas papan cerita dan perilaku run-time-nya. Untuk informasi selengkapnya, lihat Menggunakan pemicu peristiwa untuk mengontrol papan cerita setelah dimulai.

Selengkapnya tentang peristiwa yang dirutekan

Anda dapat menggunakan konsep dan panduan dalam artikel ini sebagai titik awal saat membuat peristiwa rute kustom di kelas Anda sendiri. Anda juga dapat mendukung peristiwa kustom Anda dengan kelas dan delegasi data peristiwa khusus. Pemilik peristiwa yang dirutekan dapat menjadi kelas apa pun, tetapi peristiwa yang dirutekan harus dinaikkan oleh dan ditangani oleh UIElement atau ContentElement turunan kelas agar berguna. Untuk informasi selengkapnya tentang peristiwa kustom, lihat Membuat peristiwa rute kustom.

Baca juga