ListItems attributes in a DropDownList are lost on postback?
I had the same problem and wanted to contribute this resource where the author created an inherited ListItem Consumer to persist attributes to ViewState. Hopefully it will save someone the time I wasted until I stumbled on it.
protected override object SaveViewState(){ // create object array for Item count + 1 object[] allStates = new object[this.Items.Count + 1]; // the +1 is to hold the base info object baseState = base.SaveViewState(); allStates[0] = baseState; Int32 i = 1; // now loop through and save each Style attribute for the List 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;}protected override void LoadViewState(object savedState){ if (savedState != null) { object[] myState = (object[])savedState; // restore base first if (myState[0] != null) base.LoadViewState(myState[0]); Int32 i = 1; foreach (ListItem li in this.Items) { // loop through and restore each style attribute foreach (string[] attribute in (string[][])myState[i++]) { li.Attributes[attribute[0]] = attribute[1]; } } }}
Thanks, Laramie. Just what I was looking for. It keeps the attributes perfectly.
To expand, below is a class file I created using Laramie's code to create a dropdownlist in VS2008. Create the class in the App_Code folder. After you create the class, use this line on the aspx page to register it:
<%@ Register TagPrefix="aspNewControls" Namespace="NewControls"%>
You can then put the control on your webform with this
<aspNewControls:NewDropDownList ID="ddlWhatever" runat="server"> </aspNewControls:NewDropDownList>
Ok, here's the class...
using System;using System.Collections.Generic;using System.ComponentModel;using System.Security.Permissions;using System.Linq;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace NewControls{ [DefaultProperty("Text")] [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")] public class NewDropDownList : DropDownList { [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)] protected override object SaveViewState() { // create object array for Item count + 1 object[] allStates = new object[this.Items.Count + 1]; // the +1 is to hold the base info object baseState = base.SaveViewState(); allStates[0] = baseState; Int32 i = 1; // now loop through and save each Style attribute for the List 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; } protected override void LoadViewState(object savedState) { if (savedState != null) { object[] myState = (object[])savedState; // restore base first if (myState[0] != null) base.LoadViewState(myState[0]); Int32 i = 1; foreach (ListItem li in this.Items) { // loop through and restore each style attribute foreach (string[] attribute in (string[][])myState[i++]) { li.Attributes[attribute[0]] = attribute[1]; } } } } }}
Simple solution is to add the tooltip attributes in the pre-render
event of the dropdown. Any changes to the state should be done at pre-render
event.
sample code :
protected void drpBrand_PreRender(object sender, EventArgs e) { foreach (ListItem _listItem in drpBrand.Items) { _listItem.Attributes.Add("title", _listItem.Text); } drpBrand.Attributes.Add("onmouseover", "this.title=this.options[this.selectedIndex].title"); }