Freigeben über


Ereignisse (F#)

Mit Ereignissen ordnen Sie Benutzeraktionen Funktionsaufrufe zu. Sie sind wichtig in der GUI-Programmierung. Ereignisse können auch von den Anwendungen oder dem Betriebssystem ausgelöst werden.

Behandeln von Ereignissen

Wenn Sie eine GUI-Bibliothek, z. B. Windows Forms oder Windows Presentation Foundation (WPF), verwenden, wird ein großer Anteil des Codes in der Anwendung aufgrund von Ereignissen ausgeführt, die durch die Bibliothek vordefiniert sind. Diese vordefinierten Ereignisse sind Member von GUI-Klassen, z. B. Forms und Control. Sie können einem bereits vorhandenen Ereignis benutzerdefiniertes Verhalten, z. B. das Klicken auf eine Schaltfläche, hinzufügen, indem Sie auf das entsprechende Ereignis (z. B. das Click-Ereignis der Form-Klasse) verweisen und die Add-Methode aufrufen, wie im folgenden Code gezeigt. Lassen Sie bei der Ausführung in F# Interactive den Aufruf von Run weg.

open System.Windows.Forms

let form = new Form(Text="F# Windows Form",
                    Visible = true,
                    TopMost = true)

form.Click.Add(fun evArgs -> System.Console.Beep())
Application.Run(form)

Der Typ der Add-Methode ist ('a -> unit) -> unit. Daher akzeptiert die Ereignishandlermethode einen Parameter, in der Regel die Ereignisargumente, und gibt unit zurück. Im vorherigen Beispiel ist der Ereignishandler ein Lambda-Ausdruck. Der Ereignishandler kann auch ein Funktionswert sein, wie im folgenden Codebeispiel. Im folgenden Codebeispiel wird auch die Verwendung der Ereignishandlerparameter veranschaulicht, die spezifische Informationen für den Typ des Ereignisses bereitstellen. Für ein MouseMove-Ereignis übergibt das System ein MouseEventArgs-Objekt, das die X- und Y-Position des Zeigers enthält.

open System.Windows.Forms

let Beep evArgs =
    System.Console.Beep( )  


let form = new Form(Text = "F# Windows Form",
                    Visible = true,
                    TopMost = true)

let MouseMoveEventHandler (evArgs : System.Windows.Forms.MouseEventArgs) =
    form.Text <- System.String.Format("{0},{1}", evArgs.X, evArgs.Y)

form.Click.Add(Beep)
form.MouseMove.Add(MouseMoveEventHandler)
Application.Run(form)

Erstellen von benutzerdefinierten Ereignissen

F#-Ereignisse werden durch die F# Event-Klasse dargestellt, die die IEvent-Schnittstelle implementiert. IEvent ist eine Schnittstelle, die die Funktionalität zweier anderer Schnittstellen, IObservable<T> und IDelegateEvent, kombiniert. Daher verfügen Events über die gleiche Funktionalität wie Delegaten in anderen Sprachen und zusätzlich über die Funktionen von IObservable. F#-Ereignisse unterstützen somit die Ereignisfilterung und das Verwenden von F#-Funktionen der ersten Klasse und von Lambda-Ausdrücken als Ereignishandler. Diese Funktionalität wird im Event-Modul bereitgestellt.

Zum Erstellen eines Ereignisses für eine Klasse, das sich wie ein beliebiges anderes .NET Framework-Ereignis verhält, fügen Sie der Klasse eine let-Bindung hinzu, die ein Event als Feld in einer Klasse definiert. Sie können den gewünschten Ereignisargumenttyp als Typargument angeben oder den Wert freilassen und einen geeigneten Wert durch den Compiler bestimmen lassen. Sie müssen außerdem einen Ereignismember definieren, der das Ereignis als CLI-Ereignis verfügbar macht. Dieser Member sollte über das CLIEvent-Attribut verfügen. Er wird ähnlich wie eine Eigenschaft deklariert, und seine Implementierung ist nur ein Aufruf der Eigenschaft zum Veröffentlichen des Ereignisses. Benutzer der Klasse können die Add-Methode des veröffentlichten Ereignisses verwenden, um einen Handler hinzuzufügen. Das Argument für die Add-Methode kann ein Lambda-Ausdruck sein. Sie können die Trigger-Eigenschaft des Ereignisses verwenden, um das Ereignis auszulösen und das Argument an die Handlerfunktion zu übergeben. Dies wird im folgenden Codebeispiel veranschaulicht. In diesem Beispiel ist das abgeleitete Typargument für das Ereignis ein Tupel, das die Argumente für den Lambda-Ausdruck darstellt.

open System.Collections.Generic

type MyClassWithCLIEvent() =

    let event1 = new Event<_>()

    [<CLIEvent>]
    member this.Event1 = event1.Publish

    member this.TestEvent(arg) =
        event1.Trigger(this, arg)

let classWithEvent = new MyClassWithCLIEvent()
classWithEvent.Event1.Add(fun (sender, arg) -> 
        printfn "Event1 occurred! Object data: %s" arg)

classWithEvent.TestEvent("Hello World!")

System.Console.ReadLine() |> ignore

Die Ausgabe lautet wie folgt.

Event1 occurred! Object data: Hello World!

Die zusätzliche vom Event-Modul bereitgestellte Funktionalität wird hier veranschaulicht. Im folgenden Codebeispiel wird die grundlegende Verwendung von Event.create zur Erstellung eines Ereignisses und einer Triggermethode, zum Hinzufügen zweier Ereignishandler in der Form von Lambda-Ausdrücken und dem Auslösen des Ereignisses zur Ausführung beider Lambda-Ausdrücke dargestellt.

type MyType() =
    let myEvent = new Event<_>()

    member this.AddHandlers() =
       Event.add (fun string1 -> printfn "%s" string1) myEvent.Publish
       Event.add (fun string1 -> printfn "Given a value: %s" string1) myEvent.Publish

    member this.Trigger(message) =
       myEvent.Trigger(message)

let myMyType = MyType()
myMyType.AddHandlers()
myMyType.Trigger("Event occurred.")

Der obige Code gibt Folgendes aus.

Event occurred.
Given a value: Event occurred.

Verarbeiten von Ereignisstreams

Statt einfach mit der Event.add-Funktion einen Ereignishandler für ein Ereignis hinzuzufügen, können Sie die Funktionen im Event-Modul verwenden, um Ereignisstreams hochgradig benutzerdefiniert zu verarbeiten. Hierzu verwenden Sie den Vorwärtspipeoperator (|>) zusammen mit dem Ereignis als ersten Wert in einer Reihe von Funktionsaufrufen und die Event-Modulfunktionen als nachfolgende Funktionsaufrufe.

Im folgenden Codebeispiel wird die Einrichtung eines Ereignisses gezeigt, für das der Handler nur unter bestimmten Bedingungen aufgerufen wird.

let form = new Form(Text = "F# Windows Form",
                    Visible = true,
                    TopMost = true)
form.MouseMove
    |> Event.filter ( fun evArgs -> evArgs.X > 100 && evArgs.Y > 100)
    |> Event.add ( fun evArgs ->
        form.BackColor <- System.Drawing.Color.FromArgb(
            evArgs.X, evArgs.Y, evArgs.X ^^^ evArgs.Y) )

Das Observable-Modul enthält ähnliche Funktionen, die auf Observable-Objekte wirken. Observable-Objekte sind Ereignissen ähnlich, abonnieren Ereignisse aber nur, wenn sie selbst abonniert werden.

Siehe auch

Referenz

Lambda-Ausdrücke: Das fun-Schlüsselwort (F#)

Konzepte

Member (F#)

Ereignisse und Delegaten

Weitere Ressourcen

Control.Event-Modul (F#)

Control.Event<'T>-Klasse (F#)

Control.Event<'Delegate,'Args>-Klasse (F#)

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Januar 2011

Die Verwendung von Event anstelle von DelegateEvent hervorgehoben.

Informationsergänzung.