C#等待用户在文本框中完成输入

有没有一种方法在C#中等到用户完成在文本框中键入之后才接受他们键入的值而没有按Enter键?

稍微修改了这个问题:

好吧,我有一个简单的计算器乘以2。

这就是我想要它做的事情:用户将一个类似1000的值输入到文本框中,它会自动显示2000。

这是发生的事情:一旦用户输入1,它的乘以2并输出2。

您可以使用textbox onChange()事件。 如果在文本框中更改了文本,请检查输入的值是否为数字,并根据其他值计算总值。

我现在定义“完成打字”,因为“用户输入了一些内容但在一段时间后没有输入任何内容”。 将其作为定义,我编写了一个从TextBox派生的DelayedTextChanged ,通过DelayedTextChanged事件扩展它。 我不确保完整且没有错误,但它满足了小型烟雾测试。 随意更改和/或使用它。 我称它为MyTextBox因为我现在无法想出一个更好的名字。 您可以使用DelayedTextChangedTimeout属性更改等待超时。 默认值为10000毫秒(= 10秒)。

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

另一个简单的解决方案是在表单中添加一个计时器,将Interval属性设置为250,然后使用计时器的tick事件,如下所示:

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

如果您使用的是WPF和.NET 4.5或更高版本,则名为“Delay”的控件的Binding部分上会有一个新属性。 它定义了更新源之后的时间跨度。

  

这意味着源仅在500毫秒后更新。 据我所知,它在TextBox中输入结束后进行了更新。 顺便说一句。 此属性在其他场景中也很有用,例如。 ListBox等

您可以处理文本框的LostFocus事件,该事件将在用户每次完成键入时触发并从文本框导航。 以下是LostFocus的文档: http : //msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx

但是,我不确定你到底想要做什么,因为问题不是很明确“完成”的含义。

我面临同样的挑战,这是我的简单方法。 这没有问题。

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

在UWP中,我通过进行静态lastTimeOfTyping并检查“TextChanged”事件发生的时间来进行延迟检查。 当新的“TextChanged”时间匹配然后执行所需的函数时,它会等待静态lastTimeOfTyping匹配。

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

您希望使用处理相关文本框的Leave或LostFocus事件。 我假设您正在使用WinForm,即使您没有在您的问题中说明它。

我不知道onChange()是否仅存在于旧版本的c#中,但我找不到它!

以下工作用于检测用户何时点击Enter键,或选中TextBox之外的选项卡,但仅在更改某些文本后:

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

如果您触发基于类似Tab键击或返回的事件,该怎么办?

我的同事建议使用Rx和事件限制的解决方案:

 var FindDelay = 500;//milliseconds //textBox is your text box element Observable.FromEventPattern(textBox, "TextChanged") .Select(ea => ((TextBox) ea.Sender).Text) .DistinctUntilChanged() .Throttle(TimeSpan.FromMilliseconds(FindDelay)) .Subscribe(text => { //your handler here }); 

作为异步扩展方法。 改编自Grecon14的答案。

 public static class UIExtensionMethods { public static async Task GetIdle(this TextBox txb) { string txt = txb.Text; await Task.Delay(500); return txt == txb.Text; } } 

用法:

 if (await myTextBox.GetIdle()){ // typing has stopped, do stuff }