2011-11-03 19 views
20

C'è un modo in C# di aspettare fino a quando l'utente ha finito di digitare una casella di testo prima di prendere i valori che ha digitato senza premere invio?C# aspetta che l'utente finisca di digitare in una casella di testo

rivisto questo domanda un po ':

Va bene ho una semplice calcolatrice che moltiplica per 2.

Ecco quello che voglio fare: l'utente immette un valore come 1000 in una casella di testo e visualizza automaticamente 2000.

Ecco cosa accade: non appena l'utente inserisce nella 1 suoi moltiplicazione per 2 e uscite 2.

+14

Come si determina che hanno "terminato di digitare?" Non credo che C# aggiungerà gestori per eventi telepatici per almeno un altro paio di versioni ... – Donut

+1

Il problema qui è che devi definire "finitura". È quando smettono di digitare per 3 secondi, 5, ecc ... Il modo più semplice è usare un marker come Enter o fare clic su un pulsante – JaredPar

+0

puoi aspettare un po 'e solo indovinare che l'utente ha finito di digitare o texbox non ha focus più ... altrimenti non puoi – evilone

risposta

2

È possibile utilizzare l'evento di testo onChange(). Se il testo viene modificato nella casella di testo, verificare se il valore immesso è un numero e calcolare il valore totale in base all'altro valore.

+1

onChange() non è un evento per casella di testo in VS2015 C#. – Jhollman

+10

@Jhollman Ho risposto a questa domanda nel 2011. Bene, quindi non c'era Visual Studio 2015. – evilone

+1

Come si può rispondere in qualsiasi modo alla domanda? E inoltre, perché questa è la risposta scelta? – Krythic

4

è possibile gestire l'evento LostFocus della casella di testo che scatta ogni finiture utente digitando a nd si allontana dalla casella di testo. Ecco la documentazione su LostFocus: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx

Tuttavia, non sono sicuro di cosa esattamente si stia tentando di fare qui poiché la domanda non è molto chiara su cosa significa "finitura".

0

Cosa succede se si attiva un evento in base a una sequenza di tasti come scheda o ritorno?

+0

Suppongo che tab o return funzionerebbero come aggiungerei quel tipo di eventi al mio codice – user990951

+0

una tab risulterà nell'evento 'LostFocus', vedi http://msdn.microsoft.com/it-it /library/system.windows.forms.control.lostfocus.aspx per ulteriori dettagli. – esskar

+0

Sì, lostfocus funziona meglio, quindi attiva i tuoi eventi fuori da quello –

1

Si desidera utilizzare gestire l'evento Leave o LostFocus per la casella di testo in questione. Suppongo che tu stia usando WinForm anche se non lo dici nella tua domanda.

39

Definisco "terminato digitando" ora come "l'utente ha digitato qualcosa ma non ha digitato nulla dopo un certo tempo". Avendo che come definizione ho scritto una piccola classe che deriva da TextBox per estenderlo con un evento DelayedTextChanged. Non sono sicuro che sia completo e privo di bug, ma ha soddisfatto un piccolo test del fumo. Sentiti libero di cambiare e/o usarlo. L'ho chiamato MyTextBox perché non riuscivo a trovare un nome migliore adesso. È possibile utilizzare la proprietà DelayedTextChangedTimeout per modificare il timeout di attesa. L'impostazione predefinita è 10000 ms (= 10 secondi).

public class MyTextBox : TextBox 
{ 
    private Timer m_delayedTextChangedTimer; 

    public event EventHandler DelayedTextChanged; 

    public MyTextBox() : base() 
    { 
     this.DelayedTextChangedTimeout = 10 * 1000; // 10 seconds 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (m_delayedTextChangedTimer != null) 
     { 
      m_delayedTextChangedTimer.Stop(); 
      if (disposing) 
       m_delayedTextChangedTimer.Dispose(); 
     } 

     base.Dispose(disposing);    
    } 

    public int DelayedTextChangedTimeout { get; set; } 

    protected virtual void OnDelayedTextChanged(EventArgs e) 
    { 
     if (this.DelayedTextChanged != null) 
      this.DelayedTextChanged(this, e); 
    } 

    protected override void OnTextChanged(EventArgs e) 
    { 
     this.InitializeDelayedTextChangedEvent(); 
     base.OnTextChanged(e);    
    }     

    private void InitializeDelayedTextChangedEvent() 
    { 
     if (m_delayedTextChangedTimer != null) 
      m_delayedTextChangedTimer.Stop(); 

     if (m_delayedTextChangedTimer == null || m_delayedTextChangedTimer.Interval != this.DelayedTextChangedTimeout) 
     {     
      m_delayedTextChangedTimer = new Timer(); 
      m_delayedTextChangedTimer.Tick += new EventHandler(HandleDelayedTextChangedTimerTick); 
      m_delayedTextChangedTimer.Interval = this.DelayedTextChangedTimeout; 
     } 

     m_delayedTextChangedTimer.Start(); 
    } 

    private void HandleDelayedTextChangedTimerTick(object sender, EventArgs e) 
    { 
     Timer timer = sender as Timer; 
     timer.Stop(); 

     this.OnDelayedTextChanged(EventArgs.Empty); 
    } 
} 
1

Non so se l'onChange() esiste solo in una versione precedente di C#, ma non riesco a trovarlo!

i seguenti lavori per rilevare quando un utente o colpisce il tasto Invio o Tab per uscire dal TextBox, ma solo dopo aver cambiato una parte di testo:

//--- this block deals with user editing the textBoxInputFile --- // 
    private Boolean textChanged = false; 
    private void textBoxInputFile_TextChanged(object sender, EventArgs e) { 
     textChanged = true; 
    } 
    private void textBoxInputFile_Leave(object sender, EventArgs e) { 
     if (textChanged) { 
      fileNameChanged(); 
     } 
     textChanged = false; 
    } 
    private void textBoxInputFile_KeyDown(object sender, KeyEventArgs e) { 
     if (textChanged & e.KeyCode == Keys.Enter) { 
      fileNameChanged(); 
     } 
     textChanged = false; 
    } 
    //--- end block --- // 
12

Un'altra soluzione semplice sarebbe quella di aggiungere un timer per il vostro modulo, impostare la proprietà Interval a 250 e quindi utilizzare evento tick del timer come segue:

private void timer1_Tick(object sender, EventArgs e) 
{ 
    timer1.Stop(); 
    Calculate(); // method to calculate value 
} 

private void txtNumber_TextChanged(object sender, EventArgs e) 
{ 
    timer1.Stop(); 
    timer1.Start(); 
} 
6

Se si utilizza WPF e .NET 4.5 o successiva c'è una nuova proprietà da parte di legame di un controllo denominato " Ritardo". Definisce un intervallo dopo il quale la fonte viene aggiornata.

<TextBox Text="{Binding Name, Delay=500}" /> 

Ciò significa che la sorgente viene aggiornata solo dopo 500 millisecondi. Per quanto vedo lo fa l'aggiornamento dopo aver digitato nel TextBox terminato. Btw. questa proprietà può essere utile anche in altri scenari, ad es. ListBox ecc.

+0

Se si desidera aggiornare la sorgente durante la digitazione, dopo una breve pausa, è necessario anche "UpdateSourceTrigger = PropertyChanged" nell'associazione. – MgSam

3

Ho affrontato la stessa sfida, ed ecco il mio approccio semplice. Questo funziona senza problemi.

public partial class Form2 : Form 
    { 
     static int VALIDATION_DELAY = 1500; 
     System.Threading.Timer timer = null; 
     public Form2() 
     { 
      InitializeComponent(); 
     } 

     private void textBox1_TextChanged(object sender, EventArgs e) 
     { 
      TextBox origin = sender as TextBox; 
      if (!origin.ContainsFocus) 
       return; 

      DisposeTimer(); 
      timer = new System.Threading.Timer(TimerElapsed, null, VALIDATION_DELAY, VALIDATION_DELAY); 

     } 
     private void TimerElapsed(Object obj) 
     { 
      CheckSyntaxAndReport(); 
      DisposeTimer();    
     } 

     private void DisposeTimer() 
     { 
      if (timer != null) 
      { 
       timer.Dispose(); 
       timer = null; 
      } 
     } 

     private void CheckSyntaxAndReport() 
     {    
      this.Invoke(new Action(() => 
      { 
       string s = textBox1.Text.ToUpper(); //Do everything on the UI thread itself 
       label1.Text = s; 
      } 
       ));    
     } 
    } 
1

In UWP, ho fatto un controllo ritardato facendo una lastTimeOfTyping statica e controllando il tempo in cui l'evento "TextChanged" è accaduto. Questo attende che l'ultimo staticTimeOfTyping sia uguale quando una nuova ora "TextChanged" corrisponde e quindi esegue la funzione desiderata.

private const int millisecondsToWait = 500; 
    private static DateTime s_lastTimeOfTyping; 
    private void SearchField_OnTextChanged(object sender, TextChangedEventArgs e) 
    { 
     var latestTimeOfTyping = DateTime.Now; 
     var text = ((TextBox)sender).Text; 
     Task.Run(()=>DelayedCheck(latestTimeOfTyping, text)); 
     s_lastTimeOfTyping = latestTimeOfTyping; 
    } 

    private async Task DelayedCheck(DateTime latestTimeOfTyping, string text) 
    { 
     await Task.Delay(millisecondsToWait); 
     if (latestTimeOfTyping.Equals(s_lastTimeOfTyping)) 
     { 
      // Execute your function here after last text change 
      // Will need to bring back to the UI if doing UI changes 
     } 
    } 
Problemi correlati