gridview中的链式下拉列表

时间:2014-03-06 14:47:08

标签: c# asp.net gridview

我试图在绑定到LinqDataSource的ASP.NET gridview控件中链接一些下拉列表。当我点击'编辑'命令字段下拉列表按预期显示。当用户更改第一个下拉列表时,我希望根据第一个下拉列表的选择重新填充第二个下拉列表。这是我的gridview:

<asp:GridView ID="gvAreas" runat="server" AllowSorting="True" AutoGenerateColumns="False" CssClass="grid pad5 full" DataKeyNames="ID" DataSourceID="ldsAreas">
    <Columns>
        <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" Visible="false" />
        <asp:TemplateField HeaderText="Division" SortExpression="CDB_BusinessUnit.CDB_Division.Name">
            <ItemTemplate>
                <%#Eval("CDB_BusinessUnit.CDB_Division.Name") %>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList ID="cboDivision" runat="server" AppendDataBoundItems="True" DataSourceID="ldsDivisions" DataTextField="Name" DataValueField="ID" SelectedValue='<%#Eval("CDB_BusinessUnit.DivisionID") %>' AutoPostBack="True" OnSelectedIndexChanged="cboDivision_SelectedIndexChanged">
                    <asp:ListItem Text="" Value="" />
                </asp:DropDownList>
                <asp:LinqDataSource ID="ldsDivisions" runat="server" ContextTypeName="CommonDB_Management.CommonDBDataContext" EntityTypeName="" Select="new (ID, Name)" TableName="CDB_Divisions" OrderBy="Name" />
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Business Unit" SortExpression="CDB_BusinessUnit.Name">
            <ItemTemplate>
                <%#Eval("CDB_BusinessUnit.Name") %>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList ID="cboBusinessUnit" runat="server" AppendDataBoundItems="true" DataSourceID="ldsBusinessUnits" DataTextField="Name" DataValueField="ID" SelectedValue='<%#Bind("BusinessUnitID") %>' />
                <asp:LinqDataSource ID="ldsBusinessUnits" runat="server" ContextTypeName="CommonDB_Management.CommonDBDataContext" EntityTypeName="" TableName="CDB_BusinessUnits" Where="DivisionID == @DivisionID" >
                    <WhereParameters>
                        <asp:ControlParameter ControlID="cboDivision" Name="DivisionID" PropertyName="SelectedValue" Type="Int32" />
                    </WhereParameters>
                </asp:LinqDataSource>
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:CommandField ShowEditButton="true" HeaderStyle-Width="100px" HeaderStyle-CssClass="center" ItemStyle-CssClass="center" HeaderText="Edit" ValidationGroup="gv" />
        <asp:CommandField ShowDeleteButton="true" HeaderStyle-Width="100px" HeaderStyle-CssClass="center" ItemStyle-CssClass="center" HeaderText="Delete" />
    </Columns>
</asp:GridView>

<asp:LinqDataSource ID="ldsAreas" runat="server" ContextTypeName="CommonDB_Management.CommonDBDataContext" EnableDelete="True" EnableInsert="True" EnableUpdate="True" EntityTypeName="" TableName="CDB_Areas" OrderBy="CDB_BusinessUnit.CDB_Division.Name, CDB_BusinessUnit.Name, Name"></asp:LinqDataSource>

正如您在第二列(Division)中看到的,我正在使用OnSelectedIndexChanged事件尝试重新绑定第二个下拉列表。这是事件中的代码:

protected void cboDivision_SelectedIndexChanged(object sender, EventArgs e)
{
    DropDownList cboBusinessUnit = gvAreas.Rows[gvAreas.EditIndex].FindControl("cboBusinessUnit") as DropDownList;
    cboBusinessUnit.DataBind();
}

我的问题是,上面的代码在DataBind()调用时会显示消息:

Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.

控件cboBusinessUnit明确绑定到位于其下方的LinqDataSource。为什么我收到此消息,以及有关正确方法的任何建议?

3 个答案:

答案 0 :(得分:0)

您正在调用cboBusinessUnit.DataBind();在向您的下拉列表分配任何数据之前,需要在调用DataBind()之前设置DataSource

cboBusinessUnit.DataSource = ?

但是从错误中我也说你的GridView可能在回发时变得不受约束。也许如果我们有你的Page_Load方法和DataBinding方法,我们可以告诉你更多。

更新。 是的确没有读过数据源,只是没有把它拿进来!!所以当事情绑定等时仍然会看到

答案 1 :(得分:0)

试试这个

protected void cboDivision_SelectedIndexChanged(object sender, EventArgs e)
{
cboBusinessUnit.DataSource= gvAreas.Rows[gvAreas.EditIndex].FindControl("cboBusinessUnit") as DropDownList;

cboBusinessUnit.DataBind();
}

答案 2 :(得分:0)

我使用DropDownList的SelectedValue属性和LinqDataSource ControlParameter无法正常工作,所以我必须在代码隐藏中做几乎所有事情。以下是我最终的结果:

<asp:GridView ID="gvAreas" runat="server" AllowSorting="True" AutoGenerateColumns="False" CssClass="grid pad5 full" DataKeyNames="ID" DataSourceID="ldsAreas" OnRowUpdating="gvAreas_RowUpdating" OnRowDataBound="gvAreas_RowDataBound">
    <Columns>
        <asp:BoundField DataField="ID" HeaderText="ID" InsertVisible="False" ReadOnly="True" SortExpression="ID" Visible="false" />
        <asp:TemplateField HeaderText="Division" SortExpression="CDB_BusinessUnit.CDB_Division.Name">
            <ItemTemplate>
                <%#Eval("CDB_BusinessUnit.CDB_Division.Name") %>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList ID="cboDivision" runat="server" DataSourceID="ldsDivisions" DataTextField="Name" DataValueField="ID" AutoPostBack="True" OnSelectedIndexChanged="cboDivision_SelectedIndexChanged" AppendDataBoundItems="true">
                    <asp:ListItem Value="" Text="" />
                </asp:DropDownList>
                <asp:LinqDataSource ID="ldsDivisions" runat="server" ContextTypeName="CommonDB_Management.CommonDBDataContext" EntityTypeName="" Select="new (ID, Name)" TableName="CDB_Divisions" OrderBy="Name" />
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Business Unit" SortExpression="CDB_BusinessUnit.Name">
            <ItemTemplate>
                <%#Eval("CDB_BusinessUnit.Name") %>
            </ItemTemplate>
            <EditItemTemplate>
                <asp:DropDownList ID="cboBusinessUnit" runat="server" DataTextField="Name" DataValueField="ID" />
            </EditItemTemplate>
        </asp:TemplateField>
        <asp:CommandField ShowEditButton="true" HeaderStyle-Width="100px" HeaderStyle-CssClass="center" ItemStyle-CssClass="center" HeaderText="Edit" ValidationGroup="gv" />
        <asp:CommandField ShowDeleteButton="true" HeaderStyle-Width="100px" HeaderStyle-CssClass="center" ItemStyle-CssClass="center" HeaderText="Delete" />
    </Columns>
</asp:GridView>

代码隐藏:

protected void cboDivision_SelectedIndexChanged(object sender, EventArgs e)
{
    DropDownList cboDivision = gvAreas.Rows[gvAreas.EditIndex].FindControl("cboDivision") as DropDownList;
    DropDownList cboBusinessUnit = gvAreas.Rows[gvAreas.EditIndex].FindControl("cboBusinessUnit") as DropDownList;

    cboBusinessUnit.Items.Clear();

    if (cboDivision.SelectedValue != null && !String.IsNullOrEmpty(cboDivision.SelectedValue))
    {
        var businessUnits = db.CDB_BusinessUnits.Where(b => b.DivisionID == Convert.ToInt32(cboDivision.SelectedValue)).OrderBy(b => b.Name);
        cboBusinessUnit.DataSource = businessUnits;
    }
    else
    {
        var businessUnits = db.CDB_BusinessUnits.Where(b => b.DivisionID == null).OrderBy(b => b.Name);
        cboBusinessUnit.DataSource = businessUnits;
    }

    cboBusinessUnit.DataBind();
}

protected void gvAreas_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    DropDownList cboBusinessUnit = gvAreas.Rows[gvAreas.EditIndex].FindControl("cboBusinessUnit") as DropDownList;

    if (cboBusinessUnit.SelectedValue != null && !String.IsNullOrEmpty(cboBusinessUnit.SelectedValue))
    {
        e.NewValues["BusinessUnitID"] = Convert.ToInt32(cboBusinessUnit.SelectedValue);
    }
    else
    {
        e.NewValues["BusinessUnitID"] = null;
    }
}

protected void gvAreas_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if ((e.Row.RowState & DataControlRowState.Edit) > 0)
    {
        CDB_Area area = e.Row.DataItem as CDB_Area;

        if (area.BusinessUnitID != null)
        {
            DropDownList cboDivision = e.Row.FindControl("cboDivision") as DropDownList;
            DropDownList cboBusinessUnit = e.Row.FindControl("cboBusinessUnit") as DropDownList;

            if (area.CDB_BusinessUnit.DivisionID != null)
            {
                cboDivision.Items.FindByValue(area.CDB_BusinessUnit.DivisionID.ToString()).Selected = true;

                var businessUnits = db.CDB_BusinessUnits.Where(b => b.DivisionID == area.CDB_BusinessUnit.DivisionID).OrderBy(b => b.Name);
                cboBusinessUnit.DataSource = businessUnits;
            }
            else
            {
                var businessUnits = db.CDB_BusinessUnits.Where(b => b.DivisionID == null).OrderBy(b => b.Name);
                cboBusinessUnit.DataSource = businessUnits;
            }

            cboBusinessUnit.DataBind();
            cboBusinessUnit.Items.FindByValue(area.BusinessUnitID.ToString()).Selected = true;
        }
    }
}