C#中已完成任务列表导航按钮失效问题求助
问题排查与修复方案
核心问题分析
- UI更新逻辑错误:
RefreshData每次执行都重新查库,还在while (reader.Read())循环里直接更新UI,遍历完所有记录后,UI只会显示最后一条的内容。而且每次调用都给下拉框重复加相同选项,导致下拉框数据冗余,还干扰导航计数判断。 - 数据未持久存储:
completedJobs是方法内的局部List,每次调用都重新创建,没法保存所有任务数据,导航时没有可用数据集切换记录。 - 变量作用域错误:初始调用里的
int currentRecord = 0;是局部变量,和类里用于导航的成员变量不是同一个,导致初始值没正确设置,导航逻辑直接失效。 - 导航判断条件错误:
NextRecord用cmbCompleted.Items.Count当总记录数,但下拉框里的项是重复添加的,数量和实际任务数对不上,应该用真实的任务数据集数量判断。
修复方案与代码示例
步骤1:调整类成员变量
在类级别定义存储任务的列表和当前记录索引,确保数据能跨方法复用:
// 类级别的成员变量,保存所有完成的任务数据 private List<CompletedJob> _completedJobs = new List<CompletedJob>(); private int _currentRecord = 0;
步骤2:重构RefreshData方法
把数据查询和UI更新分开,只在首次加载或需要刷新时查库,后续导航直接复用已存数据:
private void RefreshData(bool reloadData = false) { // 仅在需要时重新从数据库加载数据 if (reloadData || _completedJobs.Count == 0) { string connectionString = @"Data Source=localhost\SQLEXPRESS;Initial Catalog=AdvancedProgramming;Integrated Security=True"; _completedJobs.Clear(); using (SqlConnection connection = new SqlConnection(connectionString)) { // 改用JOIN语法,比旧的逗号分隔表可读性更强 string sql = @"SELECT job.Description, job.Price, ass.Name AS AssignedTo, comp.Name AS Completed, cust.Name AS CustomerName FROM dbo.Jobs job INNER JOIN dbo.Completeds comp ON comp.Id = job.Completed INNER JOIN dbo.Customers cust ON job.CustomerId = cust.Id -- 假设Jobs表有CustomerId关联Customers INNER JOIN dbo.AssignedToes ass ON job.AssignedToId = ass.Id -- 假设Jobs表有AssignedToId关联AssignedToes WHERE comp.Name = 'Complete'"; using (SqlCommand command = new SqlCommand(sql, connection)) { connection.Open(); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { string jobDescription = reader.GetString(0); decimal jobPrice = reader.GetDecimal(1); string assignedTo = reader.GetString(2); string jobStatus = reader.GetString(3); string customerName = reader.GetString(4); CompletedJob compJob = new CompletedJob(customerName, jobDescription, jobPrice, assignedTo, jobStatus); _completedJobs.Add(compJob); } } } } // 初始化下拉框选项(只加载一次,避免重复添加) InitializeComboBoxes(); } // 根据当前索引更新UI显示 UpdateUIWithCurrentRecord(); } // 初始化下拉框,自动去重 private void InitializeComboBoxes() { cmbCustomer.Items.Clear(); cmbAssignedTo.Items.Clear(); cmbCompleted.Items.Clear(); var uniqueCustomers = _completedJobs.Select(j => j.CustomerName).Distinct(); var uniqueAssignedTo = _completedJobs.Select(j => j.AssignedTo).Distinct(); var uniqueStatuses = _completedJobs.Select(j => j.JobStatus).Distinct(); foreach (var cust in uniqueCustomers) cmbCustomer.Items.Add(cust); foreach (var ass in uniqueAssignedTo) cmbAssignedTo.Items.Add(ass); foreach (var status in uniqueStatuses) cmbCompleted.Items.Add(status); } // 根据当前索引更新UI控件内容 private void UpdateUIWithCurrentRecord() { if (_completedJobs.Count == 0 || _currentRecord < 0 || _currentRecord >= _completedJobs.Count) return; var currentJob = _completedJobs[_currentRecord]; cmbCustomer.SelectedItem = currentJob.CustomerName; txtDescription.Text = currentJob.JobDescription; txtPrice.Text = currentJob.JobPrice.ToString(); cmbAssignedTo.SelectedItem = currentJob.AssignedTo; cmbCompleted.SelectedItem = currentJob.JobStatus; }
步骤3:修复导航按钮逻辑
基于存储的_completedJobs列表数量判断导航边界,直接更新UI无需重新查库:
private void PreviousRecord(object sender, RoutedEventArgs e) { if (_currentRecord > 0) { _currentRecord--; UpdateUIWithCurrentRecord(); } } private void NextRecord(object sender, RoutedEventArgs e) { if (_currentRecord < _completedJobs.Count - 1) { _currentRecord++; UpdateUIWithCurrentRecord(); } }
步骤4:修正初始调用代码
// 初始加载数据,强制从数据库拉取 RefreshData(reloadData: true); // 类成员变量_currentRecord默认初始为0,不用再定义局部变量
额外优化建议
- 用参数化查询:哪怕当前没用户输入,养成习惯能避免SQL注入风险。
- 把连接字符串放到配置文件(比如App.config)里,别硬编码,方便后续修改。
- 加异常处理:在数据库操作部分加try-catch块,处理连接、读取等异常,提升程序稳定性。
内容的提问来源于stack exchange,提问作者ash1997
相关产品推荐
相关产品推荐

