For DropDownList we can bind two fields one is for DropDownList DataTextField and another is for DropDownList DataValueField. If we want to bind extra field, we can bind that extra field to DropDownList ListItem attribute. By adding attributes we can find any number fields.
But in Asp.Net only DataTextField and DataValueField fields are stored through ViewState, attributes will not save in ViewState. Because of this on postback we will have only DataTextField, DataValueFields and attribute values are lost on post back.
If you want to store DropDownList ListItem attributes also using ViewState, we have to override SaveViewState() and LoadViewState() methods by deriving DropDownList class. By overriding the SaveViewState() method wehave to save attribute values in ViewState and By overriding the LoadViewState() method we have to re-bind the attribute values to DropDownList as shown below.
DropDownListAttributes.cs
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DropDownListItemAttributes
{
///<summary>
/// inheriting the DropDownList to save attributes
///</summary>
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class DropDownListAttributes : DropDownList
{
///<summary>
/// By using this method save the attributes data in view state
///</summary>
///<returns></returns>
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
protected override object SaveViewState()
{
object[] allStates = new object[this.Items.Count + 1];
object baseState = base.SaveViewState();
allStates[0] = baseState;
Int32 i = 1;
foreach (ListItem li in this.Items)
{
Int32 j = 0;
string[][] attributes = new string[li.Attributes.Count][];
foreach (string attribute in li.Attributes.Keys)
attributes[j++] = new string[] { attribute, li.Attributes[attribute] };
allStates[i++] = attributes;
}
return allStates;
}
///<summary>
/// /// By using this method Load the attributes data from view state
///</summary>
///<param name="savedState"></param>
protected override void LoadViewState(object savedState)
{
if (savedState != null)
{
object[] myState = (object[])savedState;
if (myState[0] != null)
base.LoadViewState(myState[0]);
Int32 i = 1;
foreach (ListItem li in this.Items)
foreach (string[] attribute in (string[][])myState[i++])
li.Attributes[attribute[0]] = attribute[1];
}
}
}
}
As shown above we are deriving the new DropDownList by deriving base DropDownList Control to save attributes data in ViewState and load Attributes data from ViewState.
Now We will test our new DropDownList control by adding attributes.
LoadControls.cs
using System.Data;
using System.Web.UI.WebControls;
public class LoadControls : System.Web.UI.Page
{
///<summary>
/// this method binds the data to DropDownListAttributes DropDownList
///</summary>
///<param name="ddl1"></param>
public void BindDDL1(DropDownListItemAttributes.DropDownListAttributes ddl1)
{
DataSet ds = new DataSet();
ds.ReadXml(Server.MapPath("Employee.xml"));
ddl1.DataSource = ds.Tables[0];
ddl1.DataTextField = "Name";
ddl1.DataValueField = "Id";
ddl1.DataBind();
foreach (ListItem item in ddl1.Items)
item.Attributes.Add("title", item.Text);
foreach (ListItem item in ddl1.Items)
item.Attributes.Add("ParamCode", item.Value);
}
///<summary>
/// this method binds the data to normal DropDownList
///</summary>
///<param name="ddl2"></param>
public void BindDDL2(DropDownList ddl2)
{
DataSet ds = new DataSet();
ds.ReadXml(Server.MapPath("Employee.xml"));
ddl2.DataSource = ds.Tables[0];
ddl2.DataTextField = "Name";
ddl2.DataValueField = "Id";
ddl2.DataBind();
foreach (ListItem item in ddl2.Items)
item.Attributes.Add("title", item.Text);
}
}
As shown above, in LoadControls.cs class we have to methods. BindDDL1() method binds the data to our new DropDownList of type DropDownListAttributes and BindDDL2() method binds the data to normal drop down list. Both methods add the title attribute for each ListItem to display the tool tip.
Call these methods from your asp.net page to test. Add two DropDownLists in e is of type DropDownListAttributes and another is of normal DropDownList type as shown below.
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register TagPrefix="asp" Namespace="DropDownListItemAttributes"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Adding Attributes and Keeping DropDownList ListItems Attributes on Postback in ASP.NET</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lbl1" runat="server" Text="This is not Postback"></asp:Label><br /><br />
<asp:DropDownListAttributes ID="ddl1" runat="server"></asp:DropDownListAttributes>
<asp:DropDownList ID="ddl2" runat="server"></asp:DropDownList>
<br /><br />
<asp:Button ID="btn1" runat="server" OnClick="btn1_Click" Text="Click" />
</div>
</form>
</body>
</html>
Default.aspx.cs
using System;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
BindDDL();
}
private void BindDDL()
{
LoadControls oLoad = new LoadControls();
oLoad.BindDDL1(ddl1);
oLoad.BindDDL2(ddl2);
}
protected void btn1_Click(object sender, EventArgs e)
{
lbl1.Text = "This is on Postback";
}
}
When you run the application, on page load both drop down lists displays title attributes(you can find tool tip by placing the mouse over on list item). After button click only first dropdownlist of type DropDownListAttributes displaying the title attribute because we are saving the attributes in ViewState and re loading again for this type.