2016-08-20 3 views
0

У меня есть следующий код в OnTextChanged события в проекте Xamarin.Forms:Trigger действие после задержки

async void OnTextChanged(object sender, TextChangedEventArgs e) 
     { 

      if (this.txtClientFilter.Text.Length > 4) 
      { 
       var client_list= App.ClientManager.GetTasksAsync(txtClientFilter.Text); 
       var template = new DataTemplate(typeof(TextCell)); 

       template.SetBinding(TextCell.DetailProperty, "nom_ct"); 
       template.SetBinding(TextCell.TextProperty, "cod_ct"); 

       listview.ItemTemplate = template; 
       listview.ItemsSource = await client_list; 

      } 
     } 

Как вы можете видеть, почти каждый пытается нажатие сделать запрос (с помощью метода GetTaskAsync) , Я не хочу запускать каждое нажатие клавиши, я хотел бы игнорировать некоторые нажатия клавиш в течение 1000 миллисекунд.

Как я могу это сделать? Я нашел несколько примеров, используя Task.Delay(), но не работал должным образом.

+1

Используйте Task.Delay with CancellationToken и отмените старый вызов каждый раз, прежде чем создавать новый. Таким образом будет выполнено только последнее нажатие после 1000 мс. –

+0

Очень сложно понять, что вы пробовали и «не работали должным образом», но, возможно, вам стоит взглянуть на операторов сравнения на TimeSpan, чтобы узнать, сколько времени прошло с последнего звонка ... –

+0

Как только разработчики начинают говоря о требованиях * на основе времени *, подобных этому, я рекомендую посмотреть на Reactive Extensions (Rx). Он имеет крутую кривую обучения, но идеально подходит для этих проблем. –

ответ

3
private int taskId = 0; 

    private async void ExecAutoComplete() 
    { 
     var client_list = App.ClientManager.GetTasksAsync(txtClientFilter.Text); 
     var template = new DataTemplate(typeof(TextCell)); 

     template.SetBinding(TextCell.DetailProperty, "nom_ct"); 
     template.SetBinding(TextCell.TextProperty, "cod_ct"); 

     listview.ItemTemplate = template; 
     listview.ItemsSource = await client_list; 
    } 

    private void TryExecute(int taskId) 
    { 
     if (this.taskId == taskId) 
      this.Invoke((MethodInvoker)(ExecAutoComplete)); 
    } 

    private async void OnTextChanged(object sender, TextChangedEventArgs e) 
    { 
     ++taskId; 
     Task.Delay(1000).ContinueWith(t => TryExecute(taskId)); 
    } 

Мы создаем уникальный taskId на каждый textChange и если после 1000мса taskId остается прежним (не больше изменения текста) мы выполняем фактический вызов.

+2

Замечание: почему вы смешиваете 'async' и' ContinueWith' (не путать людей)? –

+0

Хорошо, я просто оставил OP 'async' там, поскольку его другой код может положиться на него. – serhiyb

+0

После быстрого нажатия клавиши, я получил это исключение: (Excepción de HRESULT: 0x8001010E (RPC_E_WRONG_THREAD)) –

0

Создать _lastClickTime частную собственность типа DateTime на странице и добавьте в начале вашей кнопки обработчик щелчка:

if (DateTime.Now - _lastClickTime < new TimeSpan(0, 0, 0, 0, 1000)) 
{ 
    return; 
} 
_lastClickTime = DateTime.Now; 

не поняли, я на ваш вопрос?

+0

Если бы быстро нажали два нажатия клавиш, ваша логика выполнит только первый, но не второй. В то время как OP нуждается в противоположной логике - первая игнорируется, пока выполняется вторая. – serhiyb

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