Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Zdarzenia umożliwiają kojarzenie wywołań funkcji z akcjami użytkownika i są ważne w programowaniu graficznego interfejsu użytkownika. Zdarzenia mogą być również wyzwalane przez aplikacje lub przez system operacyjny.
Obsługa zdarzeń
W przypadku korzystania z biblioteki graficznego interfejsu użytkownika, takiej jak Windows Forms lub Windows Presentation Foundation (WPF), większość kodu w aplikacji jest uruchamiana w odpowiedzi na zdarzenia, które są wstępnie zdefiniowane przez bibliotekę. Te wstępnie zdefiniowane zdarzenia są elementami członkowskimi klas graficznego interfejsu użytkownika, takich jak formularze i kontrolki. Niestandardowe zachowanie można dodać do istniejącego zdarzenia, takiego jak kliknięcie przycisku, odwołując się do określonego nazwanego zdarzenia zainteresowania (na przykład Click zdarzenia Form klasy) i wywołując Add metodę, jak pokazano w poniższym kodzie. Jeśli uruchomisz to polecenie w języku F# Interactive, pomiń wywołanie metody .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)
Typ Add metody to ('a -> unit) -> unit. W związku z tym metoda obsługi zdarzeń przyjmuje jeden parametr, zazwyczaj argumenty zdarzeń i zwraca wartość unit. W poprzednim przykładzie pokazano procedurę obsługi zdarzeń jako wyrażenie lambda. Procedura obsługi zdarzeń może być również wartością funkcji, jak w poniższym przykładzie kodu. Poniższy przykład kodu pokazuje również użycie parametrów programu obsługi zdarzeń, które zawierają informacje specyficzne dla typu zdarzenia.
MouseMove W przypadku zdarzenia system przekazuje System.Windows.Forms.MouseEventArgs obiekt, który zawiera X i Y położenie wskaźnika.
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
Zdarzenia języka F# są reprezentowane przez typ zdarzenia F#, który implementuje interfejs IEvent .
IEvent sam interfejs, który łączy funkcje dwóch innych interfejsów System.IObservable<'T> i IDelegateEvent.
EventW związku z tym programy mają równoważną funkcjonalność delegatów w innych językach oraz dodatkowe funkcje programu IObservable, co oznacza, że zdarzenia języka F# obsługują filtrowanie zdarzeń i używanie funkcji pierwszej klasy języka F# i wyrażeń lambda jako procedur obsługi zdarzeń. Ta funkcja jest udostępniana w module Event (Zdarzenie).
Aby utworzyć zdarzenie w klasie, która działa podobnie jak każde inne zdarzenie programu .NET Framework, dodaj do klasy powiązanie, które definiuje Event jako pole w klasielet. Możesz określić żądany typ argumentu zdarzenia jako argument typu lub pozostawić go pusty i wywnioskować odpowiedni typ kompilatora. Należy również zdefiniować element członkowski zdarzenia, który uwidacznia zdarzenie jako zdarzenie interfejsu wiersza polecenia. Ten element członkowski powinien mieć atrybut CLIEvent . Jest deklarowana jak właściwość, a jej implementacja jest tylko wywołaniem właściwości Publish zdarzenia. Użytkownicy klasy mogą użyć Add metody opublikowanego zdarzenia, aby dodać procedurę obsługi. Argumentem Add metody może być wyrażenie lambda. Możesz użyć Trigger właściwości zdarzenia, aby zgłosić zdarzenie, przekazując argumenty do funkcji obsługi. Poniższy przykład kodu ilustruje to. W tym przykładzie argument typu wnioskowanego dla zdarzenia jest krotką, która reprezentuje argumenty wyrażenia lambda.
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
Dane wyjściowe są następujące:
Event1 occurred! Object data: Hello World!
Dodatkowe funkcje udostępniane przez Event moduł przedstawiono tutaj. Poniższy przykład kodu ilustruje podstawowe użycie Event.create metody do utworzenia zdarzenia i metody wyzwalacza, dodanie dwóch procedur obsługi zdarzeń w postaci wyrażeń lambda, a następnie wyzwolenie zdarzenia w celu wykonania obu wyrażeń 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 są następujące.
Event occurred.
Given a value: Event occurred.
Przetwarzanie strumieni zdarzeń
Zamiast po prostu dodawać program obsługi zdarzeń dla zdarzenia przy użyciu funkcji Event.add , możesz użyć funkcji w Event module do przetwarzania strumieni zdarzeń w wysoce dostosowany sposób. W tym celu należy użyć potoku przekazywania (|>) wraz ze zdarzeniem jako pierwszej wartości w serii wywołań funkcji, a Event moduł działa jako kolejne wywołania funkcji.
Poniższy przykład kodu pokazuje, jak skonfigurować zdarzenie, dla którego program obsługi jest wywoływany tylko w określonych warunkach.
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) )
Moduł Obserwowalny zawiera podobne funkcje, które działają na obserwowalnych obiektach. Obserwowane obiekty są podobne do zdarzeń, ale aktywnie subskrybują zdarzenia tylko wtedy, gdy same są subskrybowane.
Implementowanie zdarzenia interfejsu
Podczas opracowywania składników interfejsu użytkownika często zaczynasz od utworzenia nowego formularza lub nowej kontrolki dziedziczonej z istniejącego formularza lub kontrolki. Zdarzenia są często definiowane w interfejsie, a w takim przypadku należy zaimplementować interfejs w celu zaimplementowania zdarzenia. Interfejs System.ComponentModel.INotifyPropertyChanged definiuje pojedyncze System.ComponentModel.INotifyPropertyChanged.PropertyChanged zdarzenie. Poniższy kod ilustruje sposób implementowania zdarzenia zdefiniowanego przez ten dziedziczony interfejs:
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)
Jeśli chcesz podłączyć zdarzenie w konstruktorze, kod jest nieco bardziej skomplikowany, ponieważ punkt zaczepienia zdarzeń musi znajdować się w then bloku w dodatkowym konstruktorze, 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 {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)