绑定表单计算字段处理及BindingSource首次赋值不触发PositionChanged问题
问题1解答
直接调用事件处理方法不会干扰.NET内部运行机制,也不会引发内存泄漏、栈异常这类问题:
- 事件处理方法本质上就是普通的实例方法,手动调用和.NET运行时触发调用的执行逻辑完全一致,唯一区别仅在于
sender参数的传入值 - 你的代码逻辑中并没有使用
sender参数,传入null完全不会影响执行结果,也不会产生额外的资源引用或者调用栈溢出风险
问题2解答
有几个更合理的实现方案,既可以覆盖初始化场景,也能避免不必要的频繁触发:
- 先抽离公共刷新逻辑
把展示更新的逻辑从事件处理方法中抽成独立方法,避免和事件逻辑耦合,后续不管是事件触发还是手动调用都用这个方法:
private void RefreshApprovalDisplay() { var drv = talsBindingSource.Current as DataRowView; if (drv != null) { ctlBoundCheckButton1.lblText = $"Submitted {drv.Row.Field<DateTime>("SubmitDate").ToString("MM/dd/yy hh:mm tt")}"; ctlBoundCheckButton1.setControls(true); // 未审批时清空按钮状态,避免残留上一条记录的内容 ctlBoundCheckButton2.setControls(false); if (drv.Row.Field<bool>("Approved")) { var sup = talsSupervisorsBindingSource.Current as DataRowView; ctlBoundCheckButton2.lblText = $"Approved by {sup.Row.Field<string>("FullName")} on {drv.Row.Field<DateTime>("ApproveDate").ToString("MM/dd/yy")}"; ctlBoundCheckButton2.setControls(true); } } else { using (DialogCenteringService centeringService = new DialogCenteringService(this)) { MessageBox.Show("No TALs to Approve", "Confirm", MessageBoxButtons.OK); } Close(); } }
原来的事件处理方法直接调用这个公共方法即可:
private void ctlNavBar1_displayCurrent(object sender, EventArgs e) { RefreshApprovalDisplay(); }
- 精准监听字段变更,避免无效触发
不要用CurrentItemChanged这类泛用事件,直接监听DataTable的ColumnChanged事件,只有当你关心的审批相关字段实际发生变更时才触发刷新:
public TALsApprove() { InitializeComponent(); talsTableAdapter.FillForApproval(timeTrackDataSet.TALs, User.ID); usersTableAdapter.FillBySupervisor(timeTrackDataSet.Users, User.ID); timeSlipsTableAdapter.FillBySupervisor(timeTrackDataSet.TimeSlips, User.ID); // 注册字段变更监听,仅处理审批相关字段的变更 timeTrackDataSet.TALs.ColumnChanged += (s, e) => { if (e.Column.ColumnName is nameof(timeTrackDataSet.TALs.SubmitDate) or nameof(timeTrackDataSet.TALs.Approved) or nameof(timeTrackDataSet.TALs.ApproveDate)) { RefreshApprovalDisplay(); } }; ctlNavBar1.displayCurrent += ctlNavBar1_displayCurrent; ctlNavBar1.bindingSource = talsBindingSource; // 构造函数末尾直接调用一次刷新,不需要等Shown事件(除非你的UI有布局依赖显示后的尺寸) RefreshApprovalDisplay(); }
这个方案可以完全避免不必要的刷新触发,只有当记录切换、或者审批相关字段实际修改时才会更新UI。
内容的提问来源于stack exchange,提问作者RobertSF
相关产品推荐
相关产品推荐

