Zdarzenia (F#)
Zdarzenia umożliwiają kojarzenie wywołania funkcji z akcji użytkownika i są ważne w programowaniu GUI.Zdarzenia mogą też być wyzwalane przez aplikacje lub system operacyjny.
Obsługa zdarzeń
Gdy używasz biblioteki graficznego interfejsu użytkownika, takie jak Windows Forms lub systemu Windows Presentation Foundation (WPF), dużo kodu w aplikacji działa w odpowiedzi na zdarzenia, które są wstępnie zdefiniowane przez bibliotekę.Zdarzenia te wstępnie zdefiniowane są członkowie klasy GUI, takich jak formularze i formanty.Niestandardowe zachowania istniejące zdarzenia, można dodać takie jak kliknięcia przycisku, odwołując się do szczególnych o nazwie zdarzenia odsetek (na przykład, Click zdarzenia Form klasa) i wywoływanie Add metody, jak pokazano w poniższym kodzie.Jeśli to można uruchomić z F# interaktywne, pominąć wywołanie Run.
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)
Typ Add jest metoda ('a -> unit) -> unit.Dlatego metody obsługi zdarzenia przyjmuje jeden parametr, zazwyczaj argumenty zdarzeń i zwraca unit.W poprzednim przykładzie przedstawiono program obsługi zdarzeń jako wyrażenie lambda.Obsługa zdarzeń można także wartość funkcji, jak w poniższym przykładzie kodu.Poniższy przykład kodu Ponadto przedstawia ono zastosowanie zdarzenia handler parametry, które dostarczają informacje specyficzne dla typu zdarzenia.Dla MouseMove zdarzenie, system przechodzi MouseEventArgs obiekt, który zawiera X i Y położenia kursora.
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)
Tworzenie zdarzeń niestandardowych
F# zdarzeń są reprezentowane przez F# zdarzenia klasy, który implementuje IEvent interfejsu.IEventsam jest interfejsem, który łączy funkcje dwa inne interfejsy, IObservable<T> i IDelegateEvent.W związku z tym Events mają równoważne funkcje delegatów w innych językach, plus dodatkowe funkcje z IObservable, co oznacza, że zdarzenia F# obsługuje filtrowanie zdarzeń i za pomocą funkcji Pierwszorzędna F# i wyrażenia lambda jako programy obsługi zdarzeń.Ta funkcjonalność jest udostępniana w moduł zdarzenia.
Aby utworzyć zdarzenie na klasie, która działa tak jak wszelkie inne.NET Framework zdarzenia, dodać do klasy let powiązania, który definiuje Event jako pole w klasie.Można określić typ argumentu żądane zdarzenie jako argument typu lub pozostaw puste i mają kompilator wywnioskować odpowiedniego typu.Należy zdefiniować również Członkowskie zdarzenia, udostępniający zdarzeń jako zdarzenia CLI.Członek ten powinien mieć CLIEvent atrybut.Jest on zadeklarowany jako takie właściwości, jak i jego implementacja jest po prostu wywołanie do Publikuj właściwości zdarzenia.Można użyć użytkownikom klasy Add metoda opublikowanych zdarzeń, aby dodać program obsługi.Argument dla Add metoda może być wyrażenie lambda.Można użyć Trigger właściwość zdarzenia, aby podnieść przekazywania argumenty do funkcji obsługi zdarzeń.Poniższy przykład kodu ilustruje to.W tym przykładzie nie powiązano typ argumentu dla zdarzenia jest również krotką reprezentuje argumenty dla wyrażenia lambda.
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
Wprowadza dane wyjściowe.
Event1 occurred! Object data: Hello World!
Dodatkowe funkcje udostępniane przez Event moduł jest to tutaj zilustrowane.Poniższy przykład kodu ilustruje wykorzystanie podstawowych Event.create utworzyć zdarzenia i metody wyzwalacz, dodać dwa programy obsługi zdarzeń w formie wyrażenia lambda, a następnie wyzwolić zdarzenie, wykonać oba wyrażenia lambda.
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.")
Dane wyjściowe poprzedniego kodu jest następująca:
Event occurred.
Given a value: Event occurred.
Przetwarzanie zdarzenia strumieni
Zamiast po prostu dodawania obsługi zdarzenia za pomocą Event.add funkcji, można użyć funkcji w Event moduł strumieni procesu wydarzenia w dużym stopniu dostosowanych sposobów.Aby to zrobić, należy użyć potoku do przodu (|>) wraz ze zdarzeniem jako pierwsza wartość w serii wywołania funkcji i Event moduł działa jako wywołania kolejne funkcji.
Poniższy przykład kodu pokazuje, jak skonfigurować zdarzenie, dla którego program obsługi jest wywoływana tylko pod pewnymi warunkami.
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) )
Dostrzegalnych Moduł zawiera podobne funkcje, które operują na obiekty dostrzegalnych.Obiekty dostrzegalnych są podobne do zdarzenia, ale tylko aktywnie subskrybowanie zdarzeń, jeśli sami są subskrybowane.
Wykonania zdarzenia interfejsu
Podczas opracowywania składników interfejsu użytkownika, często rozpoczyna się od utworzenia nowego formularza lub nowy formant, który dziedziczy z istniejącego formularza lub formantu.Zdarzenia często są zdefiniowane w interfejsie, i w takim przypadku musi implementować interfejs do wdrażania zdarzenia.INotifyPropertyChanged Interfejs definiuje pojedynczy PropertyChanged zdarzenia.Poniższy kod ilustruje sposób implementacji zdarzenia, które ten interfejs dziedziczone zdefiniowane:
module CustomForm
open System.Windows.Forms
open System.ComponentModel
type AppForm() as this =
inherit Form()
// Define the propertyChanged event.
let propertyChanged = Event<PropertyChangedEventHandler, PropertyChangedEventArgs>()
let mutable underlyingValue = "text0"
// Set up a click event to change the properties.
do
this.Click |> Event.add(fun evArgs -> this.Property1 <- "text2"
this.Property2 <- "text3")
// This property does not have the property-changed event set.
member val Property1 : string = "text" with get, set
// This property has the property-changed event set.
member this.Property2
with get() = underlyingValue
and set(newValue) =
underlyingValue <- newValue
propertyChanged.Trigger(this, new PropertyChangedEventArgs("Property2"))
// Expose the PropertyChanged event as a first class .NET event.
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
// Define the add and remove methods to implement this interface.
interface INotifyPropertyChanged with
member this.add_PropertyChanged(handler) = propertyChanged.Publish.AddHandler(handler)
member this.remove_PropertyChanged(handler) = propertyChanged.Publish.RemoveHandler(handler)
// This is the event-handler method.
member this.OnPropertyChanged(args : PropertyChangedEventArgs) =
let newProperty = this.GetType().GetProperty(args.PropertyName)
let newValue = newProperty.GetValue(this :> obj) :?> string
printfn "Property %s changed its value to %s" args.PropertyName newValue
// Create a form, hook up the event handler, and start the application.
let appForm = new AppForm()
let inpc = appForm :> INotifyPropertyChanged
inpc.PropertyChanged.Add(appForm.OnPropertyChanged)
Application.Run(appForm)
Jeśli chcesz spięcie zdarzenia w konstruktorze, kod jest trochę bardziej skomplikowane, ponieważ do przyłączania zdarzenia musi być w then zablokować w konstruktorze dodatkowe, jak w poniższym przykładzie:
module CustomForm
open System.Windows.Forms
open System.ComponentModel
// Create a private constructor with a dummy argument so that the public
// constructor can have no arguments.
type AppForm private (dummy) as this =
inherit Form()
// Define the propertyChanged event.
let propertyChanged = Event<PropertyChangedEventHandler, PropertyChangedEventArgs>()
let mutable underlyingValue = "text0"
// Set up a click event to change the properties.
do
this.Click |> Event.add(fun evArgs -> this.Property1 <- "text2"
this.Property2 <- "text3")
// This property does not have the property changed event set.
member val Property1 : string = "text" with get, set
// This property has the property changed event set.
member this.Property2
with get() = underlyingValue
and set(newValue) =
underlyingValue <- newValue
propertyChanged.Trigger(this, new PropertyChangedEventArgs("Property2"))
[<CLIEvent>]
member this.PropertyChanged = propertyChanged.Publish
// Define the add and remove methods to implement this interface.
interface INotifyPropertyChanged with
member this.add_PropertyChanged(handler) = this.PropertyChanged.AddHandler(handler)
member this.remove_PropertyChanged(handler) = this.PropertyChanged.RemoveHandler(handler)
// This is the event handler method.
member this.OnPropertyChanged(args : PropertyChangedEventArgs) =
let newProperty = this.GetType().GetProperty(args.PropertyName)
let newValue = newProperty.GetValue(this :> obj) :?> string
printfn "Property %s changed its value to %s" args.PropertyName newValue
new() as this =
new AppForm(0)
then
let inpc = this :> INotifyPropertyChanged
inpc.PropertyChanged.Add(this.OnPropertyChanged)
// Create a form, hook up the event handler, and start the application.
let appForm = new AppForm()
Application.Run(appForm)
Zobacz też
Informacje
Wyrażenia lambda: Fun słowa kluczowego (F#)
Control.Event < "Delegate," Args > Klasa (F#)