【发布时间】:2011-02-26 04:11:31
【问题描述】:
当用户在搜索框中输入内容时,我有一个函数被调用。我想在实际执行该功能之前等待用户完成输入。我知道如何在 JavaScript 中通过超时轻松完成此操作,但我将如何在 C# 中做同样的事情?另外,在我假设用户完成输入之前我应该等待多长时间? 100 毫秒?
【问题讨论】:
标签: c# wpf visual-studio user-interface
当用户在搜索框中输入内容时,我有一个函数被调用。我想在实际执行该功能之前等待用户完成输入。我知道如何在 JavaScript 中通过超时轻松完成此操作,但我将如何在 C# 中做同样的事情?另外,在我假设用户完成输入之前我应该等待多长时间? 100 毫秒?
【问题讨论】:
标签: c# wpf visual-studio user-interface
如果您习惯使用响应式 (Rx) 框架,那么您可以使用其内置的节流极快地实现此功能。
这是一篇关于这个主题的文章:Rx Can Improve UI Responsiveness
还有一些从文章中窃取和修改的代码:
var textObserver = (from text in Observable.FromEvent<TextChangedEventArgs>(_app.myTextField, "TextChanged")
select text).Throttle(TimeSpan.FromSeconds(.5));
_searchObserver = textObserver.Subscribe(textChangedEvent =>
{
var tb = (TextBox)textChangedEvent.Sender;
DoMySearch(tb.Text);
});
如文章中所述(值得完整阅读),只要半秒后用户没有输入任何内容,就会触发 lambda 表达式中的代码。
明天我会在我的开发 PC 前清理该示例,但这应该现在为您提供一个起点。
【讨论】:
这是我根据 Loren 输入的工作代码:
private void SearchTextBox_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (SearchTextBoxTimer != null)
{
Console.WriteLine("The user is currently typing.");
if (SearchTextBoxTimer.Interval < 750)
{
SearchTextBoxTimer.Interval += 750;
Console.WriteLine("Delaying...");
}
}
else
{
Console.WriteLine("The user just started typing.");
SearchTextBoxTimer = new System.Windows.Forms.Timer();
SearchTextBoxTimer.Tick += new EventHandler(SearchTextBoxTimer_Tick);
SearchTextBoxTimer.Interval = 500;
SearchTextBoxTimer.Start();
}
}
以及事件处理程序:
private void SearchTextBoxTimer_Tick(object sender, EventArgs e)
{
Console.WriteLine("The user finished typing.");
if (SearchTextBox.Text == "")
{
ConsoleTextBox.Text = "Searching: All";
}
else
{
ConsoleTextBox.Text = "Searching: " + SearchTextBox.Text;
}
SearchTextBox_TextChanged();
SearchTextBoxTimer.Stop();
SearchTextBoxTimer.Dispose();
SearchTextBoxTimer = null;
}
如果有人使用此代码,请告诉我是否调整了我输入的时间间隔。我认为它们还不是最佳的。
【讨论】:
为所需的延迟间隔设置一个计时器。在按键事件上启动计时器。如果计时器跳闸,则停止计时器并运行搜索。
100 毫秒是 不是 一个好的间隔,但是!即使打字绝对均匀,也大约是 100wpm。
【讨论】:
一个建议是不要让用户感到惊讶。这通常是一个很好的 UI 设计原则。因此,仅在文本框失去焦点时执行实际搜索。将增量匹配的搜索字符串显示为用户类型(如谷歌)是一回事,但在一些键盘延迟后通过主动搜索让用户感到惊讶是另一回事。就我个人而言,我会觉得这很烦人,因为我在输入搜索字符串时经常会停下来想一想。
【讨论】:
这是解决此问题的代码示例
using System;
using System.Timers;
using System.Windows.Input;
using Timer = System.Timers.Timer;
namespace Example
{
public partial class OnKeyUpInputExample
{
// Timer set to elapse after 750ms
private Timer _timer = new Timer(750) { Enabled = false };
// Constructor
public OnKeyUpInputExample()
{
//What to do when _timer elapses
_timer.Elapsed += TextInput_OnKeyUpDone;
}
// Event handler
private void TextInput_OnKeyUp(object sender, KeyEventArgs e)
{
// You could also put the .Stop() in an OnKeyDown event handler if you need to account for keys being held down
_timer.Stop();
_timer.Start();
}
// Function to complement timer elapse
private void TextInput_OnKeyUpDone(object sender, ElapsedEventArgs e)
{
// If we don't stop the timer, it will keep elapsing on repeat.
_timer.Stop();
this.Dispatcher.Invoke(() =>
{
//Replace with code you want to run.
Console.WriteLine("KeyUp timer elapsed");
});
}
}
}
【讨论】:
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => 如果在 uwp 上,而不是 Invoke
一些观点可以在这里找到:Delayed function calls
记录每个 keyup 事件的时间戳,并使用 Timer 类来延迟方法的执行。在该方法中,您可以考虑用户是否已停止输入,将当前时间与最后一个 keyup 事件时间戳进行比较。您可以对间隔进行试验,以确保响应能力。限制点击也很聪明,只允许搜索最少 3 个字符。
定时器:http://msdn.microsoft.com/en-us/library/system.threading.timer.aspx
【讨论】: