Ekinlikler
Olaylar, işlev çağrılarını kullanıcı eylemleriyle ilişkilendirmenize olanak tanır ve GUI programlamada önemlidir. Olaylar, uygulamalarınız veya işletim sistemi tarafından da tetiklenebilir.
Olayları İşleme
Windows Forms veya Windows Presentation Foundation (WPF) gibi bir GUI kitaplığı kullandığınızda, uygulamanızdaki kodun çoğu kitaplık tarafından önceden tanımlanan olaylara yanıt olarak çalıştırılır. Bu önceden tanımlı olaylar, formlar ve denetimler gibi GUI sınıflarının üyeleridir. Aşağıdaki kodda gösterildiği gibi ilgili belirli adlandırılmış olaya (örneğin, Click
sınıfın Form
olayı) başvurarak ve yöntemini çağırarak Add
, düğme tıklaması gibi önceden var olan bir olaya özel davranış ekleyebilirsiniz. Bunu F# Etkileşimli'den çalıştırırsanız çağrısının atını System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
atlarsınız.
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)
yönteminin Add
türü şeklindedir ('a -> unit) -> unit
. Bu nedenle, olay işleyici yöntemi genellikle olay bağımsız değişkenleri olan bir parametre alır ve döndürür unit
. Önceki örnekte, olay işleyici lambda ifadesi olarak gösterilmiştir. Olay işleyicisi, aşağıdaki kod örneğinde olduğu gibi, bir işlev değeri de olabilir. Aşağıdaki kod örneğinde, olay türüne özgü bilgiler sağlayan olay işleyicisi parametrelerinin kullanımı gösterilmektedir. Bir MouseMove
olay için, sistem işaretçinin X
ve Y
konumunu içeren bir System.Windows.Forms.MouseEventArgs
nesnesi geçirir.
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)
Özel Olaylar Oluşturma
F# olayları, IEvent arabirimini uygulayan F# Olay türüyle temsil edilir. IEvent
, diğer iki arabirimin ve IDelegateEvent'in işlevselliğini birleştiren bir arabirimdirSystem.IObservable<'T>
. Bu nedenle, Event
diğer dillerdeki temsilcilerin eşdeğer işlevlerine, ayrıca IObservable
F# olaylarının olay filtrelemeyi desteklediği ve F# birinci sınıf işlevleri ve lambda ifadelerini olay işleyicileri olarak kullandığı anlamına gelir. Bu işlev Olay modülünde sağlanır.
Diğer tüm .NET Framework olayları gibi davranan bir sınıfta olay oluşturmak için sınıfına bir sınıfın let
alanı olarak tanımlayan Event
bir bağlama ekleyin. İstenen olay bağımsız değişkeni türünü tür bağımsız değişkeni olarak belirtebilir veya boş bırakarak derleyicinin uygun türü ortaya çıkarmasını sağlayabilirsiniz. Ayrıca, olay CLI olayı olarak sunan bir olay üyesi de tanımlamanız gerekir. Bu üye CLIEvent özniteliğine sahip olmalıdır. Bir özellik olarak bildirilir ve uygulaması yalnızca olayın Publish özelliğine yapılan bir çağrıdır. Sınıfınızın kullanıcıları, bir işleyici eklemek için yayımlanan olayın yöntemini kullanabilir Add
. yöntemi için Add
bağımsız değişken bir lambda ifadesi olabilir. Bağımsız değişkenleri işleyici işlevine geçirerek olayı yükseltmek için olayının özelliğini kullanabilirsiniz Trigger
. Aşağıdaki kod örneği bunu gösterir. Bu örnekte, olay için gösterilen tür bağımsız değişkeni, lambda ifadesi için bağımsız değişkenleri temsil eden bir kayıt düzenidir.
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
Çıktı aşağıdaki gibidir:
Event1 occurred! Object data: Hello World!
Modül tarafından Event
sağlanan ek işlevler burada gösterilmiştir. Aşağıdaki kod örneği, bir olay ve tetikleyici yöntemi oluşturmak, lambda ifadeleri biçiminde iki olay işleyicisi eklemek ve ardından her iki lambda ifadesini yürütmek için olayı tetikleme işleminin temel kullanımını Event.create
gösterir.
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.")
Önceki kodun çıktısı aşağıdaki gibidir.
Event occurred.
Given a value: Event occurred.
Olay Akışını İşleme
Event.add işlevini kullanarak yalnızca bir olay için olay işleyicisi eklemek yerine modüldeki Event
işlevleri kullanarak olay akışlarını yüksek oranda özelleştirilmiş yollarla işleyebilirsiniz. Bunu yapmak için, bir dizi işlev çağrısında ilk değer olarak olayla birlikte iletme kanalını (|>
) ve Event
sonraki işlev çağrıları olarak modül işlevlerini kullanırsınız.
Aşağıdaki kod örneği, işleyicinin yalnızca belirli koşullarda çağrıldığı bir olayın nasıl ayarlanacağını gösterir.
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) )
Gözlemlenebilir modülü, gözlemlenebilir nesneler üzerinde çalışan benzer işlevler içerir. Gözlemlenebilir nesneler olaylara benzer, fakat yalnızca, kendilerine abone olunuyorsa olaylara etkin olarak abone olurlar.
Bir Arabirim Olayı Uygulama
UI bileşenleri geliştirirken, genellikle varolan bir formdan veya denetimden devralan yeni bir form veya yeni bir denetim oluşturarak başlarsınız. Olaylar genellikle bir arabirimde tanımlanır ve bu o durumda, olayı gerçekleştirmek için arabirimi gerçekleştirmeniz gerekir. Arabirimi tek System.ComponentModel.INotifyPropertyChanged
System.ComponentModel.INotifyPropertyChanged.PropertyChanged
bir olayı tanımlar. Aşağıdaki kod, bu devralınan arabirimde tanımlanan olayın nasıl uygulanacağını göstermektedir:
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)
Oluşturucuda olayı bağlamak istiyorsanız, kod biraz daha karmaşıktır çünkü aşağıdaki örnekte olduğu gibi olay kancası ek bir oluşturucudaki bir then
blokta olmalıdır:
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)