2011-11-03 19 views
20

Czy istnieje sposób w języku C#, aby czekać, aż użytkownik zakończy pisanie w polu tekstowym przed podjęciem wartości, które wpisali bez uderzenia enter?C# czekać na użytkownika, aby zakończyć pisanie w polu tekstowym

Revised to pytanie trochę:

Ok mam prosty kalkulator, który mnoży się przez 2.

Oto, czego chcę to zrobić: Użytkownik wprowadza wartość jak 1000 do pola tekstowego i to automatycznie wyświetla 2000.

Oto co się dzieje: z chwilą wejścia w 1 użytkownik jej mnoży przez 2 i wyjść 2.

+14

Jak ustalicie, że "skończyli pisać?" Nie sądzę, że C# będzie dodawać programy obsługi zdarzeń telepatycznych dla co najmniej kilku innych wersji ... – Donut

+1

Problem polega na tym, że musisz zdefiniować "zakończenie". Czy to jest, gdy przestają pisać przez 3 sekundy, 5 itd. Najprostszym sposobem jest użycie znacznika takiego jak Enter lub kliknięcie przycisku – JaredPar

+0

możesz odczekać chwilę i po prostu zgadnąć, że użytkownik zakończył pisanie lub texbox nie ma ostrości już więcej ... inaczej nie można – evilone

Odpowiedz

2

Możesz użyć zdarzenia z pola tekstowego onChange(). Jeśli tekst jest zmieniany w polu tekstowym, sprawdź, czy wprowadzona wartość jest liczbą i obliczyć wartość całkowitą zgodnie z inną wartością.

+1

onChange() nie jest zdarzeniem dla textbox pod VS2015 C#. – Jhollman

+10

@Jhollman Odpowiedziałem na to pytanie w 2011 roku. Cóż, wtedy nie było Visual Studio 2015. – evilone

+1

Jak to w jakikolwiek sposób odpowiedzieć na pytanie? A ponadto, dlaczego jest to wybrana odpowiedź? – Krythic

0

Co się stanie, jeśli wyzwolisz zdarzenie na podstawie naciśnięcia klawisza lub powrotu?

+0

Domyślam się, że tab lub powód działałyby w taki sposób, w jaki sposób dodaję tego typu zdarzenia do mojego kodu – user990951

+0

zakładka spowoduje zdarzenie 'LostFocus', zobacz http://msdn.microsoft.com/en-us /library/system.windows.forms.control.lostfocus.aspx po więcej szczegółów. – esskar

+0

Tak, funkcja lostfocus działałaby najlepiej, a następnie wyzwalała zdarzenia z tego –

1

Chcesz użyć obsługi zdarzenia Leave lub LostFocus dla danego pola tekstowego. Zakładam, że używasz WinForm, mimo że nie podajesz go w swoim pytaniu.

39

Definiuję "gotowe pisanie" teraz jako "użytkownik wpisał coś, ale nie wpisał nic po pewnym czasie". Mając to jako definicję, napisałem małą klasę wywodzącą się z TextBox, aby rozszerzyć ją o wydarzenie DelayedTextChanged. Nie gwarantuję, że jest kompletny i wolny od błędów, ale spełnił on mały test dymu. Możesz je zmienić i/lub z niego korzystać. Nazwałem to MyTextBox, ponieważ nie mogłem teraz wymyślić lepszego imienia. Możesz użyć właściwości DelayedTextChangedTimeout, aby zmienić limit czasu oczekiwania. Domyślna wartość to 10000ms (= 10 sekund).

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

Nie wiem, czy funkcja onChange() istnieje tylko w starszej wersji C#, ale nie mogę go znaleźć!

następujące prace do wykrywania, gdy użytkownik zostanie trafiony klawisz Enter, lub karty poza TextBox, ale tylko po zmianie jakiś tekst:

//--- 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

Innym prostym rozwiązaniem byłoby dodać czasomierza do listy formularz, ustawić właściwość Interval do 250, a następnie użyć zdarzenia kleszcz timera w następujący sposób:

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

Jeśli używasz WPF i .NET 4.5 lub nowszy nie jest to nowy obiekt na wiązanie ramach kontroli, o nazwie " Opóźnienie". Określa czas, po którym źródło jest aktualizowane.

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

Oznacza to, że źródło jest aktualizowane dopiero po 500 milisekundach. O ile widzę to robi aktualizację po wpisaniu w TextBox zakończone. Btw. ta właściwość może być przydatna również w innych sytuacjach, np. ListBox itp.

+0

Jeśli chcesz, aby zaktualizować źródło podczas pisania, po krótkiej przerwie, potrzebujesz również 'UpdateSourceTrigger = PropertyChanged' w twoim powiązaniu. – MgSam

3

Zmierzyłem się z tym samym wyzwaniem, a oto moje proste podejście. Działa to bez problemów.

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

W UWP, zrobiłem opóźnione sprawdzanie poprzez statyczną lastTimeOfTyping i sprawdzenie czasu gdy „TextChanged” zdarzenie miało miejsce. To czeka, aż statyczny parametr lastTimeOfTyping zostanie dopasowany, gdy nowy czas "TextChanged" zostanie dopasowany, a następnie wykona żądaną funkcję.

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 
     } 
    } 
Powiązane problemy