Event routing is a cornerstone of the Wisej architecture. Wisej client-side JavaScript widgets can fire events on the server and server-side components can fire and handle events synchronously or asynchronously (out-of-bound) using the .NET standard events system.
Event Handling
Handling events is as simple as attaching a listener to the event of overriding the equivalent OnEvent method. There is really nothing else to it.
AddHandler Me.button1.Click, AddressOf Me.Button1_Click
...
Private Sub Button1_Click(sender As Object, e As EventArgs)
Me.button1.Text = "Clicked!"
End Sub
Another way to handle events in derived classes is to simply override the OnEvent methods and process the event before or after it's fired.
classMyButton:Wisej.Web.Button {protectedoverridevoidOnMouseDown(MouseEventArgs e) { base.OnMouseDown(e);this.Text="The mouse is at "+e.Location;}
Class MyButton
Inherits Wisej.Web.Button
Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
MyBase.OnMouseDown(e)
Me.Text = "The mouse is at " + e.Location
End Sub
Note that Wisej is able to inform the server of the mouse location (relative to the browser page) as well as the keyboard state, mouse buttons, and wheel delta.
Touch events from mobile devices are all translated to the appropriate mouse events.
Role Attribute
All pointer events on all components carry the Role property. This property contains the value of the "role" attribute of the specific HTML element that was clicked by the user.
In most cases it is just an empty string. However, you can use this feature to "deep click" inside a component and detect where the user clicked. For example, if you place HTML content in a DataGridViewCell like this:
You can handle the CellClick event (or any other cell pointer event) and check whether the value of the e.Role property is "edit". This works for labels, buttons, ListView, and any component in Wisej that can display HTML content.
Lazy Events
There is a group of "critical" events that are not fired back to the server unless the application has specifically attached to the handler. These are events that would typically fire multiple times.
MouseMove
MouseEnter
MouseHover
MouseLeave
MouseWheel
KeyDown
KeyPress
KeyUp
QueryContinueDrag
DragDrop
DragEnter
DragOver
DragLeave
Swipe
Paint
Pinch
Rotate
Track
TouchStart
TouchEnd
TouchCancel
Scroll
ModifiedChanged
LoadCompleted
ItemMouseHover
CellMouseEnter
CellMouseLeave
CellMouseMove
Once a handler is attached, you may also override the OnEvent method in a derived class.
Out-of-bound events are events fired outside of a browser request (user action). For example, an event fired by a thread monitoring the stock market is an out-of-bound event since the thread is running in the background and is unaware of any browser activity.
The client may also fire unattended events back to the server. However, these are in-bound events since the server is processing a request from the browser and has a valid session to work with.
When processing out-of-bound events you are processing a background task, which is a thread that has absolutely no knowledge of the session that is handling the event. Handling out-of-bound events - something close to impossible with other systems - is easy with Wisej, all you need to do is wrap the handling code in Application.RunInContext(component, ()=>{ code }) or Application.Update(component, ()=>{ code }).
The only difference between RunInContext and Update is that the Update call pushes any changes to the visual components back to the client.
publicclassWindow1:Wisej.Web.Form { // When this window is loaded, we connect to a background task (thread) monitoring the stock market. // The thread was started independently and the static reference saved in MyApp.Program.protectedoverridevoidOnLoad(EventArgs e) {Program.StockMarketMonitor.PriceDrop+=this.StockMarketMonitor_PriceDrop; base.OnLoad(e); } // When we receive a PriceDrop event, display an alert.voidStockMarketMonitor_PriceDrop(object sender,StockMarketMonitorEventArgs e) { // Restore the context using this component and run in context using Update since // we want to show the alert box immediately on the user's browser.Application.Update(this, ()=>{AlertBox.Show($"The price of {e.Symbol} dropped below {e.Limit}",MessageBoxIcon.Warning); // Note: We can also update the user's browser several times using: Application.Update(component) at any time.
}); }}
Class Window1 Inherits Wisej.Web.Form
' When this window is loaded, we connect to a background task (thread) monitoring the stock market.'
' The thread was started independently and the static reference saved in MyApp.Program.'
Protected Overrides Sub OnLoad(e As EventArgs)
AddHandler Program.StockMarketMonitor.PriceDrop, AddressOf Me.StockMarketMonitor_PriceDrop
MyBase.OnLoad(e)
End Sub
' When we receive a PriceDrop event, display an alert.'
Private Sub StockMarketMonitor_PriceDrop(sender As Object, e As StockMarketMonitorEventArgs)
' Restore the context using this component and run in context using Update since'
' we want to show the alert box immediately on the user browser.'
Application.Update(this, Sub()
AlertBox.Show($"The price of {e.Symbol} dropped below {e.Limit}", MessageBoxIcon.Warning)
' Note: We can also update the user browser several times using: Application.Update(component) at any time.'
End Sub)
End Sub
End Class
Once you are back in context, you can handle any component in the user session: update text, hide, show, move. There are no limits to what you can do using Wisej Real-Time features.
JavaScript Events
When creating new Wisej components and widgets, or integrating existing jQuery or other third-party JavaScript widgets, you will most likely need to fire an event from JavaScript running in the browser back to the server and handle it as any other .NET event.
This is how you fire the event from a Wisej widget:
/** * Assuming that this code is being processed as part of a Wisej widget, fire a simple event * notifying the server side of this widget (the corresponding control) that the label was clicked. */this.fireEvent("labelClicked");/** * We can also send data back to the server together with an event. * For example, say we want to notify the server component that a specific label was clicked. */this.fireDataEvent("labelClicked",label.getName());/** * And we can send complex data structures when we need to send back multiple values. */this.fireDataEvent("labelClicked", {name:label.getName(), x:e.getDocumentX(), y:e.getDocumentY()});/** * We can even send back the reference to a widget. Wisej will convert it to an actual control on * the server side! * * Assuming that label is a Wisej widget: */this.fireDataEvent("labelClicked", {label: label, name:label.getName(), x:e.getDocumentX(), y:e.getDocumentY()});
The example above shows how to fire JavaScript events back to the server.
The example below shows how to register a Wisej control to receive custom events and how to handle the data transported with the event.
// Override OnWebRender() to register the additional custom events:protectedoverridevoideOnWebRender(dynamic config) { base.OnWebRender((object)config); // add the new events to the list of wired events.config.wiredEvents.Add("labelClicked"); // if the event "labelClicked" carried data with it, we need to declare the name of the data member like this:config.wiredEvents.Add("labelClicked(Name)"); // the name in parethesis cna be anything. the example above used Name since the event was simply firing back the name.
// the example below uses "Data" as a more appropriate name when the event carries complex data structures:config.wiredEvents.Add("labelClicked(Data)");}// To handle the event, override OnWebEvent():protectedoverridevoidOnWebEvent(WisejEventArgs e) {switch (e.Type) {case"labelClicked": // the data caming in from the client is accessible using e.Parameters.{Name}. // in the case of the event sending back simply the name: this.fireDataEvent("labelClick", label.getName());AlertBox.Show(e.Parameters.Name); // in the case of the event sending back a data strucure:AlertBox.Show("Label Clicked at X:"+e.Parameters.Data.x+" Y: "+e.Parameters.Data.y);break;default: base.OnWebEvent(e);break; }}
When integrating third-party widgets, you can handle and process their events in JavaScript and send back to Wisej a custom event of any type. All you need to do is to handle their events as indicated in the third-party widget's documentation and then fire it to Wisej.