取消单击某些子复选框时清除 'All' 复选框?

Clear the 'All' checkbox when some of the sub-checkboxes have been un-clicked?

我有一个包含多个复选框的表单,还有一个 'All' 复选框,当然,它会填充或清空其余部分。我 运行 遇到的问题是,一旦取消选中其中一个子框,我需要它取消选中 'All' 框。目前我似乎无法理解如何执行此操作的逻辑,因此将不胜感激任何提示。

这是项目那部分的代码:

public partial class SrsSelectForm : Form
{

/// Property to return the full SRS names for checked items

public List<string> SelectedSrs
{
  get
  {
    return (from cb in checkBoxes
            where cb.Checked
            select cb.Tag.ToString()).ToList();
  }
}

/// <summary>
/// Unique Srs full names for all setting nodes on the current device
/// </summary>
private HashSet<string> allSrs;

/// <summary>
/// Tracks the checkboxes generated for the available SRS
/// </summary>
private List<CheckBox> checkBoxes;

/// <summary>
/// Constructor
/// </summary>
public SrsSelectForm()
{
  InitializeComponent();

  allSrs = new HashSet<string>();
  checkBoxes = new List<CheckBox>();
}

/// <summary>
/// Event handler
/// </summary>
/// <param name="sender">this form</param>
/// <param name="e">Event args</param>
private void FormLoad(object sender, EventArgs e)
{
  // center on parent
  Utilities.SetFormLocation(this);
}

/// <summary>
/// Retrieves available SRS for the setting nodes and creates check boxes
/// for selection 
/// </summary>
/// <param name="device">currently loaded device</param>
/// <param name="folder">the user's selected output folder</param>
/// <param name="node">starting settings node</param>
public void Populate(IDevice device, string folder, TreeNode node)
{
  // find all Srs output file names
  GetSrsNames(device, folder, node);

  // generate controls for them
  CreateSrsControls();
}

/// <summary>
/// Generates checkboxes for available SRS
/// </summary>
private void CreateSrsControls()
{
  int xPos = 8;
  int yPos = 55;
  int height = 24;

  foreach (string srsPath in allSrs)
  {
    CheckBox cb = new CheckBox();

    cb.AutoSize = true;
    cb.Location = new Point(xPos, yPos);

    // friendly name
    cb.Text = Utilities.GetSrsGroupName(srsPath);

    // store full name for returning to caller
    cb.Tag = srsPath;

    cb.Checked = true;

    grpSrs.Controls.Add(cb);
    checkBoxes.Add(cb);

    yPos += height;
  }
}

/// <summary>
/// Finds all Srs for the settings tree
/// </summary>
/// <param name="device">the currently loaded device</param>
/// <param name="folder">the selected export folder</param>
/// <param name="node">a tree node</param>
private void GetSrsNames(IDevice device, string folder, TreeNode node)
{
  if (node.Tag is DeviceDefinitionNodeValue)
  {
    var nodeValue = (DeviceDefinitionNodeValue)node.Tag;

    if (nodeValue.IsRelayGroup)
    {
      string fileName = string.Empty;
      if (Utilities.GetUsableSrsFileName(device, nodeValue, folder, ref fileName))
      {
        allSrs.Add(fileName);
      }
    }
  }

  // recurse
  foreach (TreeNode subNode in node.Nodes)
  {
    GetSrsNames(device, folder, subNode);
  }
}

/// <summary>
/// Toggles the SRS checkboxes in response to the All c/b changing
/// </summary>
/// <param name="sender">checkbox control</param>
/// <param name="e">event args</param>
private void CheckedOptionChanged(object sender, EventArgs e)
{
  if (sender == cbAll)
  {
    foreach (var cb in checkBoxes)
    {
      cb.Checked = cbAll.Checked;
    }
  }
}

假设您已将每个必需的复选框放入复选框列表。

if(!fromSubCheckBoxes)
foreach(CheckBox cb in checkBoxes)
    if(cbAll.Checked)
        cb.Checked = true;
    else
        cb.Checked = false;

LINQ

if(!fromSubCheckBoxes)
    checkboxes.ForEach(o => o.Checked = cbAll.Checked);

选中项目后设置 cbAll 框。

关于 子清单检查已更改

if (checkboxes.Any(o => !o.Checked) && cbAll.Checked){
    fromSubCheckBoxes = true;
    cbAll.Checked = false;
    fromSubCheckBoxes = false;
}

这将触发您的 cbAll 复选框 CheckedChanged 事件。因此,在您的 cbAll CheckedChanged 事件中抛出一个布尔值,以确保它不会被 CheckBoxList 或您的子复选框触发。

您可能应该为每个复选框勾选 CheckBox.CheckChanged。您实际上已经声明了此事件处理程序,但我看不到您在哪里有任何复选框挂钩。但无论如何 - 只需检查复选框是否为 "all checkbox",如果不是,则对所有复选框执行所需的逻辑。我假设这将是取消选中所有复选框,尽管您可以包含逻辑以查看它们是否也已全部选中,在这种情况下您可能想要实际检查 "all checkbox".

代码:

private void CreateSrsControls()
{
  int xPos = 8;
  int yPos = 55;


 int height = 24;

  foreach (string srsPath in allSrs)
  {
      CheckBox cb = new CheckBox();

      cb.AutoSize = true;
      cb.Location = new Point(xPos, yPos);

      // friendly name
      cb.Text = Utilities.GetSrsGroupName(srsPath);

      // store full name for returning to caller
      cb.Tag = srsPath;

      cb.Checked = true;

      // NEW CODE
      cb.CheckedChanged += CheckedOptionChanged;

      grpSrs.Controls.Add(cb);
      checkBoxes.Add(cb);

      yPos += height;
    }
  }

private void CheckedOptionChanged(object sender, EventArgs e)
{
  if (sender == cbAll)
  {
    foreach (var cb in checkBoxes)
    {
      cb.Checked = cbAll.Checked;
    }
  }
  else
  {
     // make sure setting this doesn't fire the event again
     cbAll.CheckedChanged -= CheckedOptionChanged;
     // this would uncheck it anytime the others are changed
     cbAll.Checked = CheckState.Unchecked;
     //now resubscribe
     cbAll.CheckedChanged += CheckedOptionChanged;
  }
}

如果我对您的 post 理解正确,您实际上是想根据是否选中其他复选框来切换“全部”复选框的状态。

如果是这样,考虑修改如下方法:

private void CheckedOptionChanged(object sender, EventArgs e)
{
  if (sender == cbAll)
  {
    foreach (var cb in checkBoxes)
    {
      cb.Checked = cbAll.Checked;
    }
  }
  else
  {
     cbAll.Checked = !checkBoxes.Any(cb => cb.Checked);
  }
}

当然,这假设您的所有复选框都使用它作为它们的检查更改处理程序。

在您的 CheckedOptionChanged 中,只需添加 else 代码:

private void CheckedOptionChanged(object sender, EventArgs e)
{
  if (sender == cbAll)
  {
    foreach (var cb in checkBoxes)
    {
      cb.Checked = cbAll.Checked;
    }
  }
  else if (!((Checkbox)sender).Checked)
  {
    cbAll.Checked = false;
  }
}