我有两个CheckBoxList
:primaryAntennas
和secondaryAntennas
检查索引为X的主天线时,应禁用索引为X的辅助天线(即检查主天线#1,禁用辅助天线#1)。反向,应该以同样的方式工作。通过将复选框设置为CheckState.Indeterminate
我很快发现,您可以点击Indeterminate
复选框,其状态将设置为CheckState.Unchecked
。
为了解决这个问题,我在点击处理程序中添加了一个检查,它将复选框重置为不确定状态:
if (e.CurrentValue == CheckState.Indeterminate)
{
this.primaryAntennas.ItemCheck -= this.primaryAntennas_ItemCheck;
// set it back to indeterminate state
this.primaryAntennas.SetItemCheckState(e.Index, CheckState.Indeterminate);
this.primaryAntennas.ItemCheck += this.primaryAntennas_ItemCheck;
return;
}
仍然,点击处理程序完成后,取消选中复选框。
这里是点击处理程序的完整代码:
(您可能会注意到我显式未分配事件处理程序,因为调用自身可以创建一个无限循环。此外,事件处理程序可以相互调用,创建另一种无限循环的可能性)
private void primaryAntennas_ItemCheck(object sender, ItemCheckEventArgs e)
{
//check if checkbox is indeterminate
if (e.CurrentValue == CheckState.Indeterminate)
{
this.primaryAntennas.ItemCheck -= this.primaryAntennas_ItemCheck;
// set it back to indeterminate state
this.primaryAntennas.SetItemCheckState(e.Index, CheckState.Indeterminate);
this.primaryAntennas.ItemCheck += this.primaryAntennas_ItemCheck;
return;
}
// if the item was checked
// disable the secondary antenna with the same index
if (e.NewValue == CheckState.Checked)
{
// disable the secondary antenna
this.secondaryAntennas.ItemCheck -= this.secondaryAntennas_ItemCheck;
secondaryAntennas.SetItemCheckState(e.Index, CheckState.Indeterminate);
this.secondaryAntennas.ItemCheck += this.secondaryAntennas_ItemCheck;
return;
}
// if the item was unchecked
// disable the primary antenna with the same index
if (e.NewValue == CheckState.Unchecked)
{
// check to make sure it does not belong to other portal
if (_myConfig.secondaryAntessasUsed[e.Index] == -1)
{
// disable even
this.secondaryAntennas.ItemCheck -= this.secondaryAntennas_ItemCheck;
// uncheck the antenna
secondaryAntennas.SetItemCheckState(e.Index, CheckState.Unchecked);
this.secondaryAntennas.ItemCheck += this.secondaryAntennas_ItemCheck;
return;
}
}
}// end of primaryAntennas_ItemCheck()
答案 0 :(得分:4)
这是一种伪造复选框“禁用”状态的新方法。不太确定你会为你的用户提供帮助,更容易让它独占,检查一个取消选中另一个。但是,从技术上讲,只需强制e.NewValue状态,这样点击就没有任何效果了。
为两个CheckedListBox提供相同的事件处理程序:
private bool updatingChecks;
private void checkedListBoxes_ItemCheck(object sender, ItemCheckEventArgs e) {
if (updatingChecks) return;
updatingChecks = true;
var otherBox = sender == checkedListBox1 ? checkedListBox2 : checkedListBox1;
if (otherBox.GetItemCheckState(e.Index) == CheckState.Checked) e.NewValue = e.CurrentValue;
else if (e.NewValue == CheckState.Checked) otherBox.SetItemCheckState(e.Index, CheckState.Indeterminate);
else if (e.NewValue == CheckState.Unchecked) otherBox.SetItemChecked(e.Index, false);
updatingChecks = false;
}
对我来说更有意义的版本,它不会忽略用户的点击:
private void checkedListBoxes_ItemCheck(object sender, ItemCheckEventArgs e) {
var otherBox = sender == checkedListBox1 ? checkedListBox2 : checkedListBox1;
if (e.NewValue == CheckState.Checked) otherBox.SetItemChecked(e.Index, false);
}
请确保您实际上并不打算实施RadioButtons。当然看起来像。
答案 1 :(得分:1)
在事件处理程序中使用SetItemCheckState
将不起作用。相反,您需要在事件参数上设置NewValue
属性。
if (e.CurrentValue == CheckState.Indeterminate)
{
e.NewValue = CheckState.Indeterminate;
return;
}
这另外修复了你的递归问题,因为它在现有事件中起作用而不是触发新事件。
答案 2 :(得分:0)
这可能会强制用户取消选中列表框选项
private void checkedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
{
if (e.CurrentValue == CheckState.Indeterminate && e.NewValue != CheckState.Indeterminate)
{
e.NewValue = CheckState.Indeterminate;
checkedListBox.SetItemCheckState(e.Index, CheckState.Indeterminate);
return;
}
}
答案 3 :(得分:-1)
一种解决方案是对每个复选框使用ItemChecked事件来设置其他复选框项的值。为了使这项工作,我们需要跟踪用户点击一个方框是否触发了ItemChecked事件,还是通过其他ItemChecked事件中的代码来跟踪。
此外,由于两个ItemCheck事件中的代码几乎相同,我为它创建了一个单独的方法,它接收“其他”复选框(要更改的复选框)以及事件参数。
我将如何做到这一点:
private bool userTriggered = true; // True means the user is triggering the event
private void primaryAntennas_ItemCheck(object sender, ItemCheckEventArgs e)
{
// If triggered by other ItemCheck method, let the change take place...
if (!userTriggered) return;
// Otherwise we process it and update the other CheckedListBox
processItemCheckEvent(this.secondaryAntennas, e);
}
private void secondaryAntennas_ItemCheck(object sender, ItemCheckEventArgs e)
{
// If triggered by other ItemCheck method, let the change take place...
if (!userTriggered) return;
// Otherwise we process it and update the other CheckedListBox
processItemCheckEvent(this.primaryAntennas, e);
}
private void processItemCheckEvent(CheckedListBox otherCheckedListBox, ItemCheckEventArgs e)
{
// Ignore user changes if we're 'disabled'
if (e.CurrentValue == CheckState.Indeterminate)
{
e.NewValue = CheckState.Indeterminate;
}
// Otherwise change the other check box
else
{
// Now we're manipulating the other checkedListBox,
// so set userTriggered to false
userTriggered = false;
if (e.NewValue == CheckState.Checked)
{
otherCheckedListBox.SetItemCheckState(e.Index, CheckState.Indeterminate);
}
else
{
otherCheckedListBox.SetItemCheckState(e.Index, CheckState.Unchecked);
}
// And set it back again now
userTriggered = true;
}
}