Tło:Ustal, kto oddał wydarzenie
W moim WinForm formie, mam sprawdzone ListView i "master" pole o nazwie checkBoxAll. Zachowanie pana brzmi następująco:
Jeżeli Master jest zaznaczone lub odznaczone, wszystkie ListViewItems należy odpowiednio zmienić.
Jeśli użytkownik odznaczy element ListViewItem, wzorzec musi się odpowiednio zmienić.
Jeśli użytkownik sprawdzi element ListViewItem i wszystkie inne elementy ListViewItems zostaną również sprawdzone, wzorzec musi się odpowiednio zmienić.
Napisałem następujący kod naśladować to zachowanie:
private bool byProgram = false; //Flag to determine the caller of the code. True for program, false for user.
private void checkBoxAll_CheckedChanged(object sender, EventArgs e)
{
//Check if the user raised this event.
if (!byProgram)
{
//Event was raised by user!
//If checkBoxAll is checked, all listviewitems must be checked too and vice versa.
//Check if there are any items to (un)check.
if (myListView.Items.Count > 0)
{
byProgram = true; //Raise flag.
//(Un)check every item.
foreach (ListViewItem lvi in myListView.Items)
{
lvi.Checked = checkBoxAll.Checked;
}
byProgram = false; //Lower flag.
}
}
}
private void myListView_ItemChecked(object sender, ItemCheckedEventArgs e)
{
//Get the appropiate ListView that raised this event
var listView = sender as ListView;
//Check if the user raised this event.
if (!byProgram)
{
//Event was raised by user!
//If all items are checked, set checkBoxAll checked, else: uncheck him!
bool allChecked = true; //This boolean will be used to set the value of checkBoxAll
//This event was raised by an ListViewItem so we don't have to check if any exist.
//Check all items untill one is not checked.
foreach (ListViewItem lvi in listView.Items)
{
allChecked = lvi.Checked;
if (!allChecked) break;
}
byProgram = true; //Raise flag.
//Set the checkBoxAll according to the value determined for allChecked.
checkBoxAll.Checked = allChecked;
byProgram = false; //Lower flag.
}
}
W tym przykładzie używam flagę (byProgram), aby upewnić się, że zdarzenie zostało spowodowane przez użytkownika lub nie , zapobiegając w ten sposób nieskończonej pętli (jedno zdarzenie może wystrzelić inną, która może wystrzelić pierwszą itd. itd.). IMHO, to jest zepsute rozwiązanie. Szukałem, ale nie mogłem znaleźć udokumentowanej metody MSDN w celu ustalenia, czy Zdarzenie Kontroli Użytkownika zostało bezpośrednio uruchomione dzięki użytkownikowi. Co mnie zaskakuje (znowu, IMHO).
Wiem, że FormClosingEventArgs ma pole, którego możemy użyć do określenia, czy użytkownik zamyka formularz, czy nie. Ale o ile wiem, jest to jedyny EventArg który zapewnia tego rodzaju funkcjonalność ...
Tak w skrócie:
Czy istnieje sposób (inne niż moim przykładzie), aby ustalić, czy zdarzenie było zwolniony bezpośrednio przez użytkownika?
Uwaga: Nie mam na myśli nadawcy wydarzenia! Nie ma znaczenia, czy zakodowuję someCheckBox.Checked = true; lub ręcznie ustawić someCheckBox, nadawcą zdarzenia zawsze będzie someCheckBox. Chcę się dowiedzieć, czy możliwe jest ustalenie, czy było to przez użytkownika (kliknięcie), czy przez program (.Checked = true).
Aaand: 30% czasu potrzebnego na napisanie tego pytania było prawidłowe sformułowanie pytania i tytułu. Nadal nie masz pewności, czy jest to 100% czyste, więc edytuj, jeśli myślisz, że możesz zrobić to lepiej :)
Po prostu dzikie domysły, ale naprawdę powinno być coś w EventArgs. Czy sprawdziłeś je w czasie wykonywania (debugowanie)? –
W zdarzeniu kliknięcia ustawia flagę, aby wiedzieć, że to połączenie pochodzi z kliknięcia, a nie według kodu? – MEYWD
Użyj 'nadawcy'? – DGibbs