My general rule of thumb (which I actually read on some other site or blog, or maybe in a book or on the msdn?) is that if you plan on using a control once or twice, use a web user control. If, however, you want to use it all over your program, you should invest the time to make it a server control. They are much easier to use in the program (in the long-term), since they allow you to drag and drop them from the toolbox and you can pass them between programs easier as a DLL instead of a .ascx file.
Server controls were one of those things that took me a while to figure out, so I thought I’d start with a relatively easy one to put together. I’m using the AJAX Control Toolkit (available for download from www.asp.net) to put together a drag & drop control that is a modal confirm dialog.
To start off with, here is an example of the results. (Note: the CSS is totally up to you. Mine is just thrown together, so that’s why it doesn’t look very fancy :) )
And here’s what the design time code looks like in the page:
<asp:LinkButton ID="DeleteButton" runat="server" EnableViewState="false" CommandName="Delete"
Text="Delete Note" />
<myCustomControl:ModalConfirmDialog runat="server" ID="ConfirmDelete1" ConfirmButtonText="Yes, delete note"
CancelButtonText="No, cancel" ConfirmText="Are you sure you want to delete this note? Note: this cannot be undone."
TargetControlID="DeleteButton" />
So what all is going on here? Let’s start at the beginning.
Step 1: Create a new class.
Feel free to name it whatever you like. I went with ModalConfirmDialog.cs. Set the class to be public, and name it. I went with “myModalConfirmDialog”. This is going to be a composite control, since it will simply piece together several controls into one wrapped up package that is easy to set properties.
At the top, I imported the required namespaces to do the work we’ll be doing in the class. I already have the AjaxControlToolkit in my project, so I can just import it by name.
So far you should have something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AjaxControlToolkit;
using System.ComponentModel;
namespace myCompany.CustomControls
{
public class myModalConfirmDialog : CompositeControl
{
}
}
Step 2: Create all the controls we’ll be using inside the CompositeControl.
I first like to start out with all the controls that will be inside the control. There are a lot for this control to work, but I have explanations above each one, so you should be able to follow along:
// The label that shows the confirmation text
protected Label _MessageLabel = new Label();
// The confirm button extender from the AJAX control toolkit.
// By default, it uses an annoying Ok/Cancel javascript popup
protected ConfirmButtonExtender _ConfirmExtender;
// The modal extender that we'll be using to instead pop up a nice in-window confirm dialog
protected ModalPopupExtender _ModalExtender;
// The panel that will be popping up
protected Panel _ModalPanel;
// The two buttons to confirm/cancel the action
protected LinkButton _ConfirmButton = new LinkButton();
protected LinkButton _CancelButton = new LinkButton();
Step 3: Create the public properties to get/set
You can make the control as customizable as you want, but I like to keep things simple, since I want the control to look about the same everywhere I use it. The four properties I’ll expose as public are:
1. The TargetControlID – This is necessary for the ConfirmExtender to work. It’s the button that the control will react to, when clicked.
2. ConfirmText – This is the text inside the panel that asks the user if they want to continue. (e.g. “Do you want to continue?”)
3. ConfirmButtonText – The text for the Confirm Button inside the modal panel. (e.g. “Ok” or “Continue”)
4. CancelButtonText – The text for the Cancel Button inside the modal panel. (e.g. “Cancel” or “Do not Continue”)
In each of these, I call EnsureChildControls() to make sure that it has (as the name suggests) child controls. Also, for some of them, I add the optional [Description(“”)] attribute, for added design time fun.
Here is the code for each of the 4. It should all be pretty self explanatory.
1.
[Description("This is the target control ID of the button that is to be confirmed")]
public string TargetControlID
{
get
{
EnsureChildControls();
return _ConfirmExtender.TargetControlID;
}
set
{
EnsureChildControls();
_ConfirmExtender.TargetControlID = value;
_ModalExtender.TargetControlID = value;
}
}
2.
[Description("This is the confirm text that is displayed inside the modal popup.")]
public string ConfirmText
{
get
{
EnsureChildControls();
return _MessageLabel.Text;
}
set
{
EnsureChildControls();
_MessageLabel.Text = value;
}
}
3.
public string ConfirmButtonText
{
get
{
EnsureChildControls();
return _ConfirmButton.Text;
}
set
{
EnsureChildControls();
_ConfirmButton.Text = value;
}
}
4.
public string CancelButtonText
{
get
{
EnsureChildControls();
return _CancelButton.Text;
}
set
{
EnsureChildControls();
_CancelButton.Text = value;
}
}
Step 4: Write CreateChildControls() Method
If you start writing protected override void you’ll notice CreateChildControls() pop up, like below:
This method is what does all the work in the control. It initializes all the backing controls and sets the properties that are required for them to work. I won’t go into too much detail for their properties. They are self-explanatory and nothing new.
The important part to pay attention to (which is marked in the code below as comments) is where I add the control(s) to the composite control class. Here is the method:
protected override void CreateChildControls()
{
base.CreateChildControls();
// create all the controls
_ModalPanel = new Panel
{
ID = "ConfirmPanel",
CssClass = "modalPopup",
};
// This is required so you don't get a "flash" on the screen of the panel:
_ModalPanel.Style.Add(HtmlTextWriterStyle.Display, "none");
_ConfirmButton = new LinkButton
{
ID = "ConfirmButton",
Text = ConfirmButtonText,
CssClass = "ModalButton",
};
_CancelButton = new LinkButton
{
ID = "CancelButton",
Text = CancelButtonText,
CssClass = "ModalButton",
};
_MessageLabel = new Label
{
CssClass = "warning",
ID = "MessageLabel",
Text = ConfirmText,
};
// Add several controls to the Panel
_ModalPanel.Controls.Add(_MessageLabel);
_ModalPanel.Controls.Add(new Literal { Text = "<br /> <br />" });
_ModalPanel.Controls.Add(_ConfirmButton);
_ModalPanel.Controls.Add(_CancelButton);
// ***** //
// Add the Panel to the CompositeControl
this.Controls.Add(_ModalPanel);
_ConfirmExtender = new ConfirmButtonExtender
{
DisplayModalPopupID = "ModalExtender",
ID = "ConfirmExtender1",
};
_ModalExtender = new ModalPopupExtender
{
BackgroundCssClass = "modalBackground",
OkControlID = "ConfirmButton",
CancelControlID = "CancelButton",
PopupControlID = "ConfirmPanel",
ID = "ModalExtender",
};
// Add the two AJAX controls to the Composite Control (outside the panel)
this.Controls.Add(_ConfirmExtender);
this.Controls.Add(_ModalExtender);
// Indicate that the childControlsCreated are true, now that all the controls are created.
this.ChildControlsCreated = true;
}
Again, a lot of the properties are default things, such as the CSS that comes w/ the Ajax control toolkit samples, and names, etc.
Update:
I realized I missed one important aspect for this to work, especially if you are using a class library to make the custom control. You’ll want to register your assembly inside your web.config, so that you can access it inside your aspx pages using the <tagprefix:name> method. After I added a reference to my class library that contains the control (named CustomControls), which has a namespace of Company.Controls, I added this line to my web.config in the <Pages> <controls> section:
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add namespace="Company.Controls" assembly="CustomControls" tagPrefix="myCustomControl"/>
</controls>
</pages>
Summary:
So that’s that. You can compile it and then drag/drop it into your project, and attach it to a control that you want to interrupt with a confirm dialog. And this also serves as an introduction to CompositeControls, which are basically the server control equivalents to web user controls (.ascx).
Cheers!
samer paul
Print | posted on Saturday, August 01, 2009 10:19 PM