如何修复状态按钮无法显示在对应列的ASP.NET表格问题
问题:状态按钮无法显示在对应列中
表格结构说明
Task列是手动添加的,ASP.NET表格结构如下:
<asp:Table ID="Group" runat="server" CssClass="table table-bordered text-center task-table"> <asp:TableHeaderRow ID="GroupHeaderRow"> <asp:TableHeaderCell CssClass="text-center task-header-cell rounded-start-4" ColumnSpan="2">Task</asp:TableHeaderCell> </asp:TableHeaderRow> <asp:TableRow Style="border-left: 2px solid #ABCDFD; z-index: 1000;"> <asp:TableCell Width="50px" CssClass="task-text-box-input-cell"> <asp:TextBox ID="taskTextBox" runat="server" CssClass="task-text-box form-control" placeholder="Enter Task" OnTextChanged="AddTask" UseSubmitBehavior="false"></asp:TextBox> </asp:TableCell> </asp:TableRow> </asp:Table>
数据库检查情况
- 已确认SQL Server中列的数据类型
- 已尝试从数据库添加对应数据
尝试过的无效方法
- 多次调用
Group.Rows.Add(tableRow)添加行(Group为Table控件名称) - 单元格和行创建完成后一次性添加TableRow
- 为任务和状态分别创建多个TableRow和TableCell
相关代码
protected void UpdatedUpdateTable() { const string connectionString = "Data Source=localhost;Initial Catalog=sunday.com;Integrated Security=True;Encrypt=False"; int user_id = Convert.ToInt32(Session["UserId"]); using (SqlConnection connection = new SqlConnection(connectionString)) { string getColumnsQuery = "SELECT * FROM columnsOfTables WHERE user_id = @user_id"; using (SqlCommand getColumnsCommand = new SqlCommand(getColumnsQuery, connection)) { connection.Open(); getColumnsCommand.Parameters.AddWithValue("@user_id", user_id); using (SqlDataReader reader = getColumnsCommand.ExecuteReader()) { // Clear the space for the updated rows excluding the taskTextBox for (int i = Group.Rows.Count - 1; i > 1; i--) { Group.Rows.RemoveAt(i); } while (reader.Read()) { TableRow tableRow = new TableRow(); TableCell tableCell = new TableCell(); string dataType = reader.GetString(3); if (dataType.Equals("Task")) { using (SqlConnection connection1 = new SqlConnection(connectionString)) { connection1.Open(); string query = "SELECT * FROM dataOfTables WHERE user_id = @user_id AND board_id = @board_id AND data_type = @data_type"; using (SqlCommand command = new SqlCommand(query, connection1)) { command.Parameters.AddWithValue("@user_id", user_id); command.Parameters.AddWithValue("@board_id", this.getBoardId()); command.Parameters.AddWithValue("@data_type", "Task"); using (SqlDataReader taskReader = command.ExecuteReader()) { while (taskReader.Read()) { string task = taskReader["data"].ToString(); TextBox textBoxWithTask = new TextBox(); textBoxWithTask.ID = $"task-textbox-{taskReader["id"].ToString()}"; textBoxWithTask.Text = task; textBoxWithTask.CssClass = "task-text-box"; textBoxWithTask.TextChanged += EditTask; tableCell.Controls.Add(textBoxWithTask); tableRow.Controls.Add(tableCell); } } } } } else if (dataType.Equals("Status")) { TableHeaderRow tableHeaderRow = (TableHeaderRow)Group.Rows[0]; bool statusHeaderExists = false; foreach (TableCell cell in tableHeaderRow.Cells) { if (cell.Text.Equals(reader["column_name"].ToString())) { statusHeaderExists = true; break; } } if (statusHeaderExists == false) { TableHeaderCell statusHeaderCell = new TableHeaderCell(); statusHeaderCell.Text = reader["column_name"].ToString(); this.GroupHeaderRow.Cells.Add(statusHeaderCell); } using (SqlConnection connection1 = new SqlConnection(connectionString)) { string query = "SELECT * FROM dataOfTables WHERE user_id = @user_id AND board_id = @board_id AND data_type = @data_type AND column_name = @column_name"; using (SqlCommand command = new SqlCommand(query, connection1)) { connection1.Open(); command.Parameters.AddWithValue("@user_id", user_id); command.Parameters.AddWithValue("@board_id", this.getBoardId()); command.Parameters.AddWithValue("@data_type", "Status"); command.Parameters.AddWithValue("@column_name", reader["column_name"].ToString()); using (SqlDataReader statusReader = command.ExecuteReader()) { while (statusReader.Read()) { string status = statusReader["data"].ToString(); HtmlGenericControl statusBtn = new HtmlGenericControl(); statusBtn.InnerText = statusReader["data"].ToString(); statusBtn.Attributes["id"] = $"status-btn-{statusReader["id"].ToString()}"; statusBtn.Attributes["class"] = "status-btn"; statusBtn.Attributes["type"] = "button"; if (statusReader["data"].ToString().Equals("Done")) { statusBtn.Attributes["styles"] = "background-color: rgb(0, 200, 117)"; tableCell.Style["background-color"] = "rgb(0, 200, 117)"; } else if (statusReader["data"].ToString().Equals("Working on it")) { statusBtn.Attributes["styles"] = "background-color: rgb(253, 188, 100)"; tableCell.Style["background-color"] = "rgb(253, 188, 100)"; } else if (statusReader["data"].ToString().Equals("Stuck")) { statusBtn.Attributes["styles"] = "background-color: rgb(253, 188, 100)"; tableCell.Style["background-color"] = "rgb(253, 188, 100)"; } else { statusBtn.Attributes["styles"] = "background-color: rgb(121, 126, 147)"; tableCell.Style["background-color"] = "rgb(121, 126, 147)"; } tableCell.Controls.Add(statusBtn); tableRow.Controls.Add(tableCell); } } connection1.Close(); } } } this.Group.Controls.Add(tableRow); } } HtmlGenericControl addColumnBtn = new HtmlGenericControl("button"); addColumnBtn.Attributes["id"] = "AddColumnButton"; addColumnBtn.Attributes["class"] = "add-column-btn"; addColumnBtn.Attributes["type"] = "button"; addColumnBtn.Attributes["onclick"] = "showColumnsMenu()"; addColumnBtn.InnerText = "+"; TableHeaderRow headerRow = (TableHeaderRow)Group.Rows[0]; bool addColumnBtnHeaderExists = false; foreach (TableCell cell in headerRow.Cells) { foreach (Control control in cell.Controls) { if (control is HtmlGenericControl btn && btn.Attributes["id"] == "AddColumnButton") { addColumnBtnHeaderExists = true; break; } } if (addColumnBtnHeaderExists) break; } if (!addColumnBtnHeaderExists) { TableHeaderCell addColumnBtnHeaderCell = new TableHeaderCell(); addColumnBtnHeaderCell.Controls.Add(addColumnBtn); headerRow.Cells.Add(addColumnBtnHeaderCell); } } } }
解决方案
你的代码核心问题在于行和单元格的创建逻辑错误,导致任务和状态被分别放在不同的行里,无法对应到同一行的不同列。具体修复如下:
1. 错误点拆解
- 遍历列(Task/Status)时单独创建行,导致Task和Status各占一行,无法对齐
- 复用同一个
TableCell添加到行中,引发控件渲染异常 - 没有建立任务与对应状态的关联关系,无法将状态匹配到具体任务
2. 重构后的代码逻辑
先获取所有任务数据,再为每个任务查询对应状态,构建包含Task列和所有Status列的完整行:
protected void UpdatedUpdateTable() { const string connectionString = "Data Source=localhost;Initial Catalog=sunday.com;Integrated Security=True;Encrypt=False"; int user_id = Convert.ToInt32(Session["UserId"]); int board_id = this.getBoardId(); using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); // 1. 先获取所有状态列名称,确保表头存在 List<string> statusColumns = new List<string>(); string getStatusColumnsQuery = "SELECT column_name FROM columnsOfTables WHERE user_id = @user_id AND data_type = 'Status'"; using (SqlCommand cmd = new SqlCommand(getStatusColumnsQuery, connection)) { cmd.Parameters.AddWithValue("@user_id", user_id); using (SqlDataReader reader = cmd.ExecuteReader()) { TableHeaderRow headerRow = (TableHeaderRow)Group.Rows[0]; while (reader.Read()) { string colName = reader["column_name"].ToString(); statusColumns.Add(colName); // 检查表头是否已存在,不存在则添加 if (!headerRow.Cells.Cast<TableCell>().Any(c => c.Text == colName)) { TableHeaderCell statusHeader = new TableHeaderCell(); statusHeader.Text = colName; headerRow.Cells.Add(statusHeader); } } } } // 2. 清空现有数据行(保留表头和输入行) for (int i = Group.Rows.Count - 1; i > 1; i--) { Group.Rows.RemoveAt(i); } // 3. 获取所有任务数据,为每个任务创建完整行 string getTasksQuery = "SELECT id, data FROM dataOfTables WHERE user_id = @user_id AND board_id = @board_id AND data_type = 'Task'"; using (SqlCommand cmd = new SqlCommand(getTasksQuery, connection)) { cmd.Parameters.AddWithValue("@user_id", user_id); cmd.Parameters.AddWithValue("@board_id", board_id); using (SqlDataReader taskReader = cmd.ExecuteReader()) { while (taskReader.Read()) { int taskId = taskReader.GetInt32(0); string taskText = taskReader["data"].ToString(); // 创建任务行 TableRow taskRow = new TableRow(); // 添加Task单元格 TableCell taskCell = new TableCell(); TextBox taskTextBox = new TextBox(); taskTextBox.ID = $"task-textbox-{taskId}"; taskTextBox.Text = taskText; taskTextBox.CssClass = "task-text-box"; taskTextBox.TextChanged += EditTask; taskCell.Controls.Add(taskTextBox); taskRow.Cells.Add(taskCell); // 为每个状态列添加对应的状态按钮单元格 foreach (string statusCol in statusColumns) { TableCell statusCell = new TableCell(); // 查询当前任务在该状态列的数据 string getStatusQuery = "SELECT data FROM dataOfTables WHERE user_id = @user_id AND board_id = @board_id AND data_type = 'Status' AND column_name = @colName AND task_id = @taskId"; using (SqlConnection statusConn = new SqlConnection(connectionString)) { statusConn.Open(); using (SqlCommand statusCmd = new SqlCommand(getStatusQuery, statusConn)) { statusCmd.Parameters.AddWithValue("@user_id", user_id); statusCmd.Parameters.AddWithValue("@board_id", board_id); statusCmd.Parameters.AddWithValue("@colName", statusCol); statusCmd.Parameters.AddWithValue("@taskId", taskId); // 需确保dataOfTables表有task_id字段关联任务 object statusObj = statusCmd.ExecuteScalar(); string statusText = statusObj?.ToString() ?? "Not Set"; // 创建状态按钮 HtmlGenericControl statusBtn = new HtmlGenericControl("button"); statusBtn.InnerText = statusText; statusBtn.Attributes["id"] = $"status-btn-{taskId}-{statusCol}"; statusBtn.Attributes["class"] = "status-btn"; // 设置按钮样式(修复原代码styles属性错误) switch (statusText) { case "Done": statusBtn.Style["background-color"] = "rgb(0, 200, 117)"; statusCell.Style["background-color"] = "rgb(0, 200, 117)"; break; case "Working on it": case "Stuck": statusBtn.Style["background-color"] = "rgb(253, 188, 100)"; statusCell.Style["background-color"] = "rgb(253, 188, 100)"; break; default: statusBtn.Style["background-color"] = "rgb(121, 126, 147)"; statusCell.Style["background-color"] = "rgb(121, 126, 147)"; break; } statusCell.Controls.Add(statusBtn); } } taskRow.Cells.Add(statusCell); } // 将完整的任务行添加到表格 Group.Rows.Add(taskRow); } } } // 4. 添加或检查添加列按钮 HtmlGenericControl addColumnBtn = new HtmlGenericControl("button"); addColumnBtn.Attributes["id"] = "AddColumnButton"; addColumnBtn.Attributes["class"] = "add-column-btn"; addColumnBtn.Attributes["type"] = "button"; addColumnBtn.Attributes["onclick"] = "showColumnsMenu()"; addColumnBtn.InnerText = "+"; TableHeaderRow headerRowFinal = (TableHeaderRow)Group.Rows[0]; bool addColumnBtnExists = headerRowFinal.Cells.Cast<TableCell>() .Any(c => c.Controls.OfType<HtmlGenericControl>().Any(btn => btn.Attributes["id"] == "AddColumnButton")); if (!addColumnBtnExists) { TableHeaderCell btnCell = new TableHeaderCell(); btnCell.Controls.Add(addColumnBtn); headerRowFinal.Cells.Add(btnCell); } } }
3. 额外注意事项
- 需确保
dataOfTables表包含task_id字段,用于关联任务与对应状态数据 - 修复了原代码中样式属性错误:将
attributes["styles"]改为正确的Style["background-color"] - 优化了数据库查询逻辑,减少重复连接创建,提升性能
内容的提问来源于stack exchange,提问作者MrOzwaldMan
相关产品推荐
相关产品推荐

