C#复选框冗余

C#复选框冗余,c#,winforms,C#,Winforms,我有复选框,当选中时,我希望按钮为真。若所有复选框均未选中,则按钮为false。现在我遇到的问题是,他们是否有一种方法可以在一个代码中完成这项工作,而不是在所有框中键入。我只包括前两个盒子,因为所有盒子都一样。我是个书呆子,这都是从youtube和你的论坛上学习C#2-3天的经历 这取决于您所说的所有复选框的含义。假设所有的复选框都直接位于表单中(与表单中的其他容器相反) 在这种情况下,您可以编写一个通用函数,如下所示 private static bool IsOneChecked(Contr

我有复选框,当选中时,我希望按钮为真。若所有复选框均未选中,则按钮为false。现在我遇到的问题是,他们是否有一种方法可以在一个代码中完成这项工作,而不是在所有框中键入。我只包括前两个盒子,因为所有盒子都一样。我是个书呆子,这都是从youtube和你的论坛上学习C#2-3天的经历


这取决于您所说的所有
复选框的含义。假设所有的
复选框都直接位于表单中(与表单中的其他容器相反)

在这种情况下,您可以编写一个通用函数,如下所示

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();
}