Ekli olaylara genel bakış (WPF .NET)

Genişletilebilir Uygulama biçimlendirme dili (XAML), ekli olay olarak adlandırılan bir dil bileşenini ve olay türünü tanımlar. Ekli olaylar, öğe olmayan bir sınıfta yeni bir yönlendirilmiş olay tanımlamak ve bu olayı ağacınızdaki herhangi bir öğeye yükseltmek için kullanılabilir. Bunu yapmak için, ekli olayı yönlendirilmiş olay olarak kaydetmeniz ve ekli olay işlevselliğini destekleyen belirli bir yedekleme kodu sağlamanız gerekir. Ekli olaylar yönlendirilmiş olaylar olarak kaydedildiğinden, bir öğeye yükseltildiğinde öğe ağacına yayılırlar.

Önemli

.NET 7 ve .NET 6 için Masaüstü Kılavuzu belgeleri yapım aşamasındadır.

Ön koşullar

Makale, Windows Presentation Foundation (WPF) tarafından yönlendirilen olaylar hakkında temel bilgiler edindiğini ve WPF'de Yönlendirilen olaylara genel bakış ve XAML okuduğunuz varsayılır. Bu makaledeki örnekleri takip etmek için XAML hakkında bilgi sahibi olmanız ve WPF uygulamalarının nasıl yazabileceğinizi bilmeniz yardımcı olur.

Ekli olay söz dizimi

XAML söz diziminde, ekli bir olay, olay adı ve sahip türü ile biçiminde <owner type>.<event name>belirtilir. Olay adı, sahip türünün adıyla nitelendiğinden, söz dizimi olayın örneklenebilen herhangi bir öğeye eklenmesini sağlar. Bu söz dizimi, olay yolu boyunca rastgele bir öğeye iliştirilen normal yönlendirilmiş olaylar için işleyiciler için de geçerlidir.

Aşağıdaki XAML özniteliği söz dizimi, ekli olayın işleyicisini AquariumFilter.Cleanaquarium1 öğesine eklerAquariumFilter_Clean:

<aqua:Aquarium x:Name="aquarium1" Height="300" Width="400" aqua:AquariumFilter.Clean="AquariumFilter_Clean"/>

Bu örnekte ve aqua: sınıfları farklı bir ortak dil çalışma zamanı (CLR) ad alanı ve derlemesinde bulunduğundan AquariumFilterAquarium ön ek gereklidir.

Ayrıca arka planda koda eklenen olaylar için işleyiciler ekleyebilirsiniz. Bunu yapmak için işleyicinin AddHandler eklemesi gereken nesnede yöntemini çağırın ve olay tanımlayıcısını ve işleyicisini yöntemine parametre olarak geçirin.

WPF ekli olayları nasıl uygular?

WPF ekli olayları, bir RoutedEvent alan tarafından yedeklenen yönlendirilmiş olaylar olarak uygulanır. Sonuç olarak, eklenen olaylar yükseltildikten sonra öğe ağacına yayılır. Genellikle, olay kaynağı olarak bilinen ekli olayı yükselten nesne bir sistem veya hizmet kaynağıdır. Sistem veya hizmet kaynakları, öğe ağacının doğrudan bir parçası değildir. Diğer ekli olaylar için olay kaynağı, bileşik denetim içindeki bir bileşen gibi ağaçtaki bir öğe olabilir.

Ekli olay senaryoları

WPF'de ekli olaylar, hizmet düzeyi soyutlamanın bulunduğu belirli özellik alanlarında kullanılır. Örneğin WPF, statik Mouse veya Validation sınıflar tarafından etkinleştirilen ekli olayların kullanımlarını yapar. Bir hizmetle etkileşim kuran veya hizmet kullanan sınıflar, ekli olay söz dizimini kullanarak bir olayla etkileşimde bulunabilir veya ekli olayı yönlendirilmiş olay olarak ortaya çıkarabilirsiniz. İkinci seçenek, bir sınıfın hizmetin özelliklerini nasıl tümleştirebileceğinin bir parçasıdır.

WPF giriş sistemi, ekli olayları kapsamlı olarak kullanır. Ancak, bu ekli olayların neredeyse tümü, temel öğeler aracılığıyla eşdeğer ekli olmayan yönlendirilmiş olaylar olarak ortaya çıkar. Yönlendirilen her giriş olayı, temel öğe sınıfının bir üyesidir ve clr olayı "sarmalayıcı" ile yedeklenmiştir. Ekli olayları nadiren doğrudan kullanır veya işlersiniz. Örneğin, XAML'de ekli Mouse.MouseDown olay UIElement söz dizimi veya arka planda kod kullanarak eşdeğer UIElement.MouseDown yönlendirilmiş olay aracılığıyla temel alınan ekli olayı işlemek daha kolaydır.

Ekli olaylar, giriş cihazlarının gelecekte genişletilmesini sağlayarak bir mimari amacına hizmet eder. Örneğin, yeni bir giriş cihazının yalnızca fare girişinin benzetimini yapmak için yükseltmesi Mouse.MouseDown gerekir ve bunu yapmak için öğesinden Mouse türetilmesi gerekmez. Bu senaryo, ekli olayın XAML işlemesi uygun olmayacağından olayın kod işlemesini içerir.

Ekli olayı işleme

Ekli olayı kodlama ve işleme işlemi temel olarak ekli olmayan yönlendirilmiş bir olayla aynıdır.

Daha önce belirtildiği gibi, mevcut WPF ekli olayları genellikle WPF'de doğrudan işlenmek üzere tasarlanmamıştır. Daha sık olarak, ekli bir olayın amacı bileşik denetim içindeki bir öğenin durumunu denetim içindeki bir üst öğeye raporlamasını sağlamaktır. Bu senaryoda, olay kodda oluşturulur ve ilgili üst sınıfta sınıf işlemeye dayanır. Örneğin, içindeki Selector öğelerin ekli olayı oluşturması Selected beklenir ve bu da sınıfı tarafından Selector işlenen sınıftır. sınıfı, Selector olayı yönlendirilmiş olaya SelectionChanged dönüştürebilirSelected. Yönlendirilen olaylar ve sınıf işleme hakkında daha fazla bilgi için bkz . Yönlendirilen olayları işlenmiş olarak işaretleme ve sınıf işleme.

Özel bir ekli olay tanımlama

Ortak WPF temel sınıflarından türetiyorsanız sınıfınıza iki erişimci yöntemi ekleyerek özel ekli olayınızı uygulayabilirsiniz. Bu yöntemler şunlardır:

  • Olay işleyicisinin eklendiği öğe olan ilk parametreye ve eklenecek olay işleyicisine sahip ikinci parametreye sahip bir Olay adı> İşleyicisi ekle<yöntemi. yöntemi, dönüş değeri olmayan ve staticolmalıdırpublic. yöntemi, yönlendirilen olayı ve işleyiciyi bağımsız değişken olarak geçirerek temel sınıf yöntemini çağırır AddHandler . Bu yöntem, bir öğeye olay işleyicisi eklemek için XAML özniteliği söz dizimini destekler. Bu yöntem ayrıca ekli olay için olay işleyici deposuna kod erişimi sağlar.

  • Olay işleyicisinin eklendiği öğe olan ilk parametreye ve kaldırılacak olay işleyicisine sahip ikinci bir parametreye sahip olay adı>İşleyicisi'ni kaldırma<yöntemi. yöntemi, dönüş değeri olmayan ve staticolmalıdırpublic. yöntemi, yönlendirilen olayı ve işleyiciyi bağımsız değişken olarak geçirerek temel sınıf yöntemini çağırır RemoveHandler . Bu yöntem, ekli olay için olay işleyici deposuna kod erişimini etkinleştirir.

wpf tanımlayıcısı RoutedEvent WPF olay sistemi tarafından tanımlandığından, WPF ekli olayları yönlendirilmiş olaylar olarak uygular. Ayrıca, bir olayı yönlendirme, ekli bir olayın XAML dil düzeyi kavramının doğal bir uzantısıdır. Bu uygulama stratejisi, ekli olayların işlenmesini UIElement türetilmiş sınıflarla veya ContentElement türetilmiş sınıflarla kısıtlar çünkü yalnızca bu sınıfların uygulamaları vardır AddHandler .

Örneğin, aşağıdaki kod sahip sınıfında ekli olayı AquariumFilter tanımlar Clean ve bu bir öğe sınıfı değildir. Kod, ekli olayı yönlendirilmiş bir olay olarak tanımlar ve gerekli erişimci yöntemlerini uygular.

public class AquariumFilter
{
    // Register a custom routed event using the bubble routing strategy.
    public static readonly RoutedEvent CleanEvent = EventManager.RegisterRoutedEvent(
        "Clean", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));

    // Provide an add handler accessor method for the Clean event.
    public static void AddCleanHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
    {
        if (dependencyObject is not UIElement uiElement)
            return;

        uiElement.AddHandler(CleanEvent, handler);
    }

    // Provide a remove handler accessor method for the Clean event.
    public static void RemoveCleanHandler(DependencyObject dependencyObject, RoutedEventHandler handler)
    {
        if (dependencyObject is not UIElement uiElement)
            return;

        uiElement.RemoveHandler(CleanEvent, handler);
    }
}
Public Class AquariumFilter

    ' Register a custom routed event using the bubble routing strategy.
    Public Shared ReadOnly CleanEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
        "Clean", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))

    ' Provide an add handler accessor method for the Clean event.
    Public Shared Sub AddCleanHandler(dependencyObject As DependencyObject, handler As RoutedEventHandler)
        Dim uiElement As UIElement = TryCast(dependencyObject, UIElement)

        If uiElement IsNot Nothing Then
            uiElement.[AddHandler](CleanEvent, handler)
        End If
    End Sub

    ' Provide a remove handler accessor method for the Clean event.
    Public Shared Sub RemoveCleanHandler(dependencyObject As DependencyObject, handler As RoutedEventHandler)
        Dim uiElement As UIElement = TryCast(dependencyObject, UIElement)

        If uiElement IsNot Nothing Then
            uiElement.[RemoveHandler](CleanEvent, handler)
        End If
    End Sub

End Class

Ekli RegisterRoutedEvent olay tanımlayıcısını döndüren yöntem, ekli olmayan yönlendirilmiş olayları kaydetmek için kullanılan yöntemle aynıdır. Hem ekli hem de bağlı olmayan yönlendirilmiş olaylar merkezi bir iç depoya kaydedilir. Bu olay deposu uygulaması, Yönlendirilen olaylara genel bakış bölümünde açıklanan "arabirim olarak olaylar" kavramını etkinleştirir.

Bağlı olmayan yönlendirilmiş olayları yedeklemek için kullanılan CLR olayının "sarmalayıcısından" farklı olarak, ekli olay erişimci yöntemleri veya ContentElementöğesinden UIElement türetilmeyen sınıflarda uygulanabilir. Ekli olay yedekleme kodu geçirilen UIElement bir örnekte ve UIElement.RemoveHandler yöntemlerini çağırdığı UIElement.AddHandler için bu mümkündür. Buna karşılık, bağlı olmayan yönlendirilmiş olaylar için CLR sarmalayıcısı bu yöntemleri doğrudan kendi sınıfında çağırır, böylece sınıfın öğesinden UIElementtüretilmesi gerekir.

WPF ekli olayı oluşturma

Ekli olay oluşturma işlemi temelde ekli olmayan yönlendirilmiş bir olayla aynıdır.

Normalde, bu olaylar genel "hizmet" kavramsal modelini izlediğinden kodunuzun mevcut WPF tanımlı ekli olayları oluşturması gerekmez. Bu modelde, gibi InputManagerhizmet sınıfları WPF tanımlı ekli olayları oluşturmakla sorumludur.

Yönlendirilen olaylara ekli olayları temel alan WPF modelini kullanarak özel bir ekli olay tanımlarken, herhangi UIElement bir veya ContentElementüzerinde ekli olay oluşturmak için yöntemini kullanınUIElement.RaiseEvent. Bağlı olsun veya olmasın yönlendirilmiş bir olayı oluştururken, öğe ağacınızdaki bir öğeyi olay kaynağı olarak atamanız gerekir. Bu kaynak daha sonra çağıran RaiseEvent olarak bildirilir. Örneğin, ekli yönlendirilmiş olayı üzerinde aquarium1yükseltmek AquariumFilter.Clean için:

aquarium1.RaiseEvent(new RoutedEventArgs(AquariumFilter.CleanEvent));
aquarium1.[RaiseEvent](New RoutedEventArgs(AquariumFilter.CleanEvent))

Yukarıdaki örnekte olay aquarium1 kaynağı verilmiştir.

Ayrıca bkz.