避免listview selectedindexchanged两次触发

时间:2012-09-26 13:34:39

标签: vb.net winforms listview selectionchanged

相当简单的问题,当列表视图的选定索引发生更改时,事件将触发两次,一次用于取消选择,另一次用于选择下一个项目。

我需要在不同的时间选择或取消选择时使用该事件,但是如果稍后重新选择重新选择它会使我的一半ui闪存从启用到关闭再重新开启,它也会导致相当多的代码运行所以我只需要一种避免取消选择的方法,如果它是另一个被点击的项目而不是空格(取消选择)

Dave R说在这里使用一个100毫秒的计时器:Am I missing something with my ListView selection event handling 听起来它会起作用,但看起来很不整洁,或者通常是一种糟糕的做法。

我唯一的另一个想法是使用点击事件,然后在该位置找到该项目?但我宁愿不去麻烦

提前感谢!

- 编辑 -

我只是认为点击事件会首先触发,所以我可以设置一个标志,如果点击事件发生在项目上,则跳过选择索引更改的代码,然后在使用后重置标志,因此跳过取消选择?我现在看看,但是再次感觉不是一种非常有效或简单的方法来做一些听起来很简单的事情吗?

4 个答案:

答案 0 :(得分:3)

使用ItemSelectionChanged事件 - ListViewItemSelectionChangedEventArgs可以告诉您哪个项目会触发它,以及是否选中它。

答案 1 :(得分:1)

以下解决方案即使延迟1 ms也能正常工作。为了确保它的工作原理,您可以选择更高的延迟,例如10 ms,但延迟100 ms会使选择“无”时有点滞后。这是C#-Code:

public class FixedListView : ListView
{
    private Timer _ItemSelectionChangedTimer = new Timer();
    private Timer _SelectedIndexChangedTimer = new Timer();

    private ListViewItemSelectionChangedEventArgs _ItemSelectionChangedEventArgs;
    private EventArgs _SelectedIndexChangedEventArgs;

    public FixedListView()
    {
        this._ItemSelectionChangedTimer.Interval = 1;
        this._SelectedIndexChangedTimer.Interval = 1;

        this._ItemSelectionChangedTimer.Tick += (sender, e) =>
        {
            this.OnItemSelectionChanged(this._ItemSelectionChangedEventArgs);
            this._ItemSelectionChangedEventArgs = null;
        };
        this._SelectedIndexChangedTimer.Tick += (sender, e) =>
        {
            this.OnSelectedIndexChanged(this._SelectedIndexChangedEventArgs);
            this._SelectedIndexChangedEventArgs = null;
        };
    }

    protected override void OnItemSelectionChanged(ListViewItemSelectionChangedEventArgs e)
    {
        if (this._ItemSelectionChangedTimer.Enabled)
        {
            this._ItemSelectionChangedTimer.Stop();
            base.OnItemSelectionChanged(e);
        }
        else
        {
            this._ItemSelectionChangedEventArgs = e;
            this._ItemSelectionChangedTimer.Start();
        }
    }

    protected override void OnSelectedIndexChanged(EventArgs e)
    {
        if (this._SelectedIndexChangedTimer.Enabled)
        {
            this._SelectedIndexChangedTimer.Stop();
            base.OnSelectedIndexChanged(e);
        }
        else
        {
            this._SelectedIndexChangedEventArgs = e;
            this._SelectedIndexChangedTimer.Start();                
        }
    }
}

这是VB代码:

Public Class FixedListBox

Inherits ListView

Public Sub New()

    Me._ItemSelectionChangedTimer.Interval = 1
    Me._SelectedIndexChangedTimer.Interval = 1

    AddHandler Me._ItemSelectionChangedTimer.Tick, _
        Sub(sender, e)
            Me.OnItemSelectionChanged(Me._ItemSelectionChangedEventArgs)
            Me._ItemSelectionChangedEventArgs = Nothing
        End Sub

    AddHandler Me._SelectedIndexChangedTimer.Tick, _
        Sub(sender, e)
            Me.OnSelectedIndexChanged(Me._SelectedIndexChangedEventArgs)
            Me._SelectedIndexChangedEventArgs = Nothing
        End Sub

End Sub

Private _ItemSelectionChangedTimer As New Timer()
Private _SelectedIndexChangedTimer As New Timer()

Private _ItemSelectionChangedEventArgs As ListViewItemSelectionChangedEventArgs
Private _SelectedIndexChangedEventArgs As EventArgs

Protected Overrides Sub OnItemSelectionChanged(e As ListViewItemSelectionChangedEventArgs)

    If Me._ItemSelectionChangedTimer.Enabled Then

        Me._ItemSelectionChangedTimer.Stop()
        MyBase.OnItemSelectionChanged(e)

    Else

        Me._ItemSelectionChangedEventArgs = e
        Me._ItemSelectionChangedTimer.Start()

    End If

End Sub

Protected Overrides Sub OnSelectedIndexChanged(e As EventArgs)

    If Me._SelectedIndexChangedTimer.Enabled Then

        Me._SelectedIndexChangedTimer.Stop()
        MyBase.OnSelectedIndexChanged(e)

    Else

        Me._SelectedIndexChangedEventArgs = e
        Me._SelectedIndexChangedTimer.Start()

    End If

End Sub

结束班

您可以像普通ListView一样使用控件,但SelectedIndexChanged和ItemSelectionChanged只会触发一次。

玩得开心......

答案 2 :(得分:1)

我刚尝试了另一种可能没有任何延迟的解决方案,它对我有用:

    If ListView1.Items(ListView1.FocusedItem.Index).Selected = False Then
        'This is the deselected value
        MsgBox("Deselected: " & ListView1.Items(ListView1.FocusedItem.Index).SubItems(0).Text)
    Else
        'This is the new selected value
        MsgBox("Selected: " & ListView1.Items(ListView1.FocusedItem.Index).SubItems(0).Text)
    End If

答案 3 :(得分:0)

只需检查SelectedIndexChanged事件,焦点项是否为null并退出。

ListView^ item = listView1-> FocusedItem;   //get selected item
if (item == nullptr){return;)  // this line exits when deselection event fires
String^ data1 = Convert::ToString (  item-> SubItems [0]    );   // get your data from columns like so
MessageBox::Show (data1);  // display

请注意,您可以通过更改SubItems中提供的索引来获取多列下的数据 使用定时器和延迟只会产生开销,特别是对于大型数据库导致应用程序在Visual C ++ .NET中减慢代码,但同样的理论适用于C#和其他

享受!!