Megosztás a következőn keresztül:


esemény

Az események lehetővé teszik a függvényhívások felhasználói műveletekhez való társításához, és fontosak a grafikus felhasználói felület programozásában. Az eseményeket az alkalmazások vagy az operációs rendszer is kiválthatja.

Események kezelése

Ha olyan grafikus felhasználói felületi kódtárat használ, mint a Windows Forms vagy a Windows megjelenítési alaprendszer (WPF), az alkalmazásban lévő kód nagy része a kódtár által előre definiált eseményekre reagálva fut. Ezek az előre definiált események a grafikus felhasználói felület osztályainak tagjai, például űrlapok és vezérlők. Egyéni viselkedést adhat hozzá egy már létező eseményhez, például egy gombkattintáshoz, ha hivatkozik az adott nevesített eseményre (például Click az Form osztály eseményére) és a metódus meghívására Add , ahogyan az az alábbi kódban látható. Ha ezt az F# Interactive-ból futtatja, hagyja ki a hívást System.Windows.Forms.Application.Run(System.Windows.Forms.Form).

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)

A metódus típusa a Add következő ('a -> unit) -> unit: . Ezért az eseménykezelő metódus egy paramétert vesz fel, általában az eseményargumentumokat, és visszaadja a függvényt unit. Az előző példában az eseménykezelő lambda kifejezésként jelenik meg. Az eseménykezelő függvényérték is lehet, ahogyan az alábbi kód példában is látható. Az alábbi kód példája az eseménykezelő paraméterek használatát is mutatja, amelyek az esemény típusára vonatkozó információkat tartalmaznak. Esemény esetén MouseMove a rendszer átad egy System.Windows.Forms.MouseEventArgs objektumot, amely tartalmazza a X mutató helyét és Y helyét.

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)

Egyéni események létrehozása

Az F#-eseményeket az F# eseménytípus jelöli, amely implementálja az IEvent felületet. IEventmaga egy felület, amely két másik interfész és az IDelegateEvent funkcióit System.IObservable<'T>egyesíti. Ezért a meghatalmazottak más nyelveken is egyenértékű funkcióval rendelkeznek, valamint a további funkciókkalIObservable, ami azt jelenti, Eventhogy az F#-események támogatják az eseményszűréseket, és az F# első osztályú függvényeket és lambda-kifejezéseket használják eseménykezelőként. Ez a funkció az Esemény modulban érhető el.

Ha olyan eseményt szeretne létrehozni egy osztályon, amely ugyanúgy működik, mint bármely más .NET-keretrendszer esemény, adjon hozzá az osztályhoz egy let olyan kötéstEvent, amely egy osztály mezőjeként definiál. Típusargumentumként megadhatja a kívánt eseményargumentumtípust, vagy üresen hagyhatja, és a fordító a megfelelő típusra következtethet. Meg kell határoznia egy olyan eseménytagot is, amely cli-eseményként teszi elérhetővé az eseményt. Ennek a tagnak rendelkeznie kell a CLIEvent attribútummal. Tulajdonságként van deklarálva, és megvalósítása csak az esemény Publish tulajdonságának hívása. Az osztály felhasználói a Add közzétett esemény metódusával adhatnak hozzá kezelőt. A metódus argumentuma Add lehet lambda kifejezés. Az esemény tulajdonságával emelheti az eseményt, és átadhatja Trigger az argumentumokat a kezelőfüggvénynek. Az alábbi példakód ezt szemlélteti. Ebben a példában az esemény kikövetkeztetett típusargumentuma egy rekord, amely a lambda kifejezés argumentumait jelöli.

open System.Collections.Generic

type MyClassWithCLIEvent() =

    let event1 = new Event<string>()

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

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

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

classWithEvent.TestEvent("Hello World!")

System.Console.ReadLine() |> ignore

A kimenet a következő.

Event1 occurred! Object data: Hello World!

A modul által Event biztosított további funkciókat itt találja. Az alábbi példakód bemutatja egy esemény és egy triggermetódus létrehozásának alapszintű használatát Event.create , két eseménykezelő hozzáadását lambdakifejezések formájában, majd aktiválja az eseményt mindkét lambda-kifejezés végrehajtásához.

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.")

Az előző kód kimenete a következő.

Event occurred.
Given a value: Event occurred.

Eseményfeldolgozási adatfolyamok

Ahelyett, hogy az Event.add függvény használatával egyszerűen hozzáad egy eseménykezelőt egy eseményhez, a modul funkcióival nagymértékben testre szabott módon dolgozhatja fel az Event eseményfolyamokat. Ehhez a továbbítási csövet (|>) és az eseményt fogja használni a függvényhívások sorozatának első értékeként, a modul pedig Event függvényhívásokként működik.

Az alábbi példakód bemutatja, hogyan állíthat be olyan eseményt, amelyhez a kezelő csak bizonyos feltételek mellett van meghívva.

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) )

Az Megfigyelhető modul hasonló függvényeket tartalmaz, amelyek megfigyelhető objektumokon működnek. A megfigyelhető objektumok hasonlóak az eseményekhez, de csak akkor iratkoznak fel aktívan az eseményekre, ha maguk is előfizetnek rájuk.

Interfészesemény implementálása

A felhasználói felület összetevőinek fejlesztése során gyakran egy új űrlap vagy egy meglévő űrlapból vagy vezérlőelemből öröklő új vezérlő létrehozásával kezdi. Az események gyakran vannak definiálva egy felületen, és ebben az esetben implementálnia kell a felületet az esemény megvalósításához. A System.ComponentModel.INotifyPropertyChanged felület egyetlen System.ComponentModel.INotifyPropertyChanged.PropertyChanged eseményt határoz meg. Az alábbi kód bemutatja, hogyan implementálható az öröklött felület által definiált esemény:

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 {args.PropertyName} changed its value to {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)

Ha az eseményt a konstruktorban szeretné csatlakoztatni, a kód egy kicsit bonyolultabb, mert az eseménycsatlakozásnak egy then blokkban kell lennie egy további konstruktorban, ahogyan az alábbi példában is látható:

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 {args.PropertyName} changed its value to {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)

Lásd még