September 24, 2004 12:09 AM

Client-side Suite

Controls and Components to Help Automate Common Client-side Chores
DevConnections
Rating: (0)

ControlFreak

LANGUAGES: C#

ASP.NET VERSIONS: 1.0 | 1.1

 

Client-sideSuite

Controlsand Components to Help Automate Common Client-side Chores

 

 

As a Webdeveloper you sometimes need a dab of JavaScript; maybe to pop up a message boxor a new window. They seem like such simple chores, yet it can take aconsiderable amount of coding and debugging to create a flexible solution.Writing server code is fairly straightforward for someone with a programmingbackground. Writing client-side code isn?t a foreboding task either ? for theadventurous type. However, mixing server code with client-side code can getrather tricky. The many ways to go about mixing client-side and server-sidecode can also be confusing. Although it?s nice to have options, it can take awhile to get your head around it all.

 

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

 

ConfirmationButton

Here?sthe scenario: Your user is about to commit to a significant event (such asdeleting 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 taskwould be difficult to develop. A Windows forms programmer could solve thisproblem with a single line of code by opening a MessageBox. However, the coderequired to accomplish similar dynamic functionality in ASP.NET iscomparatively more complex. This kind of circumstance screams for encapsulationand reuse. Therefore, the first control in this article solves the problem in astraightforward and efficient manner by inheriting and extending the standardButton control to create a new ConfirmationButton control. Figure 1 shows thecontrol in action.

 


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

 

Aconfirmation 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 donewith client-side JavaScript code so the page never posts back if the userdecides to cancel; this conserves network resources and improves performance.If the user confirms their action by clicking OK on the message box, then theconfirmation button posts back normally and raises the Click event just likeany normal button control.

 

Now,because this control is fully configurable at design time, you?ve got it eveneasier than those Windows forms programmers: You don?t even need a single lineof 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 theConfirmationText property, and you can configure any of the other standardbutton control properties as well. Figure 2 shows the source code for theConfirmationButton control.

 

using System;

usingSystem.Web.UI;

usingSystem.ComponentModel;

 

namespaceClientSide

{

  [DefaultProperty("Text"),

   ToolboxData("<{0}:ConfirmButtonrunat=server>"

 +"</{0}:ConfirmButton>")]

 public class ConfirmButton:

   System.Web.UI.WebControls.Button

 {

 private string _ConfirmText="Are yousure?";

  [Bindable(true),

 Category("Appearance")]

 public string ConfirmText

 {

   get {return _ConfirmText;}

   set {_ConfirmText = value;}

 }

 

 protected override void OnPreRender(EventArgse)

 {

   base.Attributes.Add("OnClick",

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

 }

 }

}

Figure2: This buttonasks the user to confirm their action before posting back to the server andraising the Click event. Conversely, if the user clicks the Cancel buttoninstead of OK, the page is never posted back to the server.

 

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

 

BelovedMessageBox

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

 


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

 

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

 

MessageBox1.Text="HelloWorld.";

 

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

 

usingSystem.Text;

usingSystem.Web.UI;

usingSystem.ComponentModel;

 

namespaceClientSide

{

  [DefaultProperty("Text"),

 ToolboxData("<{0}:MessageBoxrunat=server>"

   + "</{0}:MessageBox>")]

 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 voidRender(HtmlTextWriter output)

   {

     if (text.Length>0)

     {

       StringBuilder sb = new StringBuilder();

       sb.Append("<scriptlanguage='javascript'>");

       sb.Append("alert('"+text+"')");

       sb.Append("</script>");

       output.Write(sb.ToString());

     }

   }

 }

}

Figure4: Now ASP.NETdevelopers can display a MessageBox with a single line of code ? just likeWindows forms developers can.

 

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

 

Althoughthis MessageBox control works great in many situations, it has a rather awkwardcharacteristic. 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 youcan find it at design time (as shown in Figure 5), but the placement on thepage doesn?t really matter much ? and it certainly doesn?t matter at run timesince a MessageBox is displayed above the page and not really in the pageitself. The next example uses an alternative technique that avoids thisslightly awkward design.

 


Figure 5: The two non-visible components onthis page use different design techniques, so the MessageBox control appearsinside the page at design time while the WindowOpener component displaysbeneath the form in the component tray.

 

PopupWindows Aren?t All Bad

Sometimesa standard MessageBox just isn?t enough. Some situations require a moresophisticated display of information. HTML, of course, is great atsophisticated layouts, which is why popup windows have become popular fordisplaying sidebars of various sorts. Greedy advertisers have taken advantageof 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?twant to help you. However, if you?re a responsible developer (as I suspect youare), then here?s a simple way to pop up complex prompts and displays of allkinds.

 

As withthe MessageBox control, this new WindowOpener control will have no real displayon 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 bedisplayed on the page at all at design time, but it will instead be displayedbelow 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 ofcomponent, so it?s all in the family.

 

One ofthe easiest ways to add a new component to a Web Control Library project is toselect Add Component from the Project dropdownmenu in Visual Studio.NET. This technique automatically provides all thestandard interfaces, constructors, and other such code that is needed for everycomponent.

 

The mostinteresting parts of the WindowOpener component source code are displayed in Listing One; the full source code is available fordownload. Opening a new window in a flexible and reusable way can be quite achore, but the component in Listing One simplifies the process greatly. Asusual, the namespaces are declared first and then the class is defined. Thisone inherits from the Component class. For convenience it has two overriddenversions of the OpenWindowmethods. Ultimately, the first OpenWindowmethod calls the second one. The first one allows for a simple one-lineinvocation, like this:

 

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

 

Thesecond OpenWindow method assumesyou?ve already set the URL property and any other WindowOpener properties thatyou wish to set. Ultimately, they both call the public GeneratedJScript method,which (as you might guess) generates and returns the JavaScript code requiredto open the window.

 

Thismethod is made public so that you may optionally call it directly to retrievethe JavaScript in case you want to do something interesting with it, such asattaching it to a client-side event. For example, the following line of codecommands a popup window to be displayed when an image control is clicked by theuser:

 

Image1.Attributes.Add("OnClick",

windowOpener1.GeneratedJScript());

 

Basically,this WindowOpener component encapsulates the JavaScript Window.Open method. Ifyou?re familiar with this method, then you should find the WindowOpenercomponent to be quite intuitive. It provides more than a dozen properties toadjust how the window will be displayed, such as the size and location of thewindow, the URL to be displayed in the window, which IE toolbars and statusbars to display, and the name of the window. The window name will be importantif you want to interact with the window after it has been opened (with your owncustom JavaScript), perhaps to pass information back and forth between thechild window and its parent.

 

Conclusion

At thispoint you have three useful components in your hands to make common client-sidechores a breeze. They take seemingly simple chores ? which are actually fairlyinvolved ? and turn them into the simple invocations that most Windowsprogrammers have come to expect. I encourage you to use them and extend themwith new functionality, such as the ability to return more complex input fromusers. I?d love to hear about any customizations of which you?re proud enoughto share.

 

Thesample code accompanying this article is available for download.

 

Steve C.Orr is an MCSD anda Microsoft MVP in ASP.NET. He?s an independent consultant who developssoftware solutions for many leading companies in the Seattle area, such as Microsoft, Lumedx, andThe Cadmus Group. When he?s not busy designing software systems or writingabout it, he can often be found loitering at local user groups and habituallylurking in the ASP.NET newsgroup. Find out more about him at http://Steve.Orr.netor e-mail him at mailto:Steve@Orr.net.

 

Begin Listing One

using System;

usingSystem.ComponentModel;

usingSystem.Text;

 

namespaceClientSide

{

 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(

         "<scriptlanguage=javascript>"+

         GeneratedJScript() +"</script>");

     }

   }

 

   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 thenew 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 ListingOne

 

Warning!

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

 

 

 

Add a Comment

There are no comments to display. Be the first one!
You must log on before posting a comment.

Are you a new visitor? Register Here

advertisement




Comments from the DevConnections Community

Join our community of development pros.

Windows problem

I all, I have a problem on my Windows Vista that began afetr the purchase of an external Hard Disk Freecom. A few days afetr the purchase I discon...

Most Recent Posts

GOOGLE LINKS
SPONSORED LINKS
FEATURED LINKS