【问题标题】:Chained dropdown list in gridviewgridview中的链式下拉列表
【发布时间】:2014-03-14 00:21:17
【问题描述】:

我试图在绑定到 LinqDataSource 的 ASP.NET 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。为什么我会收到此消息,以及有关执行此操作的正确方法的任何建议?

【问题讨论】:

  • 为什么必须为您的 cboBusinessUnit 下拉列表绑定 SelectedValue 字段?如果你把它拿出来怎么办?
  • 用户需要能够保存BusinessUnitID作为记录。如果我删除 SelectedValue,那么他们将无法更新业务单位(并且它不会显示正确的业务单位以供记录)。
  • 它确实摆脱了错误,但当我删除它时......所以也许我必须在代码隐藏中手动设置 BusinessUnitID......
  • 嗯..需要再考虑一下....
  • 你可以试试这个。添加回 SelectedValue 属性,但这次使用

标签: c# asp.net gridview


【解决方案1】:

试试这个

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

cboBusinessUnit.DataBind();
}

【讨论】:

  • 数据源是作为控件的属性提供的,为什么还要重新提供呢? DataSourceID="ldsBusinessUnits" DataTextField="Name" DataValueField="ID"
  • 不提供数据源不能直接绑定下拉列表。我对您的理解是您正在尝试根据第一个列表的选择重新绑定第二个列表(更改列表项),因此为了做到这一点,您必须重新绑定数据源提供的第二个列表,然后重新绑定列表。
  • 提供数据源:DataSourceID="ldsBusinessUnits"
【解决方案2】:

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

cboBusinessUnit.DataSource = ?

但也从错误中,我会说您的 GridView 在回发时可能会变得未绑定。也许如果我们有您的 Page_Load 方法和 DataBinding 方法,我们可以告诉您更多信息。

更新。 是的,确实阅读了有关数据源的信息,只是没有接受!所以还是会看看什么时候绑定等

【讨论】:

  • 下拉列表的数据源没有在代码隐藏中设置,它绑定到 GridView 本身存在的 LinqDataSource。代码隐藏中的唯一代码显示在问题 (cboDivision_SelectedIndexChanged) 中。但你可能是对的,这可能是一个顺序问题,在绑定数据源之前触发了事件。
  • 想通了,但给了你赏金,所以它不会浪费,你的答案是最接近的。感谢您查看它。
【解决方案3】:

好吧,我无法使用 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;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多