0

I have a dropdownlist control on a page with AutoPostBack set to True. On the initial load of the page I am setting a CSS class on certain ListItems in the DropDownList. The resulting HTML looks like this:

<select id="mySelect">
    <option value="1">First</option>
    <option value="2" selected="selected">Second</option>
    <option value="3" class="favorite">Third</option>
    <option value="4">Fourth</option>
    <option value="5" class="favorite">Fifth</option>
</select>

After postback the ListItems lose their CSS classes. It now looks like this.

<select id="mySelect">
    <option value="1">First</option>
    <option value="2">Second</option>
    <option value="3">Third</option>
    <option value="4">Fourth</option>
    <option value="5" selected="selected">Fifth</option>
</select>

Is there any way that the dropdownlist will remember the CSS classes on individual ListItems after a postback or will I need to somehow set the classes myself after postback?

Here is the code that adds the CSS to the dropdownlist. It is run on PageLoad but not run on PostBack.

foreach(MyItem _myItem in MyItemList)
{
   ListItem _listItem = new ListItem();
   _listItem.Value = _myItem.ID.ToString();
   _listItem.Text = _myItem.Title;
   if(_myItem.IsFavorite)
   {
      _list.Attributes["class"] = "favorite";
   }
   ddlMyDropDown.Items.Add(_listItem);
}

Corey

Corey Burnett
  • 7,312
  • 10
  • 56
  • 93

2 Answers2

1

EDIT:

This works for me. Try something like this

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            LoadData();
        } 

        LoadStyle();
    }

    private void LoadData()
    {
        DropDownList1.Items.AddRange(Enumerable.Range(0, 10).Select(x => new ListItem(x.ToString())).ToArray());
    }

    private void LoadStyle()
    {
        foreach (ListItem item in DropDownList1.Items)
        {
            if (int.Parse(item.Value) % 2 == 0)
            {
                item.Attributes.Add("class", "test");
            }
        }
    }
Bala R
  • 107,317
  • 23
  • 199
  • 210
  • But if I do that won't I lose the selected item in the dropdownlist? Will I have to manually set the selected item? – Corey Burnett Mar 22 '11 at 19:15
  • @Corey is viewstate enabled ? – Bala R Mar 22 '11 at 19:19
  • Yes, I have other controls on the page that work as expected. They maintain their values through a postback. In fact, this dropdownlist does maintain the "data" after a postback - it just loses the CSS classes. – Corey Burnett Mar 22 '11 at 19:21
  • Seperate out adding items and adding css. because of viewstate, data persists between postback but css does not. so you need to add items just once but add css on every postback. – Bala R Mar 22 '11 at 19:32
0

So your problem here is one of state management, and for the most part its your responsibility to manage the state of the items on your page. Consider that this one page may be rendered 100 times in a minute (to 100 different browsers) and each one could have a different state. The server can't keep track of all these different instances and states, you have to do that.

There are two ways to deal with this, the simplest is similar to what @StackOverflowException stated, just make sure that you determine and set your state every time your page is created. This is easier, but definitely not scalable, especially if that involves a lot of database work and other stuff.

The better solution is to create some properties of your own that store things in the pages ViewState. There are a lot of ways to do this, but here's just a quick sample:

protected override OnPageLoad(EventArgs e)
{
    myListBox.Items.AddRange(myListItems);
}

protected IEnumberable<ListItems> myListItems 
{
    get 
    { 
        IEnumberable<ListItems> items = (IEnumerable<ListItems>)ViewState["myListItems"]; 

        // Build the list if we can't get it out of the viewstate
        if(items = null) 
        {
            items = BuildListItems();
            ViewState["myListItems"] = items;
        }

        return _items;          
    }

    set { ViewState["myListItems"] = value; }
}

This would take a bit longer on the initial page view, but during postbacks would (theoretically) be faster because it can get the list out of the page's view state without reconstructing it (basically deserializing it).

The drawback to this method is that your view state, which is output to the browser, can get very large if you put too much data in it.

CodingGorilla
  • 19,612
  • 4
  • 45
  • 65