3

I am attempting to DataBind an asp:DropDownList with a Collections.Generic.List of System.Web.UI.WebControls.ListItems. The DataBind() is throwing this error.

System.ArgumentOutOfRangeException: 'ddlPlatinumOptions' has a SelectedValue which is invalid because it does not exist in the list of items.

.ascx

<asp:DropDownList ID="ddlPlatinumOptions" runat="server" AutoPostBack="true" width="100%"></asp:DropDownList>

.ascx.cs

public void BindPlatinumOptions()
{
    ddlPlatinumOptions.DataTextField = "Text";
    ddlPlatinumOptions.DataValueField = "Value";
    ddlPlatinumOptions.DataSource = _platinumOptions;
    ddlPlatinumOptions.DataBind(); // Throwing Error
}

presenter

MattressProtectionInfo standard = RF_ProtectionPlan.GetMattressPlanInfo(MattressId, false);
MattressProtectionInfo premium = RF_ProtectionPlan.GetMattressPlanInfo(MattressId, true);
List<ListItem> plans = new List<ListItem>();                  
if (standard != null)
{
    plans.Add(new ListItem(standard.Price.ToString("C") + " - Standard 5-Year Platinum Protection", standard.ProductID.ToString()));
}
if (premium != null)
{
    plans.Add(new ListItem(premium.Price.ToString("C") + " - Premium 5-Year Platinum Protection", premium.ProductID.ToString()));
}

_view.PlatinumOptions = plans;
_view.BindPlatinumOptions();

Data Example

  • Value = "21696" Text = "$99.95 - Standard 5-Year Platinum Protection"
  • Value = "21702" Text = "$119.95 - Premium 5-Year Platinum Protection"

Thing I have tried

  • Nulling datasource and Databinding before my data to clear out anything (broke on dataBind as well)
  • relocating position of DataTextField and DataValueField (waste of time - no change)
  • declaring a selected index of 0 before the databind
  • ddlPlatinumOptions.Items.Clear();
  • ddlPlatinumOptions.ClearSelection();

I am grabbing at straws. It appears as if the databind is trying to select something inside of the dropdownlist that isn't there.

Is there an error in my code I'm not seeing? Any Ideas?

Ryan O'Hara
  • 311
  • 1
  • 10
  • 2
    instead of Binding ..why don't you add the items to the `DropDownList` directly.. if that's not an option then take a look here this should help solve your issue `Ryan O'Hara` [How to populate DropDownList using List](http://stackoverflow.com/questions/4864880/how-to-populate-a-dropdownlist-using-a-listlistitem) – MethodMan Dec 04 '14 at 16:03
  • I am already building my ListItem like there are in that answer. The problem appears to be with-in the asp.net DropDownList.DataBind(). It appears to be trying to select a value that is not bound yet? If I wrap the BindPlatinumOptions() in a try catch and swallow the error the ListItem are still rendered to the page and work fine. I want to know why it is throwing this error, but I can't seam to find the source code for the asp.net Databind method for asp 3.5 – Ryan O'Hara Dec 04 '14 at 18:48
  • well what event is it being triggered from.. is this happening on `Load` or during a PostBack.. also I think that you can bind directly as I have mentioned without using a List for example where are you getting the data from or reading it from in regards to loading the ddl..? I think there is a simpler approach – MethodMan Dec 04 '14 at 18:52
  • I am binding it on ViewLoad, I am building the list in the presenter not hard coding them on the view. – Ryan O'Hara Dec 04 '14 at 18:59
  • I do not think that you are understanding anyway checkout that link that was posted in my previous / earlier comment you are obviously doing something wrong and I was not talking about hard coding btw – MethodMan Dec 04 '14 at 19:00
  • Thank you, but I do understand. Setting the DataTextField and DataValueField in the code behind or markup will not make a difference as long as in the code behind, it is set before the DataBind() method is called. We use an MVP architecture, so all logic processing is done in the presenter. We also like to keep as much in code as possible so we use .DataTextField, .DataValueField, and .DataBind() in the code behind throughout our site. – Ryan O'Hara Dec 04 '14 at 19:52

2 Answers2

7

After facing this problem, too, I debugged the ASP.NET source code and found a flaw(?) in the ASP.NET source code (and, hence, the solution to our problem):

Internally, System.Web.UI.WebControls.Listcontrol caches the most recently used SelectedValue. So when a data binding occurs (which natively clears the SelectedValue property) after the SelectedValue has already been set from Request.Form[], the data binding operation tries to find and pre-select the previously cached item. Unfortunately it throws an exception when the cached value isn't found in the new DataSource list instead of silently leaving the current SelectedValue null value alone.

I guess they did that because when using ViewState and data source objects for data binding, the later data bind operation would remove the SelectedValue obtained by Request.Form[].

So, whenever you perform more than one data binding operation on a ListControl within a page lifecycle and when the data sources differ, then this exception occurs.


Here's the ASP.NET code synopsis:

    public virtual string SelectedValue
    {
        set
        {
            if (Items.Count != 0)
            {
                // at design time, a binding on SelectedValue will be reset to the default value on OnComponentChanged
                if (value == null || (DesignMode && value.Length == 0))
                {
                    ClearSelection();
                    return;
                    // !!! cachedSelectedValue is not getting reset here !!!
                }

            ...

            // always save the selectedvalue
            // for later databinding in case we have viewstate items or static items
            cachedSelectedValue = value;
        }
    }


And here's the solution:

Instead of:

    dropDownBox.DataSource = ...;
    dropDownBox.DataBind();

Write this:

    dropDownBox.Items.Clear();
    dropDownBox.SelectedValue = null;
    dropDownBox.DataSource = ...;
    dropDownBox.DataBind();


(The dropDownBox.Items.Clear(); operation is only required if dropDownBox.Items isn't already empty.)

AxD
  • 2,714
  • 3
  • 31
  • 53
2

Well, it's an out of range exception.. Are you setting the SelectedIndex to a default value at any point before you are binding to the DropDownList?

Sean
  • 46
  • 3