locked
DropDownList has a SelectedValue which is invalid because it does not exist in the list of items. RRS feed

  • Question

  • User260076833 posted

    Hello,

    I am using a lot of ListViews that show data in the ItemTemplate. In the ItemTemplate, most of the attributes are displayed with asp:Label control.
    For example, there may be a label that displays the name of a person. So far, so good.

    Now, when the user then clicks on "Edit", the ListViews switches to edit mode and displays the EditItemTemplate. Then, the attributes are displayed with editable controls instead of labels.
    For example, the field that holds the person, which was displayed with a label in the ItemTemplate, is now displayed with a DropDownList. When the DropDownList appears, the person that is stored in the data item is selected by default.

    Here comes my problem: Sometimes the DropDownList doesn't contain the entry that is stored in the data item. Then I get this error:

    [ArgumentOutOfRangeException: 'lst_Personal' has a SelectedValue which is invalid because it does not exist in the list of items.
    Parameter name: value]
     

    I understand why I get this error.
    What I would like to do is the following:

    Hook into some event that is fired just before or after the DropDownList is filled, but before the ArgumentOutOfRangeException is thrown, so that I can check if the value is missing and set its SelectedValue to null then.

    But I cannot find the right event to hook in. I think that the ListView's ItemEditing event would be a good place, but I don't know how to do the following tasks there:

    • Find out what "would" be the SelectedValue of the DropDownList, i. e. which person should be selected.
      Inside the event, the SelectedValue attribute is empty.
      How can I get this information inside this event?

    • Check if this value is missing in the list.

    • If it's missing, set the SelectedValue to null.

    I post my code below. The attribute which is causing the error is "personal".

    Any help is welcome!

    Thanks
    Magnus

    RolleForm.aspx:

    <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="RolleForm.ascx.cs" Inherits="Governix.div.psv.cmp.RolleForm" %>
    
    
    <asp:SqlDataSource ID="src_Rolle" runat="server" ConnectionString='<%$ ConnectionStrings:StMGP %>' OldValuesParameterFormatString="{0}_old"
        SelectCommand="SELECT * FROM [psv_v_verteilung] WHERE ([organisation] = @organisation AND einheit=@einheit) ORDER BY typ,personal_anzeige;"
        InsertCommand="INSERT INTO psv_verteilung (organisation,einheit,personal,typ) VALUES (@organisation,@einheit,@personal,@typ);"
        UpdateCommand="UPDATE psv_verteilung SET typ=@typ,personal=@personal WHERE (organisation=@organisation AND einheit=@einheit AND personal=@personal_old);"
        DeleteCommand="DELETE FROM psv_verteilung WHERE (organisation=@organisation AND einheit=@einheit AND personal=@personal);">
    
        <SelectParameters>
            <asp:SessionParameter Name="organisation" SessionField="ctx_Organisation" DefaultValue="1"></asp:SessionParameter>
            <asp:SessionParameter Name="einheit" SessionField="ctx_Einheit" DefaultValue=""></asp:SessionParameter>
        </SelectParameters>
    
        <InsertParameters>
            <asp:Parameter Name="organisation"></asp:Parameter>
            <asp:Parameter Name="einheit"></asp:Parameter>
            <asp:Parameter Name="typ"></asp:Parameter>
            <asp:Parameter Name="personal"></asp:Parameter>
        </InsertParameters>
    
        <UpdateParameters>
            <asp:Parameter Name="organisation"></asp:Parameter>
            <asp:Parameter Name="einheit"></asp:Parameter>
            <asp:Parameter Name="typ"></asp:Parameter>
            <asp:Parameter Name="personal"></asp:Parameter>
            <asp:Parameter Name="personal_old"></asp:Parameter>
        </UpdateParameters>
    
        <DeleteParameters>
            <asp:Parameter Name="organisation"></asp:Parameter>
            <asp:Parameter Name="einheit"></asp:Parameter>
            <asp:Parameter Name="personal"></asp:Parameter>
        </DeleteParameters>
    </asp:SqlDataSource>
    
    <asp:SqlDataSource ID="src_Typ" runat="server" ConnectionString='<%$ ConnectionStrings:StMGP %>' SelectCommand="SELECT sym,name FROM [psv_verteilung_rolle_typ] ORDER BY name;"></asp:SqlDataSource>
    
    <asp:SqlDataSource ID="src_Personal" runat="server" ConnectionString='<%$ ConnectionStrings:StMGP %>' SelectCommand="SELECT idx,anzeige_name FROM [psv_v_personal] WHERE (organisation=@org AND aktiv=1) ORDER BY anzeige_name;">
        <SelectParameters>
            <asp:SessionParameter SessionField="ctx_Organisation" DefaultValue="1" Name="org"></asp:SessionParameter>
        </SelectParameters>
    </asp:SqlDataSource>
    
    <asp:HiddenField ID="fld_Organisation" runat="server"/>
    <asp:HiddenField ID="fld_Einheit" runat="server"/>
    
    
    <table style="width: 100%">
        <tr>
            <td>
                <asp:ListView ID="lvw_Rolle" runat="server" DataSourceID="src_Rolle" DataKeyNames="organisation,einheit,personal" InsertItemPosition="LastItem"
                    GroupItemCount="1"
                    OnDataBound="lvw_Rolle_DataBound"
                    OnItemDataBound="lvw_Rolle_ItemDataBound"
                    OnItemCommand="lvw_Rolle_ItemCommand"
                    OnItemInserting="lvw_Rolle_ItemInserting" OnItemInserted="lvw_Rolle_ItemInserted"
                    OnItemEditing="lvw_Rolle_ItemEditing"
                    OnItemUpdating="lvw_Rolle_ItemUpdating" OnItemUpdated="lvw_Rolle_ItemUpdated"
                    OnItemDeleting="lvw_Rolle_ItemDeleting" OnItemDeleted="lvw_Rolle_ItemDeleted"
                    >
    
                    <LayoutTemplate>
                        <table runat="server" id="itemPlaceholderContainer" class="SimpleTable">
                            <thead>
                                <tr runat="server" id="groupPlaceholder111">
                                    <th align="left"></th>
                                    <th align="left">Funktion</th>
                                    <th align="left">Personal</th>
                                    <th align="left">
                                        <asp:Label runat="server" ID="lbl_Action" Visible='<%# showActions %>'>Aktion</asp:Label>
                                        <!-- doesnt work, workaround in Page_Load -->
                                    </th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr runat="server" id="groupPlaceholder" />
                            </tbody>
                        </table>
                    </LayoutTemplate>
    
                    <GroupTemplate>
                        <tr runat="server" id="rec">
                            <td runat="server" id="itemPlaceholder" />
                        </tr>
                    </GroupTemplate>
    
                    <ItemTemplate>
                        <%-- 
                        <asp:HiddenField ID="fld_Personal" runat="server" Value='<%# Bind("personal") %>' />
                        --%>
                        <td align="left" style="" runat="server" id="col_sel">
                            <asp:Label ID="Label2" runat="server" Text="&#10038;" Visible="false"></asp:Label>
                        </td>
                        <td align="left" style="" runat="server">
                            <asp:Label ID="lbl_Name" runat="server" Text='<%# Eval("typ_name") %>' />
                        </td>
                        <td align="left" style="" runat="server">
                            <asp:Label ID="Label1" runat="server" Text='<%# Eval("personal_Anzeige") %>' />
                        </td>
                        <td>
                            <asp:Panel runat="server" Visible='<%# showActions %>'>
                                <asp:LinkButton ID="btn_Edit" runat="server" CausesValidation="False" CommandName="Edit" Text="Ändern"></asp:LinkButton>
                                <asp:LinkButton ID="btn_Delete" runat="server" CausesValidation="False" CommandName="Delete" Text="Löschen" CommandArgument='<%# Eval("personal") %>'></asp:LinkButton>
                            </asp:Panel>
                        </td>
                    </ItemTemplate>
    
                    <ItemSeparatorTemplate>
                        <!--
                <td runat="server" style="border-right: 1px solid #00C0C0">&nbsp;</td>
                -->
                    </ItemSeparatorTemplate>
    
                    <InsertItemTemplate>
                        <asp:HiddenField ID="fld_Organisation" runat="server" Value='<%# Bind("organisation")%>' />
                        <td></td>
                        <td>
                            <asp:DropDownList ID="lst_Typ" runat="server" AutoPostBack="True" DataSourceID="src_Typ" DataValueField="sym" DataTextField="name" AppendDataBoundItems="true"
                                SelectedValue='<%# Bind("typ")%>'>
                                <asp:ListItem Value="" Text="" />
                            </asp:DropDownList>
                        </td>
                        <td>
                            <asp:DropDownList ID="lst_Personal" runat="server" AutoPostBack="True" DataSourceID="src_Personal" DataValueField="idx" DataTextField="anzeige_name" AppendDataBoundItems="true"
                                SelectedValue='<%# Bind("personal")%>'>
                                <asp:ListItem Value="" Text="" />
                            </asp:DropDownList>
                        </td>
                        <td>
                            <asp:LinkButton ID="btn_Insert" runat="server" CausesValidation="False" CommandName="Insert" Text="Hinzufügen"></asp:LinkButton>
                            <asp:LinkButton ID="btn_Cancel" runat="server" CausesValidation="False" CommandName="Cancel" Text="Abbrechen" OnClick="btn_Cancel_Click"></asp:LinkButton>
                        </td>
                    </InsertItemTemplate>
    
                    <EditItemTemplate>
                        <asp:HiddenField ID="fld_Organisation" runat="server" Value='<%# Bind("organisation")%>' />
                        <asp:HiddenField ID="fld_einheit" runat="server" Value='<%# Bind("einheit")%>' />
    
                        <td></td>
                        <td>
                            <asp:DropDownList ID="lst_Typ" runat="server" AutoPostBack="True" Enabled="false"
                                DataSourceID="src_Typ" DataValueField="sym" DataTextField="name" AppendDataBoundItems="true"
                                SelectedValue='<%# Bind("typ")%>'>
                                <asp:ListItem Value="" Text="" />
                            </asp:DropDownList>
                        </td>
                        <td>
                            <asp:DropDownList ID="lst_Personal" runat="server" AutoPostBack="True" DataSourceID="src_Personal" DataValueField="idx" DataTextField="anzeige_name" AppendDataBoundItems="true"
                                SelectedValue='<%# Bind("personal")%>'>
                                <asp:ListItem Value="" Text="" />
                            </asp:DropDownList>
                        </td>
                        <td>
                            <asp:LinkButton ID="btn_Update" runat="server" CausesValidation="False" CommandName="Update" Text="Aktualisieren" OnClick="btn_Update_Click"></asp:LinkButton>
                            <asp:LinkButton ID="btn_Cancel" runat="server" CausesValidation="False" CommandName="Cancel" Text="Abbrechen"></asp:LinkButton>
                        </td>
                    </EditItemTemplate>
    
                </asp:ListView>
    
            </td>
            <td style="text-align: right; vertical-align: top;">
                <asp:LinkButton Visible='<%# showActions %>' runat="server" ID="btn_New" Text="Neu" OnClick="btn_New_Click" />
    
            </td>
        </tr>
    </table>
    
    
    <br />
    
    <asp:Label ID="lbl_Status" runat="server" Text="" CssClass="FormStatus"></asp:Label>
    
    

    RolleForm.aspx.cs:

    using Governix.mgr;
    using Governix.dbs.dbi;
    using Governix.lib.web.apl;
    using System;
    using System.Web.UI.WebControls;
    
    namespace Governix.div.psv.cmp
    {
        public partial class RolleForm : ApplicationUserControl
        {
            protected void Page_Load(object sender, EventArgs e)
            {
            }
    
            protected void lvw_Rolle_DataBound(object snd, EventArgs evt)
            {
                lvw_Rolle.InsertItem.Visible = false;
            }
    
            protected void lvw_Rolle_ItemInserting(object snd, ListViewInsertEventArgs evt)
            {
                lbl_Status.Text = "";
    
                if (evt.Values["typ"] == null)
                {
                    lbl_Status.Text = "Die Funktion muss angegeben werden.";
                    evt.Cancel = true;
                    return;
                }
    
                String typ = Convert.ToString(evt.Values["typ"]);
    
                if (evt.Values["personal"] == null)
                {
                    lbl_Status.Text = "Der Mitarbeiter muss angegeben werden.";
                    evt.Cancel = true;
                    return;
                }
    
                int prs = Convert.ToInt32(evt.Values["personal"]);
    
                if (!check(prs,typ))
                {
                    evt.Cancel = true;
                    return;
                }
    
                src_Rolle.InsertParameters["organisation"].DefaultValue = fld_Organisation.Value;
                src_Rolle.InsertParameters["einheit"].DefaultValue = fld_Einheit.Value;
            }
    
            protected void lvw_Rolle_ItemEditing(object snd, ListViewEditEventArgs evt)
            {
                DropDownList l = (DropDownList)lvw_Rolle.InsertItem.FindControl("lst_Personal");
    
                if (l == null)
                    return;
    
                if (String.IsNullOrEmpty(l.SelectedValue))
                    return;
    
                int p = Convert.ToInt32(l.SelectedValue);
    
                // Here I would like to do something like this:
    
                // if l.SelectedValue not in List l then set l.SelectedValue=""
            }
    
            protected void lvw_Rolle_ItemUpdating(object snd, ListViewUpdateEventArgs evt)
            {
            }
    
    
            protected void btn_New_Click(object sender, EventArgs e)
            {
                lvw_Rolle.InsertItem.Visible = !lvw_Rolle.InsertItem.Visible;
            }
    
            private bool check(int prs, String typ)
            {
                return (true);
            }
    
            public void selectEinheit (int organisation,String einheit)
            {
                fld_Organisation.Value = Convert.ToString(organisation);
                fld_Einheit.Value = Convert.ToString(einheit);
                bindList();
            }
    
            private void bindList()
            {
                src_Rolle.SelectParameters["organisation"].DefaultValue = fld_Organisation.Value;
                src_Rolle.SelectParameters["einheit"].DefaultValue = fld_Einheit.Value;
                lvw_Rolle.DataBind();
            }
    
        }
    }

    Thursday, December 7, 2017 8:19 AM

All replies

  • User-1716253493 posted

    If the problem come from null value only, you can add empty value to the dropdown and set appenddatabound=true

            <asp:DropDownList ID="DropDownList1" runat="server" AppendDataBoundItems="True">
                <asp:ListItem Value="">Blank</asp:ListItem>
            </asp:DropDownList>

    If the problem come from other not listed value, remove the direct binding Eval/Bind from the dropdown, so you will not get this error message anymore.

    Use HiddenField to replace dropdown SelectedValue Binding

    <asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Bind("fieldname") %>' />

    Now, manualy select the dropdown items based hiddendfield value

        protected void ListView1_ItemEditing(object sender, ListViewEditEventArgs e)
        {
            DropDownList ddl = (DropDownList)ListView1.Items[e.NewEditIndex].FindControl("DropDownList1"); //the dropdown and hiddenfield is inside edit template
            HiddenField hf = (HiddenField)ListView1.Items[e.NewEditIndex].FindControl("HiddendField1"); //Bind the hiddenfield to field (two way binding)
            if (ddl.Items.FindByValue(hf.Value)!=null)
            {
                ddl.Items.FindByValue(hf.Value).Selected = true;
            }
        }

    When updating, set hiddenfield value from ddl selectedvalue because listview will save hiddenfield value

        protected void ListView1_ItemUpdating(object sender, ListViewUpdateEventArgs e)
        {
            DropDownList ddl = (DropDownList)ListView1.Items[ListView1.EditIndex].FindControl("DropDownList1"); //the dropdown and hiddenfield is inside edit template
            HiddenField hf = (HiddenField)ListView1.Items[ListView1.EditIndex].FindControl("HiddendField1"); //Bind the hiddenfield to field (two way binding)
            hf.Value = ddl.SelectedValue;
        }
    Thursday, December 7, 2017 8:47 AM
  • User260076833 posted

    Dear oned_gk,

    your approach seems to be the way to go, but in the ListView1_ItemEditing event, the DropDownList ddl and the HiddenField hf are null!
    e,NewEditIndex is 1.

    I have tried to replace your code with this:

    DropDownList l = (DropDownList)lvw_Rolle.EditItem.FindControl("lst_Personal");
    HiddenField f = (HiddenField)lvw_Rolle.EditItem.FindControl("fld_Personal");
    

    But in this case, lvw_Rolle.EditItem is null! (InsertItem is not, but we are in edit mode?)...

    What's still wrong?

    Thanks
    Magnus

    Thursday, December 7, 2017 4:51 PM
  • User-1716253493 posted

    Afaik, the code should work. Another way you can try to get the hiddenfield from the dropdown

        protected void DropDownList1_DataBound(object sender, EventArgs e)
        {
            DropDownList ddl = (DropDownList)sender;
            HiddenField hf = (HiddenField)ddl.NamingContainer.FindControl("HiddenField1");

    }
    Friday, December 8, 2017 2:30 AM
  • User-335504541 posted

    Hi Yeoman,

    your approach seems to be the way to go, but in the ListView1_ItemEditing event, the DropDownList <g class="gr_ gr_7 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling" id="7" data-gr-id="7">ddl</g> and the HiddenField hf are null!
    e,NewEditIndex is 1.

    I think you should use OnItemDataBound to find the control:

    protected void OnItemDataBound(object sender, ListViewItemEventArgs e)
    {
        if (lvw_Rolle.EditIndex == (e.Item as ListViewDataItem).DataItemIndex)
    { DropDownList lst_Personal = (e.Item.FindControl("lst_Personal") as DropDownList); HiddenField fld_Personal = (e.Item.FindControl("fld_Personal") as HiddenField); } }

    You could refer to the link below for more information:

    https://www.aspsnippets.com/Articles/Find-and-access-controls-in-EditItemTemplate-of-ASPNet-ListView.aspx

    Best Regards,

    Billy

    Friday, December 8, 2017 6:00 AM