Dialog Hell

ASP.NET is a great tool, but it definately has its limitations. One of those limitations is the fact that it has no built in support for any kind of UI that uses dialogs. I assume that if you have been using ASP.NET for a decent amount of time, you have run into this problem more than once.

At the base level, the problem is pretty simple to solve, but if you have a lot of dialogs in your application, you can wind up writing a lot of extra code just to get things working. This isn't even to mention that things go from bad to worse if you want your dialogs to function like real dialogs (ie. they are reusable, so you can launch, wait for the user to select an item, and then do something based off of that selection back in the code behind for the page that launched the dialog).

While building our ASP.NET based CMS (<shameless_plug>a very cool product which is due for release in the near future</shameless_plug>), it quickly became aparent that all the JavaScript coding that we were doing was quite redundant and was quite a pain. So, I put together a few classes to handle most of the basic dialog functionality. If you are in the same type of situation, you may find these classes useful. Basically, there is one base class that can be used to create a draggable dialog control (Dialog). This class basically handles launching the dialog and processing the return results (an “Open“ function is included to create the JS launch script for your dialog). The second class, “DialogPage“ serves as the base page class for your dialogs (just change inheritance on the Page class in your code behind file). It contains a few helper methods to close the window and return results. A third class, PostBackHandler is a stripped down control with no UI that allows you to handle the results of the dialog via a PostBack event. Using this type of approach definately makes working with the custom dialogs in your project a lot more developer-friendly (not to mention that you can extend the base classes to have things like modal dialog support, and all your dialogs will be automatically upgraded).

public abstract class Dialog : Control, INamingContainer

{

public Dialog()

{

pbhDialogHandler.ID = "pbhDialogHandler";

pbhDialogHandler.PostBack+=

new PostBackEventHandler(pbhDialogHandler_PostBack);

Controls.Add(pbhDialogHandler);

}

protected override void OnPreRender(EventArgs e)

{

base.OnPreRender (e);

Page.RegisterStartupScript("__dialog","<script>function __processDialogResults(controlID, results) { __doPostBack(controlID,results); }</script>");

}

PostBackHandler pbhDialogHandler =

new PostBackHandler();

protected override void CreateChildControls()

{

base.CreateChildControls ();

}

void pbhDialogHandler_PostBack(object sender, PostBackEventArgs e)

{

ProcessDialogResults(e.EventArgument);

}

protected virtual void ProcessDialogResults(string results)

{

}

protected void Open(string windowName, string url, int width, int height)

{

if(url.StartsWith("~/"))

{

url = Page.Request.ApplicationPath+"/"+url.Substring(2);

}

if(url.IndexOf("?") == -1)

{

url = url+"?ControlID="+HttpUtility.UrlEncode(

this.pbhDialogHandler.UniqueID.Replace(":","$"));

}

else

{

url = url+"&ControlID="+HttpUtility.UrlEncode(

this.pbhDialogHandler.UniqueID.Replace(":","$"));

}

Page.RegisterStartupScript("__open", "<script>window.open('"+url+"', '"+windowName+"', 'width="+width+", height="+height+", scrollbars=no, resizable=no, toolbar=no, location=no,menubar=no, directories=no');</script>");

}

public abstract void ShowDialog();

}

public abstract class DialogPage : Page

{

public DialogPage()

{

}

string ControlID

{

get

{

return HttpUtility.UrlDecode(Request["ControlID"]);

}

}

protected void Close(string results)

{

Page.RegisterStartupScript("__close", "<script>window.opener.__processDialogResults('"+ControlID+"',\""+results.Replace("\"", "\\\"")+"\"); window.close();</script>");

}

protected void Close()

{

Page.RegisterStartupScript("__close", "<script>window.close();</script>");

}

}

public class PostBackEventArgs

{

string eventArgument;

public string EventArgument

{

get

{

return eventArgument;

}

set

{

eventArgument=

value;

}

}

}

public delegate void PostBackEventHandler(object sender, PostBackEventArgs e);

public class PostBackHandler : Control, IPostBackEventHandler

{

public PostBackHandler()

{

}

public event PostBackEventHandler PostBack;

#region

IPostBackEventHandler Members

public void RaisePostBackEvent(string eventArgument)

{

PostBackEventArgs e =

new PostBackEventArgs();

e.EventArgument = eventArgument;

if(PostBack != null)

{

PostBack(

this, e);

}

}

#endregion

}

7 Comments

  • After a lot of effort invested, I am unable to get the dialog boxes invoked via DialogWindow to behave as modal dialog boxes. They always behave as modeless windows.



    While I've confirmed the javascript function &quot;MetaBuilders_DialogWindow_ModalFocus&quot; gets called, it appears none of the logic inside the first &quot;if&quot; clause is accessed. I don't know if this is part of the problem or not.



    Also, I see you apparently used a Strong Name key which is not included in the DialogWindow download. Therefore the &quot;metabuilder.com&quot; key reference in the Assembly file has to be removed. I created a new key and compiled successfully, and also created a key for my web app that is referencing DialogWindow, yet this also fails to result in modal dialog behavior.



    Finally, it appears the &quot;dialog&quot; and &quot;modal&quot; features have no applicability to IE6. Is this correct?



    Any help would be much appreciated.



    Curtis Marsden

    mespelbrunn@hotmail.com

  • Why not just put &lt;base target=&quot;_self&quot;&gt; into the &lt;head&gt; section? I can do modal dialogs with asp.net just fine with that simple addition.

  • We use quite a few &quot;dialog&quot; boxes in our asp.net application. One annoyance has always been that when you click the &quot;cancel&quot; button, the page does a refresh. I do not want the refresh for performance reasons because we are doing a long running process.I haven't found the solution to this problem

  • You don't have to do a refresh, just add window.open to the OnClick attribute of your button tag. Any standard DHTML will work regardless of whether you are using ASP.NET.

  • to Anonymous:



    if you havent figured it out already, set your button's 'causes validation' option to 'false' to stop the page from refreshing.

  • hi,



    how do i get started with this? im new with .net and i've a problem with dialogboxes till i ran across this product.



    so, i ran the defaultpage.aspx? and i get an error..





    Parser Error Message: File or assembly name MetaBuilders.WebControls.DialogWindow, or one of its dependencies, was not found.



    what do i have to do???

    thanx for the help guys



  • Your code is clipped off in IE7. Thus, we can't see it all. Is there a way for you to fix this clipped-off issue on this web page?

Comments have been disabled for this content.