Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les événements vous permettent d’associer des appels de fonction à des actions utilisateur et sont importants dans la programmation de l’interface graphique utilisateur. Les événements peuvent également être déclenchés par vos applications ou par le système d’exploitation.
Gestion des événements
Lorsque vous utilisez une bibliothèque d’interface graphique graphique comme Windows Forms ou Windows Presentation Foundation (WPF), une grande partie du code de votre application s’exécute en réponse à des événements prédéfinis par la bibliothèque. Ces événements prédéfinis sont des membres de classes GUI telles que des formulaires et des contrôles. Vous pouvez ajouter un comportement personnalisé à un événement préexistant, tel qu’un clic de bouton, en référençant l’événement nommé spécifique d’intérêt (par exemple, l’événement Click de la Form classe) et en appelant la Add méthode, comme illustré dans le code suivant. Si vous exécutez cette opération à partir de F# Interactive, omettez l’appel à 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)
Le type de la Add méthode est ('a -> unit) -> unit. Par conséquent, la méthode du gestionnaire d’événements prend un paramètre, généralement les arguments d’événement et retourne unit. L’exemple précédent montre le gestionnaire d’événements en tant qu’expression lambda. Le gestionnaire d’événements peut également être une valeur de fonction, comme dans l’exemple de code suivant. L’exemple de code suivant montre également l’utilisation des paramètres du gestionnaire d’événements, qui fournissent des informations spécifiques au type d’événement. Pour un MouseMove événement, le système transmet un System.Windows.Forms.MouseEventArgs objet, qui contient la position et Y la X position du pointeur.
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)
Création d'événements personnalisés
Les événements F# sont représentés par le type d’événement F#, qui implémente l’interface IEvent .
IEvent est lui-même une interface qui combine les fonctionnalités de deux autres interfaces et System.IObservable<'T>IDelegateEvent. Par conséquent, Eventles événements F# prennent en charge le IObservablefiltrage des événements et utilisent des fonctions lambda et des fonctions F# de première classe et des expressions lambda en tant que gestionnaires d’événements. Cette fonctionnalité est fournie dans le module Événement.
Pour créer un événement sur une classe qui agit comme n’importe quel autre événement .NET Framework, ajoutez à la classe une let liaison qui définit un Event champ en tant que champ dans une classe. Vous pouvez spécifier le type d’argument d’événement souhaité comme argument de type, ou le laisser vide et déduire le type approprié par le compilateur. Vous devez également définir un membre d’événement qui expose l’événement en tant qu’événement CLI. Ce membre doit avoir l’attribut CLIEvent . Elle est déclarée comme une propriété et son implémentation n’est qu’un appel à la propriété Publish de l’événement. Les utilisateurs de votre classe peuvent utiliser la Add méthode de l’événement publié pour ajouter un gestionnaire. L’argument de la Add méthode peut être une expression lambda. Vous pouvez utiliser la Trigger propriété de l’événement pour déclencher l’événement, en passant les arguments à la fonction de gestionnaire. L’exemple de code suivant illustre cela. Dans cet exemple, l’argument de type déduit pour l’événement est un tuple, qui représente les arguments de l’expression 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
La sortie est la suivante.
Event1 occurred! Object data: Hello World!
Les fonctionnalités supplémentaires fournies par le Event module sont illustrées ici. L’exemple de code suivant illustre l’utilisation de base pour Event.create créer un événement et une méthode de déclencheur, ajouter deux gestionnaires d’événements sous la forme d’expressions lambda, puis déclencher l’événement pour exécuter les deux expressions 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.")
La sortie du code précédent est la suivante.
Event occurred.
Given a value: Event occurred.
Traitement des flux d’événements
Au lieu d’ajouter simplement un gestionnaire d’événements pour un événement à l’aide de la fonction Event.add , vous pouvez utiliser les fonctions du Event module pour traiter les flux d’événements de manière hautement personnalisée. Pour ce faire, vous utilisez le canal de transfert (|>) avec l’événement comme première valeur dans une série d’appels de fonction, et les Event fonctions de module comme appels de fonction suivants.
L’exemple de code suivant montre comment configurer un événement pour lequel le gestionnaire est appelé uniquement dans certaines conditions.
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) )
Le module Observable contient des fonctions similaires qui fonctionnent sur des objets observables. Les objets observables sont similaires aux événements, mais s’abonnent activement aux événements s’ils sont eux-mêmes abonnés.
Implémentation d’un événement d’interface
Lorsque vous développez des composants d’interface utilisateur, vous commencez souvent par créer un formulaire ou un nouveau contrôle qui hérite d’un formulaire ou d’un contrôle existant. Les événements sont fréquemment définis sur une interface et, dans ce cas, vous devez implémenter l’interface pour implémenter l’événement. L’interface System.ComponentModel.INotifyPropertyChanged définit un événement unique System.ComponentModel.INotifyPropertyChanged.PropertyChanged . Le code suivant montre comment implémenter l’événement défini par cette interface héritée :
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)
Si vous souhaitez raccorder l’événement dans le constructeur, le code est un peu plus compliqué, car le raccordement d’événement doit se trouver dans un bloc dans un then constructeur supplémentaire, comme dans l’exemple suivant :
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)