Bagikan melalui


Cara membuat peristiwa rute kustom (WPF .NET)

Pengembang aplikasi dan penulis komponen Windows Presentation Foundation (WPF) dapat membuat peristiwa rute kustom untuk memperluas fungsionalitas peristiwa runtime bahasa umum (CLR). Untuk informasi tentang kemampuan peristiwa yang dirutekan, lihat Mengapa menggunakan peristiwa yang dirutekan. Artikel ini membahas dasar-dasar pembuatan peristiwa yang dirutekan kustom.

Prasyarat

Artikel ini mengasumsikan pengetahuan dasar tentang peristiwa yang dirutekan, dan anda telah membaca ringkasan peristiwa yang dirutekan. Untuk mengikuti contoh dalam artikel ini, ini membantu jika Anda terbiasa dengan Extensible Application Markup Language (XAML) dan tahu cara menulis aplikasi Windows Presentation Foundation (WPF).

Langkah-langkah peristiwa yang dirutekan

Langkah-langkah dasar untuk membuat peristiwa yang dirutekan adalah:

  1. RoutedEvent Daftarkan menggunakan metode .RegisterRoutedEvent

  2. Panggilan pendaftaran mengembalikan instans RoutedEvent , yang dikenal sebagai pengidentifikasi peristiwa yang dirutekan, yang menyimpan nama peristiwa terdaftar, strategi perutean, dan detail peristiwa lainnya. Tetapkan pengidentifikasi ke bidang readonly statis. Menurut konvensi:

    • Pengidentifikasi untuk peristiwa yang dirutekan dengan strategi gelembung diberi nama <event name>Event. Misalnya, jika nama peristiwa adalah Tap pengidentifikasi harus diberi nama TapEvent.
    • Pengidentifikasi untuk peristiwa yang dirutekan dengan strategi penerowongan diberi nama Preview<event name>Event. Misalnya, jika nama peristiwa adalah Tap pengidentifikasi harus diberi nama PreviewTapEvent.
  3. Tentukan CLR tambahkan dan hapus aksesor peristiwa. Tanpa aksesor peristiwa CLR, Anda hanya dapat menambahkan atau menghapus penanganan aktivitas melalui panggilan langsung ke UIElement.AddHandler metode dan UIElement.RemoveHandler . Dengan aksesor peristiwa CLR, Anda mendapatkan mekanisme penugasan penanganan aktivitas ini:

    • Untuk Extensible Application Markup Language (XAML), Anda dapat menggunakan sintaks atribut untuk menambahkan penanganan aktivitas.
    • Untuk C#, Anda dapat menggunakan += operator dan -= untuk menambahkan atau menghapus penanganan aktivitas.
    • Untuk VB, Anda dapat menggunakan pernyataan AddHandler dan RemoveHandler untuk menambahkan atau menghapus penanganan aktivitas.
  4. Tambahkan logika kustom untuk memicu peristiwa yang dirutekan. Misalnya, logika Anda mungkin memicu peristiwa berdasarkan input pengguna dan status aplikasi.

Contoh

Contoh berikut mengimplementasikan CustomButton kelas dalam pustaka kontrol kustom. Kelas CustomButton , yang berasal dari Button:

  1. Mendaftarkan bernama RoutedEvent ConditionalClick menggunakan RegisterRoutedEvent metode , dan menentukan strategi gelembung selama pendaftaran.
  2. Menetapkan instans yang RoutedEvent dikembalikan dari panggilan pendaftaran ke bidang readonly statis bernama ConditionalClickEvent.
  3. Mendefinisikan CLR menambahkan dan menghapus aksesor peristiwa.
  4. Menambahkan logika kustom untuk menaikkan peristiwa rute kustom saat CustomButton diklik dan kondisi eksternal berlaku. Meskipun kode contoh meningkatkan peristiwa yang dirutekan ConditionalClick dari dalam metode virtual yang ditimpa OnClick , Anda dapat menaikkan peristiwa anda dengan cara apa pun yang Anda pilih.
public class CustomButton : Button
{
    // Register a custom routed event using the Bubble routing strategy.
    public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
        name: "ConditionalClick",
        routingStrategy: RoutingStrategy.Bubble,
        handlerType: typeof(RoutedEventHandler),
        ownerType: typeof(CustomButton));

    // Provide CLR accessors for assigning an event handler.
    public event RoutedEventHandler ConditionalClick
    {
        add { AddHandler(ConditionalClickEvent, value); }
        remove { RemoveHandler(ConditionalClickEvent, value); }
    }

    void RaiseCustomRoutedEvent()
    {
        // Create a RoutedEventArgs instance.
        RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);

        // Raise the event, which will bubble up through the element tree.
        RaiseEvent(routedEventArgs);
    }

    // For demo purposes, we use the Click event as a trigger.
    protected override void OnClick()
    {
        // Some condition combined with the Click event will trigger the ConditionalClick event.
        if (DateTime.Now > new DateTime())
            RaiseCustomRoutedEvent();

        // Call the base class OnClick() method so Click event subscribers are notified.
        base.OnClick();
    }
}
Public Class CustomButton
    Inherits Button

    ' Register a custom routed event with the Bubble routing strategy.
    Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
        name:="ConditionalClick",
        routingStrategy:=RoutingStrategy.Bubble,
        handlerType:=GetType(RoutedEventHandler),
        ownerType:=GetType(CustomButton))

    ' Provide CLR accessors to support event handler assignment.
    Public Custom Event ConditionalClick As RoutedEventHandler

        AddHandler(value As RoutedEventHandler)
            [AddHandler](ConditionalClickEvent, value)
        End AddHandler

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

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

    End Event

    Private Sub RaiseCustomRoutedEvent()

        ' Create a RoutedEventArgs instance.
        Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent)

        ' Raise the event, which will bubble up through the element tree.
        [RaiseEvent](routedEventArgs)

    End Sub

    ' For demo purposes, we use the Click event as a trigger.
    Protected Overrides Sub OnClick()

        ' Some condition combined with the Click event will trigger the ConditionalClick event.
        If Date.Now > New DateTime() Then RaiseCustomRoutedEvent()

        ' Call the base class OnClick() method so Click event subscribers are notified.
        MyBase.OnClick()

    End Sub
End Class

Contohnya mencakup aplikasi WPF terpisah yang menggunakan markup XAML untuk menambahkan instans CustomButton ke StackPanel, dan untuk menetapkan Handler_ConditionalClick metode sebagai ConditionalClick penanganan aktivitas untuk CustomButton elemen dan StackPanel1 .

<Window x:Class="CodeSample.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
        Title="How to create a custom routed event" Height="100" Width="300">

    <StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
        <custom:CustomButton
            Name="customButton"
            ConditionalClick="Handler_ConditionalClick"
            Content="Click to trigger a custom routed event"
            Background="LightGray">
        </custom:CustomButton>
    </StackPanel>
</Window>

Di code-behind, aplikasi WPF mendefinisikan Handler_ConditionalClick metode penanganan aktivitas. Metode penanganan aktivitas hanya dapat diimplementasikan dalam code-behind.

// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
    string senderName = ((FrameworkElement)sender).Name;
    string sourceName = ((FrameworkElement)e.Source).Name;

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the ConditionalClick routed event raised on {sourceName}.");
}

// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
//     triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
//     triggered by the ConditionalClick routed event raised on CustomButton.
' The ConditionalClick event handler.
Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs)

    Dim sourceName As String = CType(e.Source, FrameworkElement).Name
    Dim senderName As String = CType(sender, FrameworkElement).Name

    Debug.WriteLine($"Routed event handler attached to {senderName}, " +
        $"triggered by the ConditionalClick routed event raised on {sourceName}.")

End Sub

' Debug output when CustomButton is clicked:
' Routed event handler attached to CustomButton,
'     triggered by the ConditionalClick routed event raised on CustomButton.
' Routed event handler attached to StackPanel1,
'     triggered by the ConditionalClick routed event raised on CustomButton.

Ketika CustomButton diklik:

  1. Peristiwa ConditionalClick yang dirutekan dinaikkan pada CustomButton.
  2. Penanganan Handler_ConditionalClick aktivitas yang terpasang CustomButton dipicu.
  3. Peristiwa ConditionalClick yang dirutekan melintasi pohon elemen ke StackPanel1.
  4. Penanganan Handler_ConditionalClick aktivitas yang terpasang StackPanel1 dipicu.
  5. Peristiwa ConditionalClick yang dirutekan berlanjut ke pohon elemen yang berpotensi memicu penanganan aktivitas lain ConditionalClick yang melekat pada elemen lain yang dilalui.

Penanganan Handler_ConditionalClick aktivitas mendapatkan informasi berikut tentang peristiwa yang memicunya:

  • Objek pengirim , yang merupakan elemen tempat penanganan aktivitas dilampirkan. Akan sender menjadi CustomButton pertama kalinya handler berjalan, dan StackPanel1 yang kedua kalinya.
  • Objek RoutedEventArgs.Source , yang merupakan elemen yang awalnya menaikkan peristiwa. Dalam contoh ini, Source selalu CustomButton.

Catatan

Perbedaan utama antara peristiwa yang dirutekan dan peristiwa CLR adalah bahwa peristiwa yang dirutekan melintasi pohon elemen, mencari handler, sedangkan peristiwa CLR tidak melintasi pohon elemen dan handler hanya dapat melekat pada objek sumber yang menaikkan peristiwa. Akibatnya, peristiwa sender yang dirutekan dapat menjadi elemen yang dilalui di pohon elemen.

Anda dapat membuat peristiwa penerowongan dengan cara yang sama seperti peristiwa gelembung, kecuali Anda akan mengatur strategi perutean dalam panggilan pendaftaran peristiwa ke Tunnel. Untuk informasi selengkapnya tentang peristiwa penerowongan, lihat Peristiwa input WPF.

Lihat juga