ASP.NET GridView中DropdownList加载数据库已选值的技术咨询
解决方案
核心问题分析
你当前代码的问题在于在RowDataBound事件中遍历所有GridView行设置同一个SelectedIndex,这会导致所有行的下拉框选中状态完全一致。而且RowDataBound是每行绑定数据时触发的事件,这种遍历操作不仅冗余,还会覆盖之前行的设置。
正确的思路是:在RowDataBound中针对当前行,从该行绑定的数据源里取出之前保存的选中值,再给当前行的下拉框单独设置选中状态。
具体修改步骤
1. 修复Page_Load的重复绑定问题
首先在Page_Load中添加!IsPostBack判断,避免每次回发都重新绑定GridView,丢失用户操作状态:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Sql_Connection.Open(); SqlCommand Select_Subject_R = new SqlCommand("SELECT SID,Period,Time,Monday,Tuesday,Wednesday,Thursday,Friday FROM [OrisonSystemRAWAFED].[dbo].[CCE_Schedule] where Academicyear =(select AcademicYear from School_AcademicYear where Status='Current') and Class='10' and Division='A'", Sql_Connection); SqlDataAdapter sda = new SqlDataAdapter(Select_Subject_R); DataTable dt = new DataTable(); sda.Fill(dt); Sql_Connection.Close(); Grid_View1.DataSource = dt; Grid_View1.DataBind(); } }
2. 优化RowDataBound事件:缓存下拉框数据源+逐行设置选中值
不要在RowDataBound里每次都查询科目数据,先在页面加载时查询一次缓存起来;然后针对当前行获取保存的选中值,设置对应下拉框的SelectedValue(比SelectedIndex更可靠,不受选项顺序影响):
// 页面级变量,缓存科目数据 private DataTable _subjectDt; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 先查询并缓存科目数据 LoadSubjectData(); // 绑定GridView BindGridView(); } } // 单独封装科目数据查询 private void LoadSubjectData() { Sql_Connection.Open(); SqlCommand cmd = new SqlCommand("SELECT dbo.CCE_SubjectGroup.SubjectCode, dbo.CCE_SubjectMaster.SubjectName FROM dbo.CCE_SubjectGroup INNER JOIN dbo.CCE_SubjectMaster ON dbo.CCE_SubjectGroup.SubjectCode = dbo.CCE_SubjectMaster.SubjectCode WHERE (dbo.CCE_SubjectGroup.AcademicYear = (select AcademicYear from School_AcademicYear where Status='Current')) AND (dbo.CCE_SubjectGroup.Class = '10') GROUP BY dbo.CCE_SubjectGroup.SubjectCode, dbo.CCE_SubjectMaster.SubjectName ORDER BY dbo.CCE_SubjectGroup.SubjectCode", Sql_Connection); SqlDataAdapter da = new SqlDataAdapter(cmd); _subjectDt = new DataTable(); da.Fill(_subjectDt); Sql_Connection.Close(); } // 单独封装GridView绑定 private void BindGridView() { Sql_Connection.Open(); SqlCommand Select_Subject_R = new SqlCommand("SELECT SID,Period,Time,Monday,Tuesday,Wednesday,Thursday,Friday FROM [OrisonSystemRAWAFED].[dbo].[CCE_Schedule] where Academicyear =(select AcademicYear from School_AcademicYear where Status='Current') and Class='10' and Division='A'", Sql_Connection); SqlDataAdapter sda = new SqlDataAdapter(Select_Subject_R); DataTable dt = new DataTable(); sda.Fill(dt); Sql_Connection.Close(); Grid_View1.DataSource = dt; Grid_View1.DataBind(); } protected void Classes_List_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { // 获取当前行绑定的数据 DataRowView rowView = (DataRowView)e.Row.DataItem; // 取出当前行保存的Monday和Tuesday选中值 string savedMondayValue = rowView["Monday"].ToString(); string savedTuesdayValue = rowView["Tuesday"].ToString(); if (_subjectDt.Rows.Count != 0) { // 绑定Monday下拉框并设置选中值 DropDownList ddlMonday = (DropDownList)e.Row.FindControl("Monday"); ddlMonday.DataSource = _subjectDt; ddlMonday.DataTextField = "SubjectName"; ddlMonday.DataValueField = "SubjectCode"; ddlMonday.DataBind(); ddlMonday.Items.Insert(0, new ListItem("", "0")); // 如果保存的值不为空且存在于下拉框中,设置选中 if (!string.IsNullOrEmpty(savedMondayValue) && ddlMonday.Items.FindByValue(savedMondayValue) != null) { ddlMonday.SelectedValue = savedMondayValue; } // 绑定Tuesday下拉框并设置选中值 DropDownList ddlTuesday = (DropDownList)e.Row.FindControl("Tuesday"); ddlTuesday.DataSource = _subjectDt; ddlTuesday.DataTextField = "SubjectName"; ddlTuesday.DataValueField = "SubjectCode"; ddlTuesday.DataBind(); ddlTuesday.Items.Insert(0, new ListItem("", "0")); if (!string.IsNullOrEmpty(savedTuesdayValue) && ddlTuesday.Items.FindByValue(savedTuesdayValue) != null) { ddlTuesday.SelectedValue = savedTuesdayValue; } } } }
关键说明
- 缓存科目数据:避免每行绑定都查询数据库,提升页面性能。
- 使用SelectedValue而非SelectedIndex:直接通过保存的
SubjectCode值设置选中,不受下拉框选项顺序变化影响,更稳定。 - 针对当前行处理:在
RowDataBound中只操作当前行(e.Row),保证每行下拉框独立设置选中状态。
内容的提问来源于stack exchange,提问作者Ammar
相关产品推荐
相关产品推荐

