Client-side Suite<o:p></o:p>

Controls and Components to Help Automate Common Client-side Chores

Control Freak

LANGUAGES: C#

ASP.NET VERSIONS: 1.0 | 1.1

 

Client-side Suite

Controls and Components to Help Automate Common Client-side Chores

 

By Steve C. Orr

 

As a Web developer you sometimes need a dab of JavaScript; maybe to pop up a message box or a new window. They seem like such simple chores, yet it can take a considerable amount of coding and debugging to create a flexible solution. Writing server code is fairly straightforward for someone with a programming background. Writing client-side code isn t a foreboding task either for the adventurous type. However, mixing server code with client-side code can get rather tricky. The many ways to go about mixing client-side and server-side code can also be confusing. Although it s nice to have options, it can take a while to get your head around it all.

 

Accompanying this article are several controls that take care of several common tasks that require a mix of client-side (JavaScript) and server-side (C#) code. You can take this opportunity to learn about how it s done, or you can simply download the controls and use them as-is (see end of article for details), so you don t have to learn about such matters right now. Either way, enjoy!

 

Confirmation Button

Here s the scenario: Your user is about to commit to a significant event (such as deleting data) and you want to verify they understand what they re about to do. It s quite a common situation indeed, and you wouldn t think such a simple task would be difficult to develop. A Windows forms programmer could solve this problem with a single line of code by opening a MessageBox. However, the code required to accomplish similar dynamic functionality in ASP.NET is comparatively more complex. This kind of circumstance screams for encapsulation and reuse. Therefore, the first control in this article solves the problem in a straightforward and efficient manner by inheriting and extending the standard Button control to create a new ConfirmationButton control. Figure 1 shows the control in action.

 


Figure 1: The ConfirmationButton control provides a simple and efficient way to get dynamic feedback from your users.

 

A confirmation message is displayed when a user clicks on the button at run time, giving them an opportunity to back out of their pending decision. This is done with client-side JavaScript code so the page never posts back if the user decides to cancel; this conserves network resources and improves performance. If the user confirms their action by clicking OK on the message box, then the confirmation button posts back normally and raises the Click event just like any normal button control.

 

Now, because this control is fully configurable at design time, you ve got it even easier than those Windows forms programmers: You don t even need a single line of code! Just drag the control onto your Web form and you re done. If you wish, you can customize the confirmation message that is displayed via the ConfirmationText property, and you can configure any of the other standard button control properties as well. Figure 2 shows the source code for the ConfirmationButton control.

 

using System;

using System.Web.UI;

using System.ComponentModel;

namespace ClientSide

{

  [DefaultProperty("Text"),

   ToolboxData("<{0}:ConfirmButton runat=server>"

 +"")]

 public class ConfirmButton:

   System.Web.UI.WebControls.Button

 {

 private string _ConfirmText="Are you sure?";

  [Bindable(true),

 Category("Appearance")]

 public string ConfirmText

 {

   get {return _ConfirmText;}

   set {_ConfirmText = value;}

 }

 protected override void OnPreRender(EventArgs e)

 {

   base.Attributes.Add("OnClick",

     "return confirm('"+ _ConfirmText + "');");

 }

 }

}

Figure 2: This button asks the user to confirm their action before posting back to the server and raising the Click event. Conversely, if the user clicks the Cancel button instead of OK, the page is never posted back to the server.

 

After importing a few useful namespaces and declaring a namespace of its own, several standard attributes are added to the class definition so it appears nicely in the toolbox when being used at design time. The class inherits from the Button class and therefore gets all the functionality that it provides for free. (It should be noted that you can choose to inherit from another similar control instead, such as an ImageButton. Then you ll have a ConfirmationImageButton control.) A new property is added to hold the text for the confirmation message that is displayed to the user. Finally, the necessary JavaScript code and confirmation message are dynamically added to the client-side OnClick event of the control. You can then add the control to your Visual Studio.NET toolbox when you compile this code inside a Web Control Library project. Then you can drag the control onto any Web form.

 

Beloved MessageBox

The ConfirmationButton control is certainly useful for many situations. However, there are some times when you ll need to display a simple message and no real confirmation is needed from the user. A Label control could be used for such a display, but there are some situations where a basic MessageBox is the perfect solution. Figure 3 shows such an example.

 


Figure 3: Displaying a basic MessageBox to a user should be easier than it is by default in ASP.NET.

 

The following control will make it as easy for you to display a MessageBox on a Web form as it is to display one on a Windows form. How s this for easy?

 

MessageBox1.Text="Hello World.";

 

Figure 4 shows the code that makes things seem so simple. As with the previous control, this one starts with some standard items that establish namespaces and toolbox attributes. It then inherits from the standard .NET Control class, which provides it with the basic functionality that every control needs. Then the first, and only, custom property is defined. This Text property is empty by default, and has attributes that define it to be bindable and to display in the Appearance section of the property window when used at design time. Finally, the necessary client-side JavaScript code is rendered to the output stream of the page. A StringBuilder object is used to concatenate this script, as they are highly efficient at such tasks. As soon as the script arrives at the browser it is displayed; therefore, you ll often want to place this control at the bottom of your page so it will display after the rest of the page has been rendered in the browser. If the Text property is left empty, no script is generated and no MessageBox will be displayed.

 

using System.Text;

using System.Web.UI;

using System.ComponentModel;

namespace ClientSide

{

  [DefaultProperty("Text"),

 ToolboxData("<{0}:MessageBox runat=server>"

   + "")]

 public class MessageBox : System.Web.UI.Control

 {

   private string text="";

    [Bindable(true),

   Category("Appearance"),

   DefaultValue("")]

   public string Text

   {

     get {return text;}

     set {text = value;}

   }

   protected override void Render(HtmlTextWriter output)

   {

     if (text.Length>0)

     {

       StringBuilder sb = new StringBuilder();

       sb.Append("");

       output.Write(sb.ToString());

     }

   }

 }

}

Figure 4: Now ASP.NET developers can display a MessageBox with a single line of code just like Windows forms developers can.

 

As with the previous control (and most any control), it is to be compiled inside a Web Control Library project. The sample code accompanying this article puts it in the same project as the ConfirmationButton control, and in the same namespace as well (see end of article for download details). The control can then be added to the Visual Studio.NET toolbox and dragged onto any Web form.

 

Although this MessageBox control works great in many situations, it has a rather awkward characteristic. The control can be dragged onto a specific place on the page, and yet it is never really displayed there. Sure, it has a placeholder so you can find it at design time (as shown in Figure 5), but the placement on the page doesn t really matter much and it certainly doesn t matter at run time since a MessageBox is displayed above the page and not really in the page itself. The next example uses an alternative technique that avoids this slightly awkward design.

 


Figure 5: The two non-visible components on this page use different design techniques, so the MessageBox control appears inside the page at design time while the WindowOpener component displays beneath the form in the component tray.

 

Popup Windows Aren t All Bad

Sometimes a standard MessageBox just isn t enough. Some situations require a more sophisticated display of information. HTML, of course, is great at sophisticated layouts, which is why popup windows have become popular for displaying sidebars of various sorts. Greedy advertisers have taken advantage of them (and us) by using them excessively to present messages of all kinds. Please stop reading now if you re one of those greedy advertisers I don t want to help you. However, if you re a responsible developer (as I suspect you are), then here s a simple way to pop up complex prompts and displays of all kinds.

 

As with the MessageBox control, this new WindowOpener control will have no real display on the page in which it is hosted. Instead, it will display above the page. Therefore, its position inside the host page doesn t really matter. It won t be displayed on the page at all at design time, but it will instead be displayed below the page in the component tray, as pictured in Figure 5. Technically, this makes it more of a component than a control, but controls are a kind of component, so it s all in the family.

 

One of the easiest ways to add a new component to a Web Control Library project is to select Add Component from the Project dropdown menu in Visual Studio.NET. This technique automatically provides all the standard interfaces, constructors, and other such code that is needed for every component.

 

The most interesting parts of the WindowOpener component source code are displayed in Listing One; the full source code is available for download. Opening a new window in a flexible and reusable way can be quite a chore, but the component in Listing One simplifies the process greatly. As usual, the namespaces are declared first and then the class is defined. This one inherits from the Component class. For convenience it has two overridden versions of the OpenWindow methods. Ultimately, the first OpenWindow method calls the second one. The first one allows for a simple one-line invocation, like this:

 

windowOpener1.OpenWindow("http://Steve.Orr.net");

 

The second OpenWindow method assumes you ve already set the URL property and any other WindowOpener properties that you wish to set. Ultimately, they both call the public GeneratedJScript method, which (as you might guess) generates and returns the JavaScript code required to open the window.

 

This method is made public so that you may optionally call it directly to retrieve the JavaScript in case you want to do something interesting with it, such as attaching it to a client-side event. For example, the following line of code commands a popup window to be displayed when an image control is clicked by the user:

 

Image1.Attributes.Add("OnClick",

windowOpener1.GeneratedJScript());

 

Basically, this WindowOpener component encapsulates the JavaScript Window.Open method. If you re familiar with this method, then you should find the WindowOpener component to be quite intuitive. It provides more than a dozen properties to adjust how the window will be displayed, such as the size and location of the window, the URL to be displayed in the window, which IE toolbars and status bars to display, and the name of the window. The window name will be important if you want to interact with the window after it has been opened (with your own custom JavaScript), perhaps to pass information back and forth between the child window and its parent.

 

Conclusion

At this point you have three useful components in your hands to make common client-side chores a breeze. They take seemingly simple chores which are actually fairly involved and turn them into the simple invocations that most Windows programmers have come to expect. I encourage you to use them and extend them with new functionality, such as the ability to return more complex input from users. I d love to hear about any customizations of which you re proud enough to share.

 

The sample code accompanying this article is available for download.

 

Steve C. Orr is an MCSD and a Microsoft MVP in ASP.NET. He s an independent consultant who develops software solutions for many leading companies in the Seattle area, such as Microsoft, Lumedx, and The Cadmus Group. When he s not busy designing software systems or writing about it, he can often be found loitering at local user groups and habitually lurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.net or e-mail him at mailto:[email protected].

 

Begin Listing One

using System;

using System.ComponentModel;

using System.Text;

namespace ClientSide

{

 public class WindowOpener : System.ComponentModel.Component

 {

   public void OpenWindow(string URL)

   {

     _URL=URL;

     OpenWindow();

   }

   public void OpenWindow()

   {

     if (_URL.Trim().Length>0)

     {

       System.Web.HttpContext.Current.Response.Write(

         "");

     }

   }

   public string GeneratedJScript()

   {

     StringBuilder sb = new StringBuilder();

     sb.Append("status="+

       Convert.ToInt32(_StatusBar) + ",");

     sb.Append("location="+

       Convert.ToInt32(_LocationBar) + ",");

     sb.Append("menubar="+

       Convert.ToInt32(_MenuBar) + ",");

     sb.Append("titlebar="+

       Convert.ToInt32(_TitleBar) + ",");

     sb.Append("toolbar="+

       Convert.ToInt32(_ToolBar) + ",");

     sb.Append("scrollbars="+

       Convert.ToInt32(_ScrollBars) + ",");

     sb.Append("resizable="+

       Convert.ToInt32(_Resizable) + ",");

     sb.Append("fullscreen="+

       Convert.ToInt32(_FullScreen) + ",");

     if (_Height>0) sb.Append("height="+

                _Height + ",");

     if (_Width>0) sb.Append("width="+

               _Width + ",");

     

     string s;

     if (_Modal==true)

       s="window.showModalDialog('"+

         _URL + "','"+sb.ToString()+"');";

     else

       s="window.open('"+ _URL + "','"+

         _WindowName+"','"+sb.ToString()+"');";

     return s;

    }

   private string _URL = "http://Steve.Orr.net";

    [Bindable(true),

   Category("Appearance"),

   Description("URL to be opened in the new window")]

   public string URL

   {

     get {return _URL;}

     set {_URL = value;}

   }

   private string _WindowName = "_blank";

    [Bindable(true), Category("Appearance")]

   public string WindowName

   {

     get {return _WindowName;}

     set {_WindowName = value;}

   }

   private bool _StatusBar = true;

    [Bindable(true), Category("Appearance")]

   public bool StatusBar

   {

     get {return _StatusBar;}

     set {_StatusBar = value;}

   }

 }

}

End Listing One

 

Warning!

These days a lot of people have some form of popup blocker on their computers. These imperfect add-ins, which are intended to block unwanted advertisements, sometimes interfere with legitimate popup window functionality. Therefore, you may end up with some tech support headaches that you won t have if you avoid popup windows. This is less of a problem in an intranet environment where you likely have more control of your user s browser settings.

 

 

 

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish