Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind data to DropDownList in UpdatePanel inside DetailsView

I use DetailsView to insert rows in database. Row has fields id, subcategory_id etc. I want to fill dynamically dropdownlist ddl_subcategories, which is used in TemplateField. Selected item value of first dropdownlist ddl_categories is used as parameter for generating collection for ddl_subcategories. I try it with using UpdatePanel, but method DataBind returns error "Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.".

There's code of web form

<asp:DetailsView ID="dvw" runat="server" Height="50px" Width="125px" 
    AutoGenerateRows="False" DataSourceID="ods"
    DefaultMode="Insert" DataKeyNames="Section_id"
    OnDataBound="dvw_DataBound" OnItemUpdated="dvw_ItemUpdated" 
    OnItemCommand="dvw_ItemCommand">
    <Fields>
    <asp:TemplateField HeaderText="Category" >
       <ItemTemplate>
                 <asp:DropDownList ID="ddl_categories" runat="server" AutoPostBack="true" DataSourceID="ods_categories"
                  DataTextField="Name" DataValueField="Category_id" OnSelectedIndexChanged="category_select_index_changed"/>
       </ItemTemplate>
    </asp:TemplateField>            

    <asp:TemplateField HeaderText="Subcategory" >
        <ItemTemplate>
            <asp:UpdatePanel runat="server" UpdateMode="Conditional">
                <ContentTemplate>
                    <asp:DropDownList ID="ddl_subcategories" runat="server"                               
                          SelectedValue='<%# Bind("Subcategory_id") %>' />
                </ContentTemplate>
                <Triggers>
                    <asp:AsyncPostBackTrigger ControlID="ddl_categories" EventName="SelectedIndexChanged" />
                </Triggers>
            </asp:UpdatePanel>
        </ItemTemplate>
    </asp:TemplateField>
...
 </Fields>
</asp:DetailsView>

There is part of behind-code:

protected void category_select_index_changed(object sender, EventArgs e)
{
    DropDownList ddl_categories = (DropDownList)dvw.FindControl("ddl_categories");
    List<SUBCATEGORY> sections =  SUBCATEGORY.Select_all_by_parameters(Int32.Parse(ddl_categories.SelectedValue));//Select all subcategories by id of category
    DropDownList ddl_subcategories= (DropDownList)dvw.FindControl("ddl_subcategories");

    ddl_subcategories.DataSource = sections;
    ddl_subcategories.DataTextField = "Name";
    ddl_subcategories.DataValueField = "Subcategory_id";
    ddl_subcategories.DataBind();
}

What is my error? Thanks.

like image 986
greatromul Avatar asked Nov 05 '22 10:11

greatromul


1 Answers

The problem is that when you are data binding the subcategories dropdown, there is no DataBinding Context (see here for more info, pay attention to David Fowler's comments). I don't think the UpdatePanel is the issue as the behavior is the same with or without it (and if you wrap the entire DetailsView in an UpdatePanel).

A solution is to load the items individually instead of data binding the control. It seems a little clumsy, I admit, but it does work.

protected void category_select_index_changed(object sender, EventArgs e)
{
    DropDownList ddl_categories = (DropDownList)dvw.FindControl("ddl_categories");
    IEnumerable<SUBCATEGORY> sections = new SUBCATEGORY[] { new SUBCATEGORY() { Name = "First " + ddl_categories.SelectedValue, Subcategory_id = "1" }, new SUBCATEGORY() { Name = "Second", Subcategory_id = "2" } };
    DropDownList ddl_subcategories = (DropDownList)dvw.FindControl("ddl_subcategories");

    ddl_subcategories.Items.Clear();
    foreach (SUBCATEGORY cat in sections)
    {
        ddl_subcategories.Items.Add(new ListItem(cat.Name, cat.Subcategory_id));
    }
}

A better option would be to not use Bind in the control, and just set the value in the ObjectDataSource's parameters on Insert/Update.

Update: You can set the ObjectDataSource value directly. Add an event handler for the OnInserting (or OnUpdating as needed) as follows:

protected void ods_OnInserting(object sender, ObjectDataSourceMethodEventArgs e)
{
    DropDownList ddl_subcategories = (DropDownList)dvw.FindControl("ddl_subcategories");
    e.InputParameters["Subcategory_id"] = ddl_subcategories.SelectedValue;
}

I can't actually test this right now, but it should be close.

like image 163
sgriffinusa Avatar answered Nov 15 '22 06:11

sgriffinusa