C# C ListView ItemSelectionChanged事件Multi-Select仅获取最后选定的项目

C# C ListView ItemSelectionChanged事件Multi-Select仅获取最后选定的项目,c#,events,listview,multi-select,C#,Events,Listview,Multi Select,Im在C.NET4.5中使用多选列表视图 选择多个项目时会出现问题,例如Shift+结束或Shift+单击等。当然,这些只是多个选择的许多不同鼠标/键盘组合的几个示例 这是我在列表中选择项目时的事件处理程序: private void lvTitles_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { MessageBox.Show(e.Item.Text.ToString());

Im在C.NET4.5中使用多选列表视图 选择多个项目时会出现问题,例如Shift+结束或Shift+单击等。当然,这些只是多个选择的许多不同鼠标/键盘组合的几个示例

这是我在列表中选择项目时的事件处理程序:

private void lvTitles_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
    MessageBox.Show(e.Item.Text.ToString());
    //MessageBox just for testing I am actually running a SQL query here
}
我的问题是,如果我选择500项,事件将触发500次。其目的是让用户通过上面提到的键盘/鼠标组合选择的最后一项打开并使用它做一些事情。。。在我的例子中,我需要对它运行SQL查询

如果我首先单击listview中的项0,则可以运行查询,然后在按住shift键并结束时,它将高亮显示所有其余项,并且我希望它仅对最后选定的项运行查询。相反,它在这两者之间的每一项上都运行


编辑:另一个注意事项是,事件在取消选择时也会触发,在这种情况下,取消选择时确实不应该执行任何操作。

您是否考虑过在按下按钮时执行此操作?这样,他们也可以使用Ctrl-Click来选择他们想要的任何单个项目

否则,您必须等待一定的时间,然后再启动该操作(称为“取消公告”),您可以在此处阅读更多关于取消公告的内容:

我创建了一个可用于取消抖动的类:

public class Debounce {
    private Action _action;
    private bool _isThreadRunning;
    private Thread _thread;
    private DateTime _runAt;
    private double _waitSeconds;

    private Debounce(double waitSeconds, Action action) {
        _action = action;
        _waitSeconds = waitSeconds;
    }

    private void Invoke() {
        _runAt = DateTime.Now.AddSeconds(_waitSeconds);

        lock(this) {
            if(!_isThreadRunning) {
                _isThreadRunning = true;

                _thread = new Thread(() => {
                    while(true) {
                        Thread.Sleep(100);

                        lock(this) {
                            if(DateTime.Now > _runAt) {
                                _action();
                                _isThreadRunning = false;
                                _thread = null;
                                break;
                            }
                        }
                    }
                });

                _thread.Start();
            }
        }
    }

    private static Dictionary<Action, Debounce> __debounces;
    private static Dictionary<Action, Debounce> _debounces {
        get {
            if(__debounces == null) {
                __debounces = new Dictionary<Action, Debounce>();
            }

            return __debounces;
        }
    }

    public static void Run(double waitSeconds, Action action) {
        Debounce debounce;

        if(!_debounces.TryGetValue(action, out debounce)) {
            debounce = new Debounce(waitSeconds, action);
            _debounces.Add(action, debounce);
        }

        debounce._waitSeconds = waitSeconds;
        debounce.Invoke();
    }
}
无论他们如何选择项目,它都会在他们上次选择操作后5秒运行代码


我刚刚写了这个类并做了一个快速测试,建议进行更彻底的测试。在任何情况下,我希望这足以让我产生这个想法。

我需要一系列用户通常期望的操作,如键盘Ctrl-a、Shift+End、Shift+Down Arrow。。。etc以及鼠标单击+Shift和鼠标单击+Ctrl。。。以及所有其他考虑因素当运行并进行单个选择时,messagebox在5秒钟内不会弹出。。这只有在您确切知道要运行多长时间之前才能起作用。。。我想知道是否有什么东西可以从这另一个SO帖子中得到帮助:那个SO帖子看起来确实是一个有效的选择。我建议既然你都有这两种方法的代码,为什么不试一下,看看哪一种方法对你有效。我以5秒为例,你可以改变你想要的任何东西,1秒半。它所做的是在上次触发lvTitles\u ItemSelectionChanged后的X秒调用MessageBox.Showe.Item.Text.ToString。谢谢,我将使用它运行!
private void lvTitles_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
    Debounce.Run(5, () => MessageBox.Show(e.Item.Text.ToString()));
}