Using Ajax in a web application makes a better user experience and if used well, it even improves performance! But it's not all advantages. With the change of a technology, of an approach we need to adjust our way of thinking and the way we apply our solutions for different task.
This might be a bit abstract, so I'll get specific about what I mean. As often met, when you click certain controls on a webpage, you expect to see an outcome, a result or a message as a response to your "request". What Ajax does is ... it replace only certain regions of your webpage. If that region isn't in the visible in the current scroll position of your page in the browser, you won't see the effect.
As an example: you have data in a gridview that spans over several page lengths, with a button at each row which when pressed displays some information about that row. Everything seems logical, except, where should I display the data so that the user won't need to scroll back and forth to see the actual result of the command.
To display a simple message to the user the ModalPopupExtender from the AjaxControlToolkit is perfectly suited. The ModalPopupExtender won't allow the user to click anywhere else except the Panel inside itself, where we could place an Button which hides the modal popup.
My idea is to implement this as a web user control which then is reusable on every page of your website.
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="OKMessageBox.ascx.cs"
Inherits="UserControls_OKMessageBox" %>
<ajax:ModalPopupExtender ID="mpext" runat="server" BackgroundCssClass="modalBackground"
TargetControlID="pnlPopup" PopupControlID="pnlPopup">
</ajax:ModalPopupExtender>
<asp:Panel ID="pnlPopup" runat="server" CssClass="modalPopup" Style="display: none;"
DefaultButton="btnOk">
<table width="100%">
<tr class="topHandle">
<td colspan="2" align="left" runat="server" id="tdCaption">
<asp:Label ID="lblCaption" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td style="width: 60px" valign="middle" align="center">
<asp:Image ID="imgInfo" runat="server" ImageUrl="/Images/Info-48x48.png" />
</td>
<td valign="middle" align="left">
<asp:Label ID="lblMessage" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<asp:Button ID="btnOk" runat="server" Text="Ok" OnClick="btnOk_Click" />
</td>
</tr>
</table>
</asp:Panel>
<script type="text/javascript">
function fnClickOK(sender, e)
{
__doPostBack(sender,e);
}
</script>
The fnClickOk javascript function will force the btnOk button to post back. (to actually achieve this we need to add a little piece of code in the Page_Load method of the user control.
protected void Page_Load(object sender, EventArgs e)
{
btnOk.OnClientClick = String.Format("fnClickOK('{0}','{1}')", btnOk.UniqueID, "");
}
This control works in a similar way to the Windows Forms MessageBox, I.E. you'll need to call a Show() method on the usercontrol with then in term will handle the logic to display the message as a "MessageBox". Here's the code to achieve this:
public void ShowMessage(string Message)
{
lblMessage.Text = Message;
lblCaption.Text = "";
tdCaption.Visible = false;
mpext.Show();
}
public void ShowMessage(string Message, string Caption)
{
lblMessage.Text = Message;
lblCaption.Text = Caption;
tdCaption.Visible = true;
mpext.Show();
}
private void Hide()
{
lblMessage.Text = "";
lblCaption.Text = "";
mpext.Hide();
}
Why are there 2 separate definitions for ShowMessage() I hear you asking, well ... I've created this control to display a simple message with or without a (similar to the windows forms approach).
I've also added an event model so that the event can be handled on any page when the user actually clicks the Ok button.
public void btnOk_Click(object sender, EventArgs e)
{
OnOkButtonPressed(e);
}
public delegate void OkButtonPressedHandler(object sender, EventArgs args);
public event OkButtonPressedHandler OkButtonPressed;
protected virtual void OnOkButtonPressed(EventArgs e)
{
if (OkButtonPressed != null)
OkButtonPressed(btnOk, e);
}
To directly use this user control on any page on your website, you can register the control in your web.config file by adding the following inside the "controls" section of "pages" (in system.web).
<add tagPrefix="uc" src="~/UserControls/OkMessageBox.ascx" tagName="OkMessageBox"/>
Here are some screenshots so you can see how it works.
This is the simple messagebox without any caption! The following example demonstrates a long message text (and also includes a caption.
The server side code needed to run the upper application is:
protected void Page_Load(object sender, EventArgs e)
{
omb.OkButtonPressed +=
new UserControls_OKMessageBox.OkButtonPressedHandler(omb_OkButtonPressed);
}
void omb_OkButtonPressed(object sender, EventArgs args)
{
lblStatus.Text = "Ok button pressed at: " + DateTime.Now.ToLongTimeString();
}
protected void btnFireOkMessage_Click(object sender, EventArgs e)
{
omb.ShowMessage(DateTime.Now.ToLongTimeString());
}
protected void btnFireOkMessageWithCaption_Click(object sender, EventArgs e)
{
omb.ShowMessage("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis congue urna in enim.
Nulla fringilla sem sed odio. In convallis elementum pede. Donec aliquam malesuada
mauris. Morbi facilisis dui quis dolor.", "Message at: " + DateTime.Now.ToShortTimeString());
}
The needed server side markup is the following:
<asp:UpdatePanel ID="upPnlPage" runat="server">
<ContentTemplate>
<asp:Button ID="btnFireOkMessage" runat="server" OnClick="btnFireOkMessage_Click"
Text="Show current server time" />
<asp:Button ID="btnFireOkMessageWithCaption" runat="server"
Text="Show current server date with caption"
onclick="btnFireOkMessageWithCaption_Click" />
<asp:Label ID="lblStatus" runat="server"></asp:Label>
<uc:OkMessageBox ID="omb" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
I hope you had fun reading this post and that is useful for your application. If anybody is interested in a messagebox with some other functionality (like Ok, Cancel with the convenient events which I think would be allot easier to use than the standard ConfirmButtonExtender) I'll gladly write another control for that, but anyway I would like to see what the public reaction is to my idea.
Download the source code and tell me what you think. OkMessageBox-2008.zip (.NET 3.5 SP1), OkMessageBox-2005.zip (.NET 2.0)