C#中无法获取ASPxGridView内下拉框选中项数据求助
解决ASPxGridView中客户端绑定下拉框无法获取选中值的问题
这个问题我之前也碰到过,核心原因很明确:你通过WebMethod在客户端异步绑定的DropDownList,服务器端并没有维护它的视图状态和数据状态。因为所有选项都是在浏览器里加载的,服务器端控件的DataSource、Items集合在回发时是空的,自然就获取不到选中值,甚至会出现NullReferenceException。
下面给你两种针对性的解决方案,根据你的需求选择:
方案一:改用服务器端绑定(推荐,最稳定)
如果你的数据源可以在服务器端直接获取,建议把下拉框的绑定逻辑移到服务器端的GridView事件里,这样服务器能跟踪控件的状态,回发时就能正常读取选中值。
步骤1:给GridView添加OnInitNewRow事件
修改你的ASPX代码,给dgDepots加上初始化新行的事件:
<dx:ASPxGridView ID="dgDepots" runat="server" ClientInstanceName="grid" Width="100%" OnRowDeleting="dgDepots_RowDeleting" OnRowInserting="dgDepots_RowInserting" OnRowUpdating="dgDepots_RowUpdating" OnInitNewRow="dgDepots_InitNewRow"> <Columns> <dx:GridViewDataColumn FieldName="LocationCode" VisibleIndex="0"> <EditItemTemplate> <asp:DropDownList ID="ddlLocation" runat="server"></asp:DropDownList> </EditItemTemplate> </dx:GridViewDataColumn> </Columns> </dx:ASPxGridView>
步骤2:在服务器端实现绑定逻辑
在后台代码里,通过OnInitNewRow事件找到下拉框,用服务器端方式绑定数据:
protected void dgDepots_InitNewRow(object sender, DevExpress.Web.Data.ASPxDataInitNewRowEventArgs e) { // 获取编辑行中的DropDownList控件 var ddlLocation = (DropDownList)dgDepots.FindEditRowCellTemplateControl( (GridViewDataColumn)dgDepots.Columns["LocationCode"], "ddlLocation" ); // 这里替换成你原本在WebMethod里获取数据的逻辑(比如从数据库读取) var locationData = GetLocationCodesFromDatabase(); // 自定义方法,返回数据源 ddlLocation.DataSource = locationData; ddlLocation.DataTextField = "Text"; // 对应你数据里的显示字段 ddlLocation.DataValueField = "Value"; // 对应你数据里的取值字段 ddlLocation.DataBind(); // 添加默认选项 ddlLocation.Items.Insert(0, new ListItem("Select", "-1")); } // 示例:模拟从数据库获取数据的方法 private DataTable GetLocationCodesFromDatabase() { // 这里写你的数据库查询逻辑,返回包含Text和Value的DataTable DataTable dt = new DataTable(); dt.Columns.Add("Text"); dt.Columns.Add("Value"); // 假设这是从数据库拿到的数据 dt.Rows.Add("Location A", "1"); dt.Rows.Add("Location B", "2"); return dt; }
步骤3:修改RowInserting事件获取值
现在你原来的RowInserting代码就能正常工作了,因为服务器端已经维护了下拉框的状态:
protected void dgDepots_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e) { e.Cancel = true; // 取消GridView默认的插入逻辑,我们自己处理 var ddlLocation = (DropDownList)dgDepots.FindEditRowCellTemplateControl( (GridViewDataColumn)dgDepots.Columns["LocationCode"], "ddlLocation" ); // 验证是否选择了有效选项 if (ddlLocation.SelectedIndex > 0 && !string.IsNullOrEmpty(ddlLocation.SelectedValue)) { using (var con = new SqlConnection("你的连接字符串")) { SqlCommand cmd = new SqlCommand("SP_Insert_Line_Item", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@LocationCode", ddlLocation.SelectedValue); con.Open(); int i = cmd.ExecuteNonQuery(); con.Close(); } // 重新绑定GridView,刷新数据 dgDepots.DataBind(); } }
方案二:保留客户端绑定,通过隐藏域传递值
如果必须用WebMethod客户端绑定,那可以通过隐藏域在客户端把选中值存起来,回发时服务器端读取隐藏域的值。
步骤1:在EditItemTemplate里添加隐藏域
修改ASPX的编辑模板,增加一个隐藏域:
<EditItemTemplate> <asp:DropDownList ID="ddlLocation" runat="server" OnClientSelectedIndexChanged="ddlLocation_OnSelectedIndexChanged"></asp:DropDownList> <asp:HiddenField ID="hfSelectedLocation" runat="server" /> </EditItemTemplate>
步骤2:写客户端脚本同步选中值到隐藏域
在页面里添加JavaScript,当下拉框选中项变化时,把值存到隐藏域:
function ddlLocation_OnSelectedIndexChanged(sender, args) { // 获取隐藏域的客户端ID,赋值选中值 var hiddenField = document.getElementById('<%= hfSelectedLocation.ClientID %>'); hiddenField.value = sender.value; }
步骤3:在RowInserting事件里读取隐藏域的值
后台代码里不再直接操作DropDownList,而是读取隐藏域的值:
protected void dgDepots_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e) { e.Cancel = true; // 获取隐藏域控件 var hfLocation = (HiddenField)dgDepots.FindEditRowCellTemplateControl( (GridViewDataColumn)dgDepots.Columns["LocationCode"], "hfSelectedLocation" ); string selectedValue = hfLocation.Value; if (!string.IsNullOrEmpty(selectedValue) && selectedValue != "Select") { using (var con = new SqlConnection("你的连接字符串")) { SqlCommand cmd = new SqlCommand("SP_Insert_Line_Item", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@LocationCode", selectedValue); con.Open(); int i = cmd.ExecuteNonQuery(); con.Close(); } dgDepots.DataBind(); } }
补充说明
你提到的ContentPlaceHolder不会影响这个问题,核心矛盾就是客户端绑定的控件服务器端无状态——服务器端不知道你在客户端加载了哪些选项,所以回发时控件的状态是“空”的,自然拿不到选中值。
内容的提问来源于stack exchange,提问作者sa f
相关产品推荐
相关产品推荐

