C#复选框冗余
我有复选框,当选中时,我希望按钮为真。若所有复选框均未选中,则按钮为false。现在我遇到的问题是,他们是否有一种方法可以在一个代码中完成这项工作,而不是在所有框中键入。我只包括前两个盒子,因为所有盒子都一样。我是个书呆子,这都是从youtube和你的论坛上学习C#2-3天的经历C#复选框冗余,c#,winforms,C#,Winforms,我有复选框,当选中时,我希望按钮为真。若所有复选框均未选中,则按钮为false。现在我遇到的问题是,他们是否有一种方法可以在一个代码中完成这项工作,而不是在所有框中键入。我只包括前两个盒子,因为所有盒子都一样。我是个书呆子,这都是从youtube和你的论坛上学习C#2-3天的经历 这取决于您所说的所有复选框的含义。假设所有的复选框都直接位于表单中(与表单中的其他容器相反) 在这种情况下,您可以编写一个通用函数,如下所示 private static bool IsOneChecked(Contr
这取决于您所说的所有
复选框的含义。假设所有的复选框都直接位于表单中(与表单中的其他容器相反)
在这种情况下,您可以编写一个通用函数,如下所示
private static bool IsOneChecked(Control parent) {
return parent.Controls.OfType<CheckBox>().Any(box => box.Checked);
}
butInstall.Enabled = IsOneChecked(this);
此
表示包含所有复选框的容器实例
。您可以根据表单的布局方式对其进行调整。如果
复选框跨越多个容器,您可以展开
IsOneChecked功能以查找所有相关的
复选框`
现在我遇到的问题是,他们是否有一种方法可以在一个代码中完成这项工作,而不是在所有框中键入。我只包括前两个盒子,因为所有盒子都一样
你的直觉是,如果你多次输入同一个代码,就会出现严重错误,这是正确的,因为你的直觉很好
处理这个问题的方法是将代码抽象为一个方法:
private void CheckedChanged(CheckBox box)
{
if (box.Checked == true)
butInstall.Enabled = true;
else if
(boxChrome.Checked == false &
boxAdobeReader.Checked == false &
boxESET.Checked == false &
boxiTunes.Checked == false &
boxQuicktime.Checked == false &
boxTeamviewer.Checked == false &
boxWinrar.Checked == false &
boxVLC.Checked == false)
butInstall.Enabled = false;
}
private void boxChrome_CheckedChanged(object sender, EventArgs e) =>
CheckChanged(boxChrome);
private void boxAdobereader_CheckedChanged(object sender, EventArgs e) =>
CheckChanged(boxAdobeReader);
好的。我们能做得更好吗?天哪,是的
首先:在C#中,只有新手才会说
if (box.Checked == true)
boxChrome.Checked == false
这意味着“如果这件事是真的,那么”,这是疯狂的。只要说“如果这件事是真的,那么”
如果它是真的,那么它已经是真的了。您不需要检查true是否等于true
同样,只有新手才会说
if (box.Checked == true)
boxChrome.Checked == false
如果您想知道是否有错误,请使用NOT
运算符:
!boxChrome.Checked
好了,现在我们有了
private void CheckedChanged(CheckBox box)
{
if (box.Checked)
butInstall.Enabled = true;
else if (
!boxChrome.Checked & !boxAdobeReader.Checked &
!boxESET.Checked & !boxiTunes.Checked &
!boxQuicktime.Checked & !boxTeamviewer.Checked &
!boxWinrar.Checked & !boxVLC.Checked))
butInstall.Enabled = false;
}
那就好多了
我们能做得更好吗?当然我们可以注意到,“所有这些事情都是假的吗?”与“这些事情中有一件是真的,这是假的吗?”
所以这更容易阅读。我注意到,您也可以使用|
而不是|
,尽管在这种情况下,它实际上没有什么区别
我们能做得更好吗?当然我们到底想查什么?我们试图表达“是否有未检查的框?”的概念,所以我们可以使用LINQ序列操作符来回答这个问题。创建一个包含方框的字段:
private CheckBox[] boxes;
在表单加载方法中,初始化字段:
...
boxes = { boxChrome, boxAdobeReader, ... }
...
现在我们可以使用这个:
private void CheckedChanged(CheckBox box)
{
if (box.Checked)
butInstall.Enabled = true;
else if (!boxes.Any(box => box.Checked))
butInstall.Enabled = false;
}
现在代码读起来像它的意图如果选中了特定框,则启用该按钮;如果没有任何复选框,则禁用该按钮“。尝试找到一种方法,使您的代码按照其意图阅读。它将更短,更容易理解,而且更有可能是正确的
总是问自己“我能做得更好吗?”?“例如,我们能否自动生成复选框集?我对Vikhram答案的评论给出了一个很好的建议。这个问题有很多解决方案,但这里有一个想法。制作一个复选框列表,在更新复选框时,更新主复选框。您可以检查列表中已检查的内容。如果添加复选框,则只需将其添加到列表中
var checkBoxes = new List<CheckBox>();
checkBoxes.Add(boxAdobeReader);
... // add the others.
private void UpdateMasterCheckBoxState(){
masterButton.IsChecked = checkboxes.Any((cbox) => cbox.IsChecked == true );
}
private void anyCheckBox_CheckedChanged(object sender, EventArgs e)
{
UpdateMasterCheckBoxState();
}
请注意,VisualStudio
标记是为有关VisualStudio的问题保留的。标签:“如果您对VisualStudio的特性和功能有特定的问题,而不仅仅是关于代码的问题,请使用此标签”为什么不让所有复选框触发相同的事件。然后,该事件将选中更改按钮所需的所有复选框。我将如何将其记录下来?很抱歉,这一切都还不熟悉。您应该了解WPF数据绑定、命令、转换器等。之后,您可以轻松解决您的问题。这是Winforms还是WPF?很抱歉,“所有复选框”是表单中的所有框。你的答案和我在这个网站上找到的一张表格很相似,但我无法理解。@臭名昭著你的评论是什么意思。。?如果你不明白。。然后,我建议您仔细阅读lambda表达式,并理解Controls类比parent.Controls.Cast()更好。Any(…)
是parent.Controls.OfType().Any(cb=>cb.Checked)
您可以进一步修复它。如果您将lambda设置为类型
@EricLippert,则无需在lambda内部进行is
检查,谢谢!又修好了。这就是匆忙工作的结果:)这是一个很棒的答案,非常感谢!这是一个关于思考过程和做同一件事的不同方法的很好的演练。这是一个非常详细的答案,你特意给了我一些建议。非常感谢你,先生。我还没有尝试过,但会尝试一下,然后发布我的结果!
var checkBoxes = new List<CheckBox>();
checkBoxes.Add(boxAdobeReader);
... // add the others.
private void UpdateMasterCheckBoxState(){
masterButton.IsChecked = checkboxes.Any((cbox) => cbox.IsChecked == true );
}
private void anyCheckBox_CheckedChanged(object sender, EventArgs e)
{
UpdateMasterCheckBoxState();
}
<CheckBox Click="anyCheckbox_CheckedChanged">AdobeReader</Checkbox>
private void AdobeCheckBox_CheckedChanged(object sender, EventArgs e)
{
DoAdobeOnlyStuff();
UpdateMasterCheckBoxState();
}