Events

Event routing concepts.

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.

this.button1.Click += this.Button1_Click;
...

void Button1_Click(object sender, EventArgs e) {

  this.button1.Text = "Clicked!";

}

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.

class MyButton : Wisej.Web.Button {

protected override void OnMouseDown(MouseEventArgs e) {

  base.OnMouseDown(e);
  
  this.Text = "The mouse is at " + e.Location;

}

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:

"<span>Hello</span><img src="edit.png" role="edit"/>"

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.

Touch Events

Out-of-Bound Events

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.

public class Window1 : 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 override void OnLoad(EventArgs e) {

    Program.StockMarketMonitor.PriceDrop += this.StockMarketMonitor_PriceDrop;

    base.OnLoad(e);
  }

  // When we receive a PriceDrop event, display an alert.

  void StockMarketMonitor_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.

      });
  }

}

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:
protected override voide OnWebRender(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():
protected override void OnWebEvent(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.

Last updated