Reputation: 41
I'm having a problem with a ListView ItemSelectionChanged
event being called twice. From searching I've found it's because the event is being called when an item is selected and again when an item is deselected. I only want it to fire when an item is selected, not when it's deselected. The solution seems to have an if(e.IsSelected)
at the beginning of the event so it's only called when an item is selected, but that's not working for me in this case. Here's the basic structure of my code:
private void SelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected)
{
DialogResult GetDialogResult =
MessageBox.Show("Keep this item selected?",
"Keep Selected",
MessageBoxButtons.YesNo);
if (GetDialogResult == DialogResult.No)
listView1.SelectedItems[0].Selected = false;
}
}
MultiSelect is disabled so the selected item index will always be 0. My problem is I want the selected item to be deselected if the DialogResult
is No, but when you click no, the SelectionChanged
event is firing again, and e.IsSelected
is apparently still true, so the Dialog Box pops up a second time. I imagine it has something to do with the fact that the first event hasn't completely finished executing when the item is being deselected, but I'm not sure how to solve that and make it so the Dialog Box only shows up once. Any suggestions?
Edit: Something else I've tried now is instead of Deselecting the item in the listBox, clearing all items in the listbox and recreating them. If the items are all cleared, the dialog box doesn't come up a second time. However if the items are immediately recreated, the same item becomes selected again and the dialog box still comes up the 2nd time.
Upvotes: 3
Views: 2943
Reputation: 41
I've found a solution that works. Calling a function to deselect the item asynchronously in a separate thread seems to have solved the issue for me. Without doing this, the second SelectionChanged event is called and has to finish executing before the first one can finished executing, which apparently causes the problem I was seeing. Here is the code I came up with that has worked:
delegate void DeselectDelegate();
public void DeselectItem()
{
if (this.listView1.InvokeRequired)
{
DeselectDelegate del = new DeselectDelegate(DeselectItem);
this.Invoke(del);
}
else
{
listView1.SelectedItems[0].Selected = false;
}
}
private void SelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (e.IsSelected)
{
DialogResult GetDialogResult =
MessageBox.Show("Keep this item selected?",
"Keep Selected",
MessageBoxButtons.YesNo);
if (GetDialogResult == DialogResult.No)
{
Thread thread = new Thread(DeselectItem);
thread.Start();
}
}
}
Upvotes: 1
Reputation: 9002
ItemSelectionChanged
(like several other events on other controls) gets fired when you change the value from the program as well. So when you run this line of code, that counts as a "selection changed"...
listView1.SelectedItems[0].Selected = false;
One way to handle this is by setting a flag:
private bool _programChangingSelection;
private void SelectionChanged(object sender, EventArgs e)
{
if (_programChangingSelection)
{
_programChangingSelection = false;
return;
}
if (e.IsSelected)
{
DialogResult GetDialogResult =
MessageBox.Show("Keep this item selected?",
"Keep Selected",
MessageBoxButtons.YesNo);
if (GetDialogResult == DialogResult.No)
{
_programChangingSelection = true;
listView1.SelectedItems[0].Selected = false;
}
}
}
Although, personally I think the add/remove handler method is probably a bit more elegant.
Upvotes: 2
Reputation: 11840
If the behaviour you want is:
then one approach is to unhook your event handler before you set the Selected property to false, then rehook afterwards, as follows:
if (GetDialogResult == DialogResult.No)
{
listView1.ItemSelectionChanged -= SelectionChanged;
e.Item.Selected = false;
listView1.ItemSelectionChanged += SelectionChanged;
}
This will stop the event handler from triggering again until your operation has completed.
Upvotes: 2