C#中高效刷新DataGridView子集数据并指定显示列的方法
优化DataGridView绑定与列显示的实现方案
一、核心优化逻辑
用_dbContext.Candidates.Local.ToBindingList()绑定后,EF Core的ChangeTracker会自动跟踪实体的新增、修改、删除操作,无需每次调用查询方法刷新数据库,直接就能同步到DataGridView,彻底解决原方案的效率问题。要控制显示指定列,可通过以下几种方式实现:
二、方式一:手动指定DataGridView列(最可控)
- 关闭自动生成列,避免多余列显示
dataGridView1.AutoGenerateColumns = false;
- 手动创建需要显示的列,绑定实体对应属性
// 编号列(绑定Id属性) var idCol = new DataGridViewTextBoxColumn { HeaderText = "编号", DataPropertyName = "Id", // 必须和实体类的属性名完全一致 ReadOnly = true // 根据需求设置是否只读 }; dataGridView1.Columns.Add(idCol); // 名字列(绑定FirstName属性) var firstNameCol = new DataGridViewTextBoxColumn { HeaderText = "名", DataPropertyName = "FirstName" }; dataGridView1.Columns.Add(firstNameCol); // 姓氏列(绑定LastName属性) var lastNameCol = new DataGridViewTextBoxColumn { HeaderText = "姓", DataPropertyName = "LastName" }; dataGridView1.Columns.Add(lastNameCol);
- 绑定数据源(确保先加载初始数据到Local集合)
// 首次加载数据到上下文Local集合 _dbContext.Candidates.Load(); // 绑定到DataGridView dataGridView1.DataSource = _dbContext.Candidates.Local.ToBindingList();
三、方式二:通过实体类属性标记控制列显示
如果不想手动创建列,可通过特性标记实体类属性,控制自动生成列的显示:
- 在实体类中,给不需要显示的属性添加
[Browsable(false)]特性
public class Candidate { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } // 该属性不会在DataGridView中显示 [Browsable(false)] public string Email { get; set; } }
- 开启自动生成列并绑定数据源
dataGridView1.AutoGenerateColumns = true; _dbContext.Candidates.Load(); dataGridView1.DataSource = _dbContext.Candidates.Local.ToBindingList();
这种方式适合只需要隐藏少数属性的场景,若需精确指定显示列,推荐方式一。
四、方式三:投影到DTO类(解耦实体与UI)
如果实体类属性过多,或需要对显示数据做转换,可定义仅包含所需属性的DTO类:
- 创建DTO类
public class CandidateDto { public int Id { get; set; } public string FullName => $"{FirstName} {LastName}"; // 可组合属性 public string FirstName { get; set; } public string LastName { get; set; } }
- 加载数据并投影到DTO集合,同时监听实体变化同步更新
// 初始加载并投影 var dtoList = _dbContext.Candidates .Select(c => new CandidateDto { Id = c.Id, FirstName = c.FirstName, LastName = c.LastName }) .ToList(); // 绑定到BindingList var bindingList = new BindingList<CandidateDto>(dtoList); dataGridView1.DataSource = bindingList; // 监听上下文的实体变化事件,同步更新DTO集合 _dbContext.ChangeTracker.StateChanged += (sender, e) => { if (e.Entry.Entity is Candidate candidate) { // 根据实体状态(新增/修改/删除)更新dtoList和bindingList // 示例:处理修改操作 if (e.Entry.State == EntityState.Modified) { var dto = bindingList.FirstOrDefault(d => d.Id == candidate.Id); if (dto != null) { dto.FirstName = candidate.FirstName; dto.LastName = candidate.LastName; } } } };
这种方式适合需要UI层与实体类解耦的场景,但需要额外处理实体变化的同步逻辑。
五、注意事项
- 使用
Local.ToBindingList()前,必须确保数据已加载到上下文,可通过_dbContext.Candidates.Load()或执行任意查询(如_dbContext.Candidates.ToList())完成初始加载。 - 新增实体后,只需调用
_dbContext.Candidates.Add(newCandidate)并保存上下文,Local集合会自动更新,DataGridView也会同步显示新增行。 - 修改实体后,直接修改实体属性并保存,DataGridView会自动同步修改内容,无需重新查询。
内容的提问来源于stack exchange,提问作者Unis
相关产品推荐
相关产品推荐

