Различия между пользователем, изменяющим значение Checkbox.Checked, или программным изменением
Я вижу, что флажки имеют событие CheckedChanged. можно ли определить, было ли оно изменено программно или пользователем, действительно проверяющим флажок?
У меня есть большая сетка, в которой пользователь может ввести фильтр, или использовать флажки для своего рода "быстрого фильтра", который предлагает общие параметры фильтрации. Затем скажите, что они идут и меняют фильтр через текстовое поле, я проверял, должен ли я программно (un) проверять элементы управления CheckBox, чтобы он отражал фильтр в текстовом поле.
private void genericCheckbox_CheckedChanged(object sender, EventArgs e)
{
UpdateFilter();
}
private void UpdateFilter()
{
if (gdcSVNDefaultView.RowCount == 0)
return;
gdcSVNDefaultView.ActiveFilterString = BuildTableFilter();
gdcSVNDefaultView.BestFitColumns();
}
private void gdcSVNDefaultView_ColumnFilterChanged(object sender, EventArgs e)
{
lblTotalFileCount.Text = gdcSVNDefaultView.RowCount.ToString();
if (gdcSVNDefaultView.ActiveFilterString.Contains("Normal"))
cheNormalFiles.Checked = true;
else
cheNormalFiles.Checked = false;
if (gdcSVNDefaultView.ActiveFilterString.Contains("bin") ||
gdcSVNDefaultView.ActiveFilterString.Contains("obj"))
cheBinObjFolders.Checked = true;
else
cheBinObjFolders.Checked = false;
}
С некоторыми очень легкими испытаниями, это, кажется, работает так, как я хочу. Но я боюсь, что существует какой-то случай с "бесконечным циклом", в котором событие ColumnFilterChanged будет срабатывать из-за вызова метода UpdateFilter при возникновении события CheckedChanged, что, в свою очередь, может привести к тому, что CheckedChange произойдет снова, поскольку ColumnFilterChanged управляет флажками.
Ответы
Ответ 1
Я бы, наверное, отсоединил, а затем снова привязал обработчик, например.
private void gdcSVNDefaultView_ColumnFilterChanged(object sender, EventArgs e)
{
cheNormalFiles.CheckedChanged -= genericCheckbox_CheckedChanged;
cheBinObjFolders.CheckedChanged -= genericCheckbox_CheckedChanged;
// do stuff...
cheNormalFiles.CheckedChanged += genericCheckbox_CheckedChanged;
cheBinObjFolders.CheckedChanged += genericCheckbox_CheckedChanged;
}
Ответ 2
Использование flag
для этой цели в порядке:
bool suppressCheckedChanged;
private void gdcSVNDefaultView_ColumnFilterChanged(object sender, EventArgs e)
{
suppressCheckedChanged = true;
//.... your own code
//....
suppressCheckedChanged = false;
}
private void genericCheckbox_CheckedChanged(object sender, EventArgs e)
{
if(suppressCheckedChanged) return;
UpdateFilter();
}
UPDATE
Использование flag
- лучший способ (самый сжатый и удобный), я думаю. Однако после некоторого поиска в внутренней реализации CheckBox.cs, я обнаружил, что используется внутреннее поле checkState. свойство Checked
предназначено только для удобства. Событие CheckedChanged
возникает в настройщике свойства CheckState
. Поэтому, изменяя поле CheckState
, мы обходим CheckedChanged
event raiser. Поскольку поле CheckState
не является общедоступным, мы должны использовать Reflection
для изменения его значения. Вот почему этот код немного длиннее по сравнению с использованием flag
.
Это код для вас, обратите внимание, что это всего лишь ссылка на широкое распространение знаний по этой проблеме, так как я сказал, что использование flag
гораздо более кратким и код также является когерентным:
//Use this extension method for convenience
public static class CheckBoxExtension {
public static void SetChecked(this CheckBox chBox, bool check){
typeof(CheckBox).GetField("checkState", BindingFlags.NonPublic |
BindingFlags.Instance)
.SetValue(chBox, check ? CheckState.Checked :
CheckState.Unchecked);
chBox.Invalidate();
}
}
//then you can use the SetChecked method like this:
checkBox1.SetChecked(true);//instead of checkBox1.Checked = true;
checkBox1.SetChecked(false);//instead of checkBox1.Checked = false;
Ответ 3
В общем случае вы можете использовать событие Click CheckBoxName_Click, которое вызывается только тогда, когда пользователь нажимает на этот флажок (а не когда вы устанавливаете флажок checked из кода), как указывает название события.