Monday, September 10, 2012

Creating Web Dialog Boxes On-The-Fly

When creating a web application with Real Studio, dialog boxes can be managed in a way that is much easier and nicer than in a desktop application. After creating the dialog box, you can just drag it onto the web page in which you wish to show the dialog. An instance of the dialog appears in the tray at the bottom of the layout editor:

To display the dialog box, simply call the Show method from the instance you added. For example,  to show the dialog above, your code would be:


To help you visualize it, here's the example login dialog box in action:

What makes web dialog boxes different from how dialogs are handled in desktop applications is that in web applications the dialog as a whole is treated like a control. It has events and maintains its values while the web page is open. For example, if the user clicks a checkbox in the dialog or fills in a textfield, when you display the dialog again, those values will still be set. This can be convenient if that's the behavior you want. If it's not, it might be your instinct to add code to the Shown event (either of the dialog or the individual controls in the dialog) to reset things. Perhaps you need to set a checkbox back to unchecked (or checked) or clear the values from textfields.

Rather than writing all that code that then has to be maintained, you can instead create an instance of the dialog on-the-fly rather than dragging it to the page itself to create an instance. The advantage is that since you are creating it on-the-fly each time its going to be displayed, the controls will automatically be reset to their default values.

To display the dialog is easy enough. You create an instance of the dialog then call the Show method:

dim theDialog As New LoginDialog

The example above is a login dialog box. Where would you put the code to log the user into your system? Ideally, you would keep that code with the web page that displays the dialog since you might use this dialog for another purpose on another page. It's easy to display a web dialog using the method first described, simply put your code in the Dismissed event of the web dialog instance on the page. That's the MyLogin web dialog box in the first figure above. You might think that when creating a web dialog on-the-fly, you would simply add your code after calling the Show method. For example:

dim theDialog As New LoginDialog
'code to log into the system goes here

That won't work because web dialogs, even when instantiated on-the-fly, execute asynchronously. That means that while the dialog will be displayed, the code following the Show method won't wait for the dialog to be dismissed by the user. It will execute immediately. So that method is not going to work.

You might be thinking you will just use the web dialog's Dismissed event. The problem with that solution is that this event is part of the web dialog itself and not part of the page where the dialog is used. That means that you can't easily use the web dialog with different pages.

The solution is to re-route the web dialog's Dismissed event so that it causes a method of the web page itself to execute. The code that should execute when the dialog is dismissed will be part of the web page that called an instance of the web dialog in the first place. To do this, you use a method call AddHandler. Using this method, you are telling the web framework that you want to delegate responsibility for handling a particular event to a method instead. AddHandler needs to know which event you want to delegate and the method that will handle the event. Here's a version that uses the AddHandler method when displaying the same dialog box:

dim theDialog As New LoginDialog
AddHandler theDialog.Dismissed, AddressOf LogInDismissed

LoginDismissed, in this case, is a method of the web page that is displaying the dialog box. The AddressOf operator is passing the memory address of the LoginDismissed method so that it can be executed when the Dismissed event fires. That's it. Just add a LoginDismissed method to the web page and write the code there that should execute when the dialog is closed. When you want to use this dialog with another page, just add a LoginDismissed method to that page and use the same code above to display the dialog box. The LoginDismissed method will be passed a reference to the dialog object so you can easily access the dialog's various controls.

In this example, the Login dialog has Cancel and OK buttons. You need to know which one they clicked. So the LoginDialog has an Accepted As Boolean property. The Action event of the OK button sets this property to true so you just test for that in the LogInDismissed method:

LoginDismisssed(theDialog As LoginDialog)
  if thedialog.Accepted then
    MsgBox "The user clicked OK."
  end if
End Sub

Creating a web dialog on-the-fly is a little more work than simply dragging one on to a web page, but it also can save you from having to write extra code to reset the dialog each time you display it should you need that behavior.

There's an example project available here.

1 comment:

Valéry Tarondeau said...

I'm so glad that creating dialogs on the fly are officially supported !
I'm using this since the beginning with the fear to learn that it won't be supported in the future.
Thanks !