Eventos (F#)
Eventos permitem que você associe a ações do usuário de chamadas de função e são importantes na programação de GUI.Eventos também podem ser acionados por seus aplicativos ou pelo sistema operacional.
Tratamento de eventos
Quando você usa uma biblioteca de GUI, como Windows Forms ou Windows Presentation Foundation (WPF), boa parte do código em seu aplicativo é executado em resposta a eventos que são predefinidas pela biblioteca.Esses eventos predefinidos são membros de classes de GUI como, por exemplo, formulários e controles.Você pode adicionar o comportamento personalizado a um evento preexistente, como, por exemplo, clicar em um botão, fazendo referência a específica chamada de evento de interesse (por exemplo, o Click evento da Form classe) e invocando o Add método, conforme mostrado no código a seguir.Se você executá-lo de F# interativo, omitir a chamada para 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)
O tipo da Add método é ('a -> unit) -> unit.Portanto, o método de manipulador de eventos recebe um parâmetro, normalmente, os argumentos do evento e retorna unit.O exemplo anterior mostra o manipulador de eventos como uma expressão lambda.O manipulador de eventos também pode ser um valor de função, como no exemplo de código a seguir.O exemplo de código a seguir mostra também o uso do evento parâmetros do manipulador, que fornecem informações específicas para o tipo de evento.Para um MouseMove o sistema de evento, passa um MouseEventArgs objeto, que contém o X e Y a posição do ponteiro.
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)
Criando eventos personalizados
F# eventos são representados por F# evento , de classe que implementa o IEvent interface.IEvento próprio é uma interface que combina a funcionalidade de duas interfaces, IObservable<T> e IDelegateEvent.Portanto, Events' possui a funcionalidade equivalente de delegados em outros idiomas, mais a funcionalidade adicional de IObservable, que significa que o F# eventos oferecem suporte a filtragem de eventos e usando funções de primeira classe F# e expressões lambda como manipuladores de eventos.Essa funcionalidade é fornecida na módulo de eventos.
Para criar um evento em uma classe que funciona exatamente como qualquer outro.NET evento Framework, adicione à classe um let ligação que define um Event como um campo em uma classe.Você pode especificar o tipo de argumento de evento desejado como o argumento de tipo, ou deixe em branco e que o compilador para inferir o tipo apropriado.Você também deve definir um membro de evento que expõe o evento como um evento CLI.Este membro deve ter o CLIEvent atributo.Ela é declarada como uma propriedade e sua implementação é apenas uma chamada para o Publicar propriedade do evento.Os usuários de sua classe podem usar o Add o método do evento publicado para adicionar um manipulador.O argumento para o Add método pode ser uma expressão lambda.Você pode usar o Trigger propriedade do evento para disparar o evento, passando os argumentos para a função de manipulador.O exemplo de código a seguir ilustra isso.Neste exemplo, o argumento de tipo inferido para o evento é uma tupla, que representa os argumentos para a expressão 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
A saída é da seguinte maneira.
Event1 occurred! Object data: Hello World!
A funcionalidade adicional fornecida pelo Event módulo é ilustrado aqui.O exemplo de código a seguir ilustra o uso básico do Event.create para criar um evento e um método de disparador, adicione dois manipuladores de eventos na forma de expressões lambda e, em seguida, disparar o evento para executar as duas expressões 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.")
A saída do código anterior é da seguinte maneira.
Event occurred.
Given a value: Event occurred.
Processa fluxos de evento
Em vez de simplesmente adicionar um manipulador de eventos para um evento usando o Event.add função, você pode usar as funções na Event module para fluxos de processo de eventos meios altamente personalizados.Para fazer isso, você pode usar o pipe direta (|>) juntamente com o evento como o primeiro valor em uma série de chamadas de função e o Event módulo funciona como chamadas de função subseqüentes.
O exemplo de código a seguir mostra como configurar um evento para o qual o manipulador é chamado somente sob determinadas condições.
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) )
O módulo observável contém funções semelhantes que operam nos objetos observáveis.Objetos observáveis são semelhantes aos eventos, mas apenas ativamente assinar eventos se eles próprios estão sendo inscrito.
A implementação de um evento de Interface
À medida que você desenvolve componentes de UI, normalmente começam com a criação de um novo formulário ou um novo controle que herda a partir de um formulário existente ou um controle.Eventos com freqüência são definidos em uma interface e, nesse caso, você deve implementar a interface para implementar o evento.O INotifyPropertyChanged interface define um único PropertyChanged evento.O código a seguir ilustra como implementar o evento que esta interface herdada definido:
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)
Se você desejar ligar o evento no construtor, o código é um pouco mais complicado, pois a conexão de evento deve estar em um then bloquear em um construtor adicional, como no exemplo a seguir:
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)
Consulte também
Referência
As expressões lambda: Diversão palavra-chave (F#)
Control.Event <'T>. Classe (F#)
Control.Event <'Delegate,' Args > Classe (F#)