取消单击某些子复选框时清除 '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;
}
}
我有一个包含多个复选框的表单,还有一个 '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;
}
}