posted 6/22/2011 by Raghav Khunger
I was working with custom control today where I needed to catch the postback event of DropDownlist in DataBound Control. But I noticed that ASP.NET DropDownList doesn't have the CommandName and CommandArgument properties. Now if my DropDownList does the postback then how will my DataBound control's ItemCommand will get called? The solution was to make my own Custom DropDownList. In this blog I will share the code of that CustomControl.
using System; using System.Drawing; using System.Security.Permissions; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal), ToolboxBitmap(typeof(DropDownList)), ToolboxData("<{0}:MyDropDownList runat=\"server\" />")] public class MyDropDownList : DropDownList { #region Events /// <summary> /// Object which acts as key for the Command event /// </summary> private static readonly object EventCommand = new object(); /// <summary> /// Occurs when [command]. /// </summary> public event CommandEventHandler Command { add { Events.AddHandler(EventCommand, value); } remove { Events.RemoveHandler(EventCommand, value); } } /// <summary> /// Raises the <see cref="E:Command"/> event. /// </summary> /// <param name="eventArgs">The <see cref="System.Web.UI.WebControls.CommandEventArgs"/> instance containing ///the event data.</param> protected virtual void OnCommand(CommandEventArgs eventArgs) { //Command event can be attached for this control from outside //and hence that attached method needs to be executed var commandEventHandler = Events[EventCommand] as CommandEventHandler; if (commandEventHandler != null) { commandEventHandler(this, eventArgs); } //Bubble up this event so that the base control ItemCommand event can be fired base.RaiseBubbleEvent(this, eventArgs); } #endregion #region Properties /// <summary> /// Gets or sets the name of the command. /// </summary> /// <value>The name of the command.</value> public string CommandName { get { string commandName = ViewState["CommandName"] as string; return commandName ?? ""; } set { ViewState["CommandName"] = value; } } /// <summary> /// Gets or sets the command argument. /// </summary> /// <value>The command argument.</value> public string CommandArgument { get { string commandArgument = ViewState["CommandArgument"] as string; return commandArgument ?? ""; } set { ViewState["CommandArgument"] = value; } } #endregion #region Override the default implementation of SelectedIndexChanged /// <summary> /// Raises the <see cref="E:System.Web.UI.WebControls.ListControl.SelectedIndexChanged"/> event. This allows you to ///provide a custom handler for the event. /// </summary> /// <param name="e">A <see cref="T:System.EventArgs"/> that contains the event data.</param> protected override void OnSelectedIndexChanged(EventArgs e) { base.OnSelectedIndexChanged(e); if (AutoPostBack) { var commandEventArgs = new CommandEventArgs(this.CommandName, this.CommandArgument); OnCommand(commandEventArgs); } } #endregion }//end class
As you are seeing "OnSelectedIndexChanged" method has been overridden and on PostBack the OnCommand method of this control is called. Then in "OnCommand" method base.RaiseBubbleEvent(this, eventArgs); i.e it will bubble the OnCommand to ItemCommand of the DataBoundControl with the information of CommandName and CommandArgument of MyDropDownList control.Now let's see how can we use this in a repeater control(custom control in my case).
ASPX code
<%@ Page Language="C#" AutoEventWireup="true" EnableEventValidation="false" %> <%@ Register TagPrefix="MyControls" Namespace="MyControls" Assembly="WebApplication2" %> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> </head> <body> <form id="HtmlForm" runat="server"> <div> <MyControls:MyRepeater ID="MyRepeater1" runat="server"> <HeaderTemplate> <MyControls:MyDropDownList ID="MyDropDownList" runat="server" AutoPostBack="true"> <asp:ListItem Value="1">Item1</asp:ListItem> <asp:ListItem Value="2">Item2</asp:ListItem> </MyControls:MyDropDownList> </HeaderTemplate> <ItemTemplate> </ItemTemplate> </MyControls:MyRepeater> </div> </form> </body> </html>
The code of MyRepeater is as following:
using System; using System.Collections.Generic; using System.Web.UI.WebControls; namespace MyControls { public class MyRepeater : Repeater{ protected override void OnLoad(EventArgs e) { ItemDataBound += MyRepeater_ItemDataBound; ItemCommand += MyRepeater_ItemCommand; if (!Page.IsPostBack) { //Dummy binding of repeater var list = new List<int> {1, 2}; this.DataSource = list; this.DataBind(); } } protected void MyRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ListItemType.Header) { var myDropDownList = (MyDropDownList)e.Item.FindControl("MyDropDownList"); myDropDownList.CommandName = "MyDropDownListCommand"; } } protected void MyRepeater_ItemCommand(object source, RepeaterCommandEventArgs e) { if (e.CommandName == "MyDropDownListCommand") { //Do your work } } } }
Now when the DropDownlist selected index is changed, its CommandName and CommandArgument is passed to repeater's ItemCommand event. Hope the above info will help you.
What kind of email newsletter would you prefer to receive from CodeAsp.Net?18