ASP GridView填充问题求助:DataTable有数据但GridView为空
问题根源分析
你遇到的GridView为空的核心原因是静态WebMethod的特性导致你操作的是一个全新的页面实例,而非当前用户请求的页面实例:
ViewDetailsItemOrdersWS是静态方法,你在里面new Index()创建的页面对象,和当前客户端正在交互的页面完全是两个独立的实例。这个新实例里的gvList控件是服务器端新生成的,和前端页面上的gvList没有任何关联,所以即使你绑定了数据,前端也完全看不到变化。- 另外,你的前端代码里还有个小bug:获取下拉框值的选择器写错了,
$('.<%= ddlTime.ClientID %>')应该改成$('#<%= ddlTime.ClientID %>')(ID选择器用#而非.),否则根本拿不到下拉框的选中值。
解决方案
下面提供两种可行的解决思路,推荐第一种更贴合你当前Ajax的使用场景:
方案一:WebMethod返回JSON数据,前端动态渲染表格(推荐)
这种方式让WebMethod只负责获取数据并返回JSON,前端用JavaScript动态生成表格内容,避免服务器端控件实例不匹配的问题。
后端代码修改
修改WebMethod,将DataTable转换为可序列化的对象列表并返回:
[System.Web.Services.WebMethod] [ScriptMethod(ResponseFormat = ResponseFormat.Json)] public static object ViewDetailsItemOrdersWS(String ddlTimeSelectedVal) { int val = Convert.ToInt32(ddlTimeSelectedVal); DataTable dt = getMenuData(val); // 将DataTable转换为可序列化的字典列表 List<Dictionary<string, object>> dataList = new List<Dictionary<string, object>>(); foreach (DataRow row in dt.Rows) { Dictionary<string, object> rowDict = new Dictionary<string, object>(); foreach (DataColumn col in dt.Columns) { rowDict[col.ColumnName] = row[col]; } dataList.Add(rowDict); } return dataList; }
注:可以删除原来的itemOrder方法,因为不再需要通过页面实例绑定控件了
前端代码修改
修正下拉框选择器,并在Ajax成功回调里动态渲染GridView:
$(document).ready(function () { // 修正选择器:用#获取ID var dataDDLTime = $('#<%= ddlTime.ClientID %>').val(); $('#<%= lblItemOrders.ClientID %>').on('click', function () { var dataOfDDLTime = JSON.stringify({ ddlTimeSelectedVal: dataDDLTime }); $.ajax({ type: "POST", url: "Index.aspx/ViewDetailsItemOrdersWS", data: dataOfDDLTime, contentType: 'application/json; charset=utf-8', dataType: "json", success: function (response) { var grid = $('[id$=gvList]'); var tbody = grid.find('tbody'); tbody.empty(); // 清空原有内容 // 循环返回的数据生成表格行(请根据你的DataTable列名调整) response.d.forEach(function(item) { var row = $('<tr>'); // 示例:根据实际列名添加td,比如你的列是OrderId, ItemName, Quantity row.append($('<td>').text(item.OrderId)); row.append($('<td>').text(item.ItemName)); row.append($('<td>').text(item.Quantity)); tbody.append(row); }); grid.show(); // 显示GridView }, error: function (err) { console.log(err); } }); }); });
方案二:使用UpdatePanel实现局部刷新(保留服务器端绑定)
如果你更习惯服务器端控件的绑定方式,可以用UpdatePanel实现局部页面刷新,避免整页回发:
前端ASPX代码修改
将Label(建议换成LinkButton,因为Label默认不支持回发)和GridView放入UpdatePanel:
<asp:UpdatePanel ID="UpdatePanel1" runat="server"> <ContentTemplate> <asp:LinkButton ID="lblItemOrders" runat="server" Text="查看订单" OnClick="lblItemOrders_Click"></asp:LinkButton> <asp:GridView ID="gvList" runat="server" Visible="false"></asp:GridView> </ContentTemplate> </asp:UpdatePanel>
后端代码修改
添加LinkButton的点击事件处理方法,直接调用你的itemOrder方法:
protected void lblItemOrders_Click(object sender, EventArgs e) { string selectedVal = ddlTime.SelectedValue; itemOrder(selectedVal); } // 保留你原来的itemOrder方法即可 protected void itemOrder(String ddlTimeSelectedVal) { int val = Convert.ToInt32(ddlTimeSelectedVal); DataTable s = getMenuData(val); gvList.DataSource = s; gvList.DataBind(); gvList.Visible = true; }
注:这种方式不需要再写jQuery Ajax代码,UpdatePanel会自动处理局部刷新
内容的提问来源于stack exchange,提问作者domster
相关产品推荐
相关产品推荐

