我在表单上有一些控件:
- 一个复选框,负责根据选中状态启用/禁用页面上的所有其他控件。
- 一些单选按钮,负责根据选中状态启用/禁用页面上的特定控件。
- 由上述控件操作的其他控件。
出现了几种情况:
- 当表单初始化时,我加载复选框的状态。然后,它启用或禁用表单上的其余控件。
- 随着表单继续初始化,我加载了单选按钮的状态。如果单选按钮被选中但被禁用,这有机会撤销之前的要求。因此,我先检查以确保单选按钮已启用。
- 加载表单后,用户可以选中或取消选中单选按钮。这是一个微不足道的案例,我只是运行了满足最后一个要求的代码。但是,另一种情况是用户可以选中/取消选中该复选框。当复选框启用时,它想要重新启用页面上的所有控件,因为它禁用了它们。不过,这样做会违反单选按钮的要求。
这种情况用蛮力处理是微不足道的。我创建了几种方法来突出显示:
private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
snmpSettingsErrorProvider.Clear();
foreach (Control control in grpBxSNMPv3.Controls)
{
if (control != sender)
control.Enabled = ((CheckBox)sender).Checked;
}
}
private void rdBtnAuthNoPriv_CheckedChanged(object sender, EventArgs e)
{
RadioButton authNoPrivRadioButton = ((RadioButton)sender);
if (authNoPrivRadioButton.Enabled)
{
bool isChecked = authNoPrivRadioButton.Checked;
SetControlState(cmbBxAuthProtocol, isChecked);
SetControlState(mskdTxtBxAuthPassword, isChecked);
SetControlState(mskdTxtBxAuthPasswordConfirm, isChecked);
SetControlState(cmbBxPrivacyProtocol, !isChecked);
SetControlState(mskdTxtBxPrivacyPassword, !isChecked);
SetControlState(mskdTxtBxPrivacyPasswordConfirm, !isChecked);
}
}
//More methods for other checkedChange and also for when rdBtn's enable.
布局的大概思路:
综上所述,我的问题很“简单”:
- 方法应该在没有其他方法存在的假设下起作用。然而,如果我保留 rdBtn 对 chkBx 存在的逻辑判断,那么我将拥有必须相互对抗的代码。
我可以这样写我的代码:
private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
snmpSettingsErrorProvider.Clear();
txtBxEngineID = ((CheckBox)sender).Checked;
rdBtnAuthNoPriv = ((CheckBox)sender).Checked;
rdBtnAuthPriv = ((CheckBox)sender).Checked;
rdBtnNoAuthNoPriv = ((CheckBox)sender).Checked;
//Pass work for enabling Auth and Priv fields to rdBtn events.
}
此解决方案效率更高,并保证我不会看到任何闪烁。然而,这也意味着为了“成功完成”启用页面上的所有控件,我的 chkBx 现在必须依赖 rdBtn 的逻辑。这是好的编程习惯吗?
最佳答案
我认为这是保留在表单中的合理代码,但我会提出一些建议;
1) 强制转换的处理成本很小,因此您应该避免在循环内强制转换。事实上,作为一般概念,当结果保证保持不变时,您应该避免在循环内执行任何重复操作。所以你可以像这样改进你的第一个方法;
private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
snmpSettingsErrorProvider.Clear();
// cast the sender once only
CheckBox cb = sender as CheckBox;
if (null == cb) return;
foreach (Control control in grpBxSNMPv3.Controls)
{
if (control != sender)
control.Enabled = cb.Checked;
}
}
2) 我建议将启用/禁用逻辑移出到一个单独的方法中,然后从您的控件事件处理程序中调用它。如果您决定从其他控件重用相同的逻辑,这将使您能够重用。紧密耦合行为以控制事件,我发现会导致重复代码。像这样;
private void ChkBxSnmPv3OnCheckedChanged(object sender, EventArgs eventArgs)
{
snmpSettingsErrorProvider.Clear();
// cast the sender once only
CheckBox cb = sender as CheckBox;
if (null == cb) return;
SetEnabled(grpBxSNMPv3, cb.Checked, new[] { cb });
}
private void SetEnabled(Control parent, bool isEnabled, Control[] exludeControls)
{
if (null == parent) return;
foreach (Control control in parent.Controls)
{
if (!excludeControls.Contains(control))
control.Enabled = isEnabled;
}
}
您现在有一个可重用的方法来启用/禁用另一个包含的所有控件。
3) 关于您的最后一个问题,是的,我认为这种方法很好。减少耦合总是一件好事。想想如何设计您的方法以提高可重用性,我认为您会想出一个干净的解决方案。
关于c# - 将职责委派给 WinForm 控件——控件是否应该了解彼此的操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10690010/