2013-09-28 1 views
3

Im, использующий multi-select ListView в C# .NET 4.5 Проблема возникает при выборе нескольких элементов (например, Shift + End или Shift + Click и т. Д.). Это всего лишь несколько примеров из множества различных комбинаций мыши/клавиатуры для мульти-выбора конечно ..C# ListView ItemSelectionChanged Событие Multi Выбрать получить ТОЛЬКО последний выбранный элемент

Это мой обработчик события при выборе элементов в списке:

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-запрос против него.

Если я нажму сначала на элемент 0 в списке, это нормально для запуска запроса, тогда, когда вы сдвигаете + конец, выделяются все остальные, и я хочу, чтобы он выполнял запрос только по последнему выбранному элементу. Вместо этого он работает на каждом элементе между ними.

РЕДАКТИРОВАТЬ: В другом примечании событие срабатывает, поскольку оно также отменяет выбор, и в этом случае он действительно ничего не должен делать при отмене выбора.

ответ

1

Вы считаете, что вместо нажатия на кнопку нажмите кнопку? Таким образом, они могут также использовать Ctrl-Click для выбора любых отдельных элементов, которые они хотят?

В противном случае, что вы должны сделать, это ждать определенное количество времени перед обжигом действия, известное как дребезг, вы можете прочитать больше о дребезге здесь: https://stackoverflow.com/a/4517995/984780

Я создал класс, который вы можете использовать для дребезга :

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

Затем вы можете изменить свой код на этот:

private void lvTitles_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) 
{ 
    Debounce.Run(5,() => MessageBox.Show(e.Item.Text.ToString())); 
} 

Это должно работать независимо от того, как они выбирают предметы, его будет запускать ваш код через 5 секунд после их последнего действия выбора.

Я только что написал этот класс и сделал быструю проверку, рекомендуется более тщательный тест. В любом случае, надеюсь, этого достаточно, чтобы получить эту идею.

+0

Мне нужен ряд действий, которые обычно ожидаются пользователем, такие как клавиатура Ctrl-A, Shift + End, Shift + стрелка вниз ... и т. Д., А также мышь Click + Shift и Mouse Click + Ctrl ... и все остальные соображения – Kairan

+0

При запуске и выполнении одного выбора окно сообщения не всплывает в течение 5 секунд .. это будет работать, только если вы точно знаете, сколько времени потребуется, чтобы бежать заранее ... Мне интересно, есть ли что-то, что может быть вытащил из этого другого сообщения SO, чтобы мне было полезно: http://stackoverflow.com/questions/3666678/how-do-you-respond-once-to-a-user-selecting-a-range-in-a-listview -control – Kairan

+0

Это сообщение SO определенно выглядит как допустимый вариант. Я предлагаю, так как у вас есть код для обоих, почему бы вам не попробовать их и посмотреть, работает ли для вас работа. Я использовал 5 секунд в качестве примера. Вы можете изменить все, что хотите, 1 секунду, полсекунды. Он делает то, что он вызывает MessageBox.Show (e.Item.Text.ToString()) «X» секунд после последнего запуска lvTitles_ItemSelectionChanged(). –

 Смежные вопросы

  • Нет связанных вопросов^_^