ok, so, to continue my previous post on the AjaxControlToolKit(ModalPopup), one of the things I feel might be convenient is the addition of a window frame panel that can be used alongside the Popup or ModalPopup control.
Both the Popup and ModalPopup controls allow you to supply the Cancel button control id, which is normally the button that should close the Popup, usually represented by an 'X' symbol in the title bar of a window frame. We then have the title bar where we can include a title and the body part follows.
While this is easy to construct manually using a set of panels and a button etc, it simply becomes ridiculously cumbersome and repetitive. What would be ideal is a custom panel control with all the "I am a beautiful window frame, simply provide me with body content" type functionality, that we can easily attach to our Popup or ModalPopup and have it render the window frame for us.
Inheriting the panel and adding the extra titlebar container and a close button next to it is as easy as eating cake, so i'm not really going to try and explain the obvious ;p
Also please note that below i have included a working solution that builds onto my previous post with the addition of an elegant window frame to our ModalPopup. Also along with the formatted source code for the control and usage, i've included a screenshot, so you know what to expect. Please, do try running the WebSite solution included in the attachment below as it will provide you a quick live preview + you can use it to further enhance and include additional features while testing your additions to the control :-)
First the screenshot :

/// <summary>
/// Summary description for PopupPanel
/// </summary>
public class PopupPanel : Panel
{
public PopupPanel()
{
}
private Unit titleTopMarginValue;
public Unit TitleTopMargin
{
get
{
if (titleTopMarginValue == Unit.Empty)
titleTopMarginValue = Unit.Parse("6px");
return titleTopMarginValue;
}
set { titleTopMarginValue = value; }
}
private Unit closeButtonTopMarginValue;
public Unit CloseButtonTopMargin
{
get
{
if (closeButtonTopMarginValue == Unit.Empty)
closeButtonTopMarginValue = Unit.Parse("8px");
return closeButtonTopMarginValue;
}
set { closeButtonTopMarginValue = value; }
}
/// <summary>
/// The maximum number of characters to trim the title
/// and display an ellipses. If this property is not set,
/// no trimming will take place.
/// </summary>
private int titleMaxiumCharsValue;
public int TitleMaximumChars
{
get { return titleMaxiumCharsValue; }
set { titleMaxiumCharsValue = value; }
}
private string titleValue;
public string Title
{
get
{
if (!string.IsNullOrEmpty(titleValue))
{
if (titleValue.Length > TitleMaximumChars)
return string.Format("{0}...",
titleValue.Substring(0, TitleMaximumChars));
}
return titleValue;
}
set { titleValue = value; }
}
/// <summary>
/// Text displayed for the close button. If supplied,
/// instead of an image button, a linkbutton with this text
/// is used. Supply text to this property completely makes the
/// CloseButtonImageUrl property useless, since you can't have both.
/// </summary>
private string closeButtonTextValue;
public string CloseButtonText
{
get { return closeButtonTextValue; }
set { closeButtonTextValue = value; }
}
private string closeButtonImageUrlValue;
/// <summary>
/// Image to display in an ImageButton for closing the dialog window
/// </summary>
[Editor(typeof(System.Web.UI.Design.ImageUrlEditor),
typeof(UITypeEditor))]
public string CloseButtonImageUrl
{
get { return closeButtonImageUrlValue; }
set { closeButtonImageUrlValue = value; }
}
private string headerBackgroundImageValue;
[Editor(typeof(System.Web.UI.Design.ImageUrlEditor),
typeof(UITypeEditor))]
public string HeaderBackgroundImage
{
get { return headerBackgroundImageValue; }
set { headerBackgroundImageValue = value; }
}
private Unit headerHeightValue;
public Unit HeaderHeight
{
get
{
if (headerHeightValue == Unit.Empty)
headerHeightValue = Unit.Parse("30px");
return headerHeightValue;
}
set { headerHeightValue = value; }
}
string closeButtonIdValue;
public string CloseButtonId
{
get
{
if (string.IsNullOrEmpty(closeButtonIdValue))
return string.Format("{0}_CloseButton",
this.ClientID);
else
return closeButtonIdValue;
}
set
{
closeButtonIdValue = value;
}
}
private Unit headerWidthValue;
public Unit HeaderWidth
{
get
{
if (headerWidthValue == Unit.Empty)
headerWidthValue = Unit.Parse("80%");
return headerWidthValue;
}
set { headerWidthValue = value; }
}
string dragHandleIdValue;
public string DragHandleId
{
get
{
if (string.IsNullOrEmpty(dragHandleIdValue))
return string.Format("{0}_DragHandle",
this.ClientID);
else
return dragHandleIdValue;
}
set
{
dragHandleIdValue = value;
}
}
private void RenderHeader(HtmlTextWriter writer)
{
if (!string.IsNullOrEmpty(HeaderBackgroundImage))
writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundImage,
ResolveUrl(HeaderBackgroundImage));
writer.AddAttribute(HtmlTextWriterAttribute.Id, DragHandleId);
writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, "move");
writer.AddStyleAttribute(HtmlTextWriterStyle.Height,
HeaderHeight.ToString());
writer.AddStyleAttribute(HtmlTextWriterStyle.Margin, "0px");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.AddStyleAttribute("float", "left");
writer.AddStyleAttribute(HtmlTextWriterStyle.Width, HeaderWidth.ToString());
writer.AddStyleAttribute("text-indent", "5px");
writer.AddStyleAttribute(HtmlTextWriterStyle.Margin,
string.Format("{0} 0 0 0",
TitleTopMargin.ToString()));
writer.RenderBeginTag(HtmlTextWriterTag.Div);
writer.Write(Title);
writer.RenderEndTag();//div - title
writer.AddAttribute(HtmlTextWriterAttribute.Id, CloseButtonId);
writer.AddStyleAttribute("float", "right");
writer.AddStyleAttribute(HtmlTextWriterStyle.Cursor, "pointer");
if (string.IsNullOrEmpty(CloseButtonText))
{
writer.AddAttribute(HtmlTextWriterAttribute.Src,
ResolveUrl(CloseButtonImageUrl));
writer.AddStyleAttribute(HtmlTextWriterStyle.Margin,
string.Format("{0} 0 0 0",
CloseButtonTopMargin.ToString()));
writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "0px");
writer.RenderBeginTag(HtmlTextWriterTag.Img);
}
else
{
writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.Write(CloseButtonText);
}
writer.RenderEndTag();//img or anchor - close button
writer.RenderEndTag();//div - header
}
public override void RenderBeginTag(HtmlTextWriter writer)
{
base.RenderBeginTag(writer);
RenderHeader(writer);
}
}
}first register it in your declarative code :
<%@ Register TagPrefix="Web" Namespace="Demo.Controls" %>
then use as any other control :
<Web:PopupPanel ID="PopupPanelDetailsView"
HeaderBackgroundImage="~/RedHeaderStrip.gif"
Title="Details View" CloseButtonImageUrl="~/close.gif"
Width="300px" runat="server">
</Web:PopupPanel>
<h1>This is my content that will showup in the body area of the window</h1>
</Web:PopupPanel>
Ofcourse, this is a very basic window frame with the most basic functionality. You can further ehance it greatly with the extra features you need. Personally I use a slightly modified version in my own solutions and adding features that i do not need is a waste of time for me. So feel free to add what you need to it :-)