listView ItemSelectionChanged'被选中'没有按预期工作?

时间:2013-12-10 02:27:05

标签: c# .net winforms

我遇到了ListView ItemSelectionChanged事件被调用两次的问题。从搜索中我发现它是因为在选择项目时调用事件,而在取消选择项目时再次调用事件。我只希望在选择项目时触发它,而不是在取消选择它时触发。解决方案似乎在事件开始时有一个if(e.IsSelected),因此只有在选择一个项目时才会调用它,但在这种情况下,这对我不起作用。这是我的代码的基本结构:

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,因此所选项目索引将始终为0.我的问题是,如果DialogResult为否,我希望取消选择所选项目,但是当您单击否时,SelectionChanged事件再次开火,e.IsSelected显然仍然是真的,所以对话框第二次弹出。我想这与第一个事件在取消选择项目时尚未完全执行的事实有关,但我不知道如何解决这个问题并使其成为对话框只显示一次。有什么建议吗?

编辑:我现在尝试的其他内容不是取消选择列表框中的项目,清除列表框中的所有项目并重新创建它们。如果项目全部清除,则对话框不会再次出现。但是,如果立即重新创建项目,则会再次选择相同的项目,第二次对话框仍然会出现。

3 个答案:

答案 0 :(得分:2)

如果你想要的行为是:

  1. 用户点击商品
  2. 对话框弹出
  3. 如果他们在弹出窗口中单击“否”,则不会选择
  4. 如果他们点击“是”,则会
  5. 然后一种方法是在将Selected属性设置为false之前取消挂钩事件处理程序,然后重新挂钩,如下所示:

    if (GetDialogResult == DialogResult.No)
    {
        listView1.ItemSelectionChanged -= SelectionChanged;
        e.Item.Selected = false;
        listView1.ItemSelectionChanged += SelectionChanged;
    }
    

    这将阻止事件处理程序再次触发,直到您的操作完成。

答案 1 :(得分:2)

当您从程序中更改值时,

ItemSelectionChanged(与其他控件上的其他几个事件一样)会被触发。因此,当您运行此行代码时,这将被视为“选择已更改”...

listView1.SelectedItems[0].Selected = false;

处理此问题的一种方法是设置标志:

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;
        }
    }
}

虽然,我个人认为添加/删除处理程序方法可能更优雅。

答案 2 :(得分:1)

我找到了一个有效的解决方案。调用一个函数在一个单独的线程中异步取消选择该项似乎已经为我解决了这个问题。如果不执行此操作,将调用第二个SelectionChanged事件,并且必须在第一个完成执行之前完成执行,这显然会导致我看到的问题。以下是我提出的代码:

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();
        }
    }
}