连续输入时不要引发TextChanged [英] Don't raise TextChanged while continuous typing
问题描述
我有一个文本框,其中有一个相当大的 _TextChanged
事件处理程序。在正常的键入条件下,性能还可以,但是当用户执行长时间的连续操作(例如按住退格按钮一次删除大量文本)时,它的性能会明显滞后。
I have a textbox that has a fairly hefty _TextChanged
event handler. Under normal typing condition the performance is okay, but it can noticeably lag when the user performs a long continuous action, such as keeping the backspace button pressed to delete a lot of text at once.
例如,该事件完成了0.2秒,但用户每0.1秒执行一次删除。因此,它无法赶上进度,将需要处理大量积压的事件,从而导致UI滞后。
For example, the event took 0.2 seconds to complete, but the user is performing one deletion every 0.1 seconds. Thus, it cannot catch up and there will be a backlog of events that needs to be handled, leading to the UI lagging.
但是,该事件不需要运行对于这些中间状态,因为它只在乎最终结果。有什么办法让事件处理程序知道它应该只处理最新的事件,而忽略所有先前的过时更改?
However, the event does not need to run for these in-between states, because it only cares about the end result. Is there any way to let the event handler know that it should process only the latest event, and ignore all the previous stale changes?
推荐答案
根据经验,我已经多次遇到此问题,到目前为止,发现此解决方案简单而整洁。它可以在 Windows窗体
中运行,但可以轻松转换为 WPF
。
I've come across this problem several times based on experience found this solution simple and neat so far. It is working in Windows Form
but can easily be converted to WPF
.
工作原理:
当 TypeAssistant
的对象被获取时通知发生了文本更改
,它运行了一个计时器。在 WaitingMilliSeconds
之后,计时器引发 Idleی
事件。通过处理此事件,您可以完成所需的任何工作。如果在从计时器启动开始的时间段内又发生了文本更改
,此后又发生了 WaitingMilliSeconds
,则计时器重置。
When an object of TypeAssistant
gets informed that a text change
has happened, it runs a timer. After WaitingMilliSeconds
the timer raises Idleی
event. By handling this event you can do whatever job you desire. If another text change
occurs in the time period starting from the timer start and WaitingMilliSeconds
afterwards, the timer resets.
public class TypeAssistant
{
public event EventHandler Idled = delegate { };
public int WaitingMilliSeconds { get; set; }
System.Threading.Timer waitingTimer;
public TypeAssistant(int waitingMilliSeconds = 600)
{
WaitingMilliSeconds = waitingMilliSeconds;
waitingTimer = new Timer(p =>
{
Idled(this, EventArgs.Empty);
});
}
public void TextChanged()
{
waitingTimer.Change(WaitingMilliSeconds, System.Threading.Timeout.Infinite);
}
}
用法:
public partial class Form1 : Form
{
TypeAssistant assistant;
public Form1()
{
InitializeComponent();
assistant = new TypeAssistant();
assistant.Idled += assistant_Idled;
}
void assistant_Idled(object sender, EventArgs e)
{
this.Invoke(
new MethodInvoker(() =>
{
// do your job here
}));
}
private void yourFastReactingTextBox_TextChanged(object sender, EventArgs e)
{
assistant.TextChanged();
}
}
优势:
- 简单!
- 同时在
WPF
和Windows Form
$ b中工作$ b - 使用.Net Framework 3.5 +
- Simple!
- Working both in
WPF
andWindows Form
- Working with .Net Framework 3.5+
缺点:
- 再运行一个线程
- 需要调用,而不是直接操纵表单
这篇关于连续输入时不要引发TextChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!