Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Dialog Opener that Fires Server Event on Main Form when Closed

0.00/5 (No votes)
1 Dec 2004 1  
A pair of server controls, DialogOpener and DialogCloser, that you can drop on a web form to enable you to open a dialog, and when the dialog is closed, cause a server event of your choice to fire on the main form.

Introduction

Often when programming in ASP.NET, you want to pop up a dialog window that requests some kind of user input. When the user is finished with the dialog and closes it, you want the main form to fire a server event that performs some kind of refresh or other actions. Surprisingly, this task is not as easy as it seems, and a Google search turns up lots of confusing information. You can easily end up writing much more code than you need to. After some experimenting, I think I found a reasonably neat and tidy way to accomplish this, and so that I never have to do it again, I wrapped the code for opening and closing the dialog into a pair of server controls.

This article presents a pair of server controls, DialogOpener and DialogCloser, that enable you to quickly set up a dialog that opens, receives user input, closes, and fires an event of your choice on the main form.

DialogOpener

Here is the code for the DialogOpener control:

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Web;

namespace ExWebCtlLib
{
 [DefaultProperty("Text"), ToolboxData("<ExWebCtlLib:DialogOpener 
    runat="server"></WebCtlLib:DialogOpener>")]
 public class DialogOpener : System.Web.UI.WebControls.WebControl, 
    IPostBackEventHandler  
 {

  true)>
  public event EventHandler DialogClosed
  {
   add
   {
    dialogClosed += value;
   }
   remove
   {
    dialogClosed += value;
   }
  }
  private event EventHandler dialogClosed;

  true), Category("Appearance"), DefaultValue("")> 
  public string Text
  {
   get
   {
    return text;
   }

   set
   {
    text = value;
   }
  }
  private string text = "Open Dialog";

  true), Category("Appearance"), DefaultValue("")> 
  public string DialogName
  {
   get
   {
    return dialogname;
   }

   set
   {
    dialogname = value;
   }
  }
  private string dialogname = "Dialog";


  true), Category("Appearance"), DefaultValue(true)> 
  public bool Scrollbars
  {
   get
   {
    return scrollbars;
   }

   set
   {
    scrollbars = value;
   }
  }
  private bool scrollbars = true;

  true), Category("Appearance"), DefaultValue("")> 
  public string DialogPagePath
  {
   get
   {
    return dialogPagePath;
   }

   set
   {
    dialogPagePath = value;
   }
  }
  private string dialogPagePath = "";

  true), Category("Appearance"), DefaultValue("")> 
  public string DialogParam
  {
   get
   {
    if( ViewState[ this.ID + "DialogParam" ] == null )
     return dialogParam;
    else
     return (string)ViewState[ this.ID + "DialogParam" ];
   }

   set
   {
    dialogParam = value;
    ViewState[ this.ID + "DialogParam" ] = value;
   }
  }
  private string dialogParam = "-1";

  
  protected override void Render(HtmlTextWriter output)
  {
   string url = HttpContext.Current.Request.ApplicationPath + "/" + 
    DialogPagePath + @"?PostBackEventReference=" + 
    Page.Server.UrlEncode( Page.GetPostBackEventReference(this) ).Replace(
    "'", "%27" ) + @"&DialogParam=" + DialogParam;
   string height = Height.Value.ToString();
   string width = Width.Value.ToString();
   string scrollbars = Scrollbars ? "yes" : "no";

   output.Write( @"<input id=""ExFxDialogOpener"" type=""button"" 
    value=""" + Text + @""" class=""" + CssClass + @""" 
    onclick=""javascript:OpenDialog('" + url + "', '" + 
    DialogName + "', " + height + ", " + width + ", '" + 
    scrollbars + "' " + @" );"">" );
  }

  public void RaisePostBackEvent(string eventArgument)
  {
   if( dialogClosed != null )
    dialogClosed( this, new EventArgs() );
  }

 }
}

The code is mostly very straightforward, just some simple properties with getters and setters. The interesting property is the DialogClosed event property. This event will fire on the form when the dialog is closed. Now look at the construction of the URL, specifically the PostBackEventReference param. The HTML that gets generated by the control looks something like this, depending on the exact settings of the control:

<input id="ExFxDialogOpener" type="button" value="Image Gallery" 
  class="Button" onclick="javascript:OpenDialog(
  '/html/Forms/Fx/ImageGallery.aspx?PostBackEventReference=
  __doPostBack(%27_ctl15%24ImageGalleryOpener%27%2c%27%27)
  &DialogParam=SelectImage', 'Dialog', 456, 580, 'yes' );">

The PostBackEventReference is passed as a URL param to the dialog. We'll use that information in the dialog to fire the server event on closing.

The script calls the JavaScript function OpenDialog(...). You'll need to ensure that the OpenDialog script is in your page by using RegisterClientScript to register it in your main form, or modify the control to call window.open directly. Here's the script for OpenDialog.

function OpenDialog( url, name, height, width, scrollbars ) 
{
    if( scrollbars == null )
      scrollbars = "yes";
      var top = (screen.height - height) / 2;
      var left = (screen.width - width) / 2;
      window.open( url, name, "width = " + width + ", 
        height = " + height + ", menubar = no, 
        scrollbars = " + scrollbars + ", toolbar = no, 
        location = no, directories = no, resizable = no, 
        top = " + top + ", left = " + left );

(Since we have standard JavaScript registration templates in our shop, OpenDialog is always available on our pages, which is why it's not included in the DialogOpener code.)

DialogCloser

The DialogCloser control generates the necessary JavaScript to close the dialog and fire the server event on the main form. It does this by reading the PostBackEventReference that we passed in the URL using DialogOpener and constructing the required JavaScript.

Here's the code for DialogCloser:

public class DialogCloser : System.Web.UI.WebControls.WebControl
{
  public void Close()
  {
    if( HttpContext.Current.Request[ "PostBackEventReference" ] == null )
      Page.RegisterStartupScript("__close", "<script>window.close();</script>"); 
    else
    {
      string script = String.Format("<script>window.opener.{0}; 
        window.close();</script>", HttpContext.Current.Request[ 
        "PostBackEventReference" ] );
      Page.RegisterStartupScript( "__close", script ); 
    }

  }
}

Here's an example of the JavaScript that gets registered when DialogCloser.Close is called:

<script>
  window.opener.__doPostBack('_ctl15$ImageGalleryOpener',''); 
  window.close();
</script>

Compiling the Controls

To compile the controls, just create a couple of new server control classes in your own server control library. If you don't have a server control library, create a new project of type "Class Library", drop in the code, compile, then right click on your toolbox, click Add/Remove Items and browse to the .dll you just created. Click OK and the two controls will appear on your toolbox.

Using the Controls

Using the controls is easy. Create two aspx pages. One will be the main form and the other will be the dialog. Drop the DialogOpener onto the main form and open the Properties sheet. Set the DialogPagePath property to the path and name of the dialog page. Double-click the DialogClosed event and write the code you want to run when the dialog closes.

Drop the DialogCloser control onto the dialog form. Somewhere in the dialog code, when you want the dialog to close, write the following line:

DialogCloser.close();

Run the main form. Click on the DialogOpener button. Close the dialog. The DialogClosed event will be called on the main form and your event handler code will run.

Conclusion

This short article has shown you how to create a pair of useful server controls that you can drop on a pair of forms to handle dialog opening and closing, and calling a server event on the main form when the dialog closes. I hope this saves you some headache searching for the answer like I did!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here