我有一个模拟键盘输入的条形码扫描仪。我用它在一个文本框中输入ISBN号,然后再搜索该标题。我需要使用文本框方法在执行任何操作之前等待10或13个字符的条目,但是我不知道该怎么做。
到目前为止,我有以下内容:
private void scanBox_TextChanged(object sender, EventArgs e)
{
if (scanBox.Text.Length == 10)
{
getRecord10();
}
else if (scanBox.Text.Length == 13)
{
getRecord13();
}
else
{
MessageBox.Show("Not in directory", "Error");
}
}
我考虑使用某种定时器实现来阻止最后一个条件,但我真正需要的是等待10或13位数的方法。条形码扫描器模拟按下的各个键,这就是它当前失败的原因。
答案 0 :(得分:13)
您可以在WPF中使用Timer(或DispatcherTimer)。此示例应用程序在最后一次击键后300ms更新窗口的标题。
System.Windows.Forms.Timer _typingTimer; // WinForms
// System.Windows.Threading.DispatcherTimer _typingTimer; // WPF
public MainWindow()
{
InitializeComponent();
}
private void scanBox_TextChanged(object sender, EventArgs e)
{
if (_typingTimer == null)
{
/* WinForms: */
_typingTimer = new Timer();
_typingTimer.Interval = 300;
/* WPF:
_typingTimer = new DispatcherTimer();
_typingTimer.Interval = TimeSpan.FromMilliseconds(300);
*/
_typingTimer.Tick += new EventHandler(this.handleTypingTimerTimeout);
}
_typingTimer.Stop(); // Resets the timer
_typingTimer.Tag = (sender as TextBox).Text; // This should be done with EventArgs
_typingTimer.Start();
}
private void handleTypingTimerTimeout(object sender, EventArgs e)
{
var timer = sender as Timer; // WinForms
// var timer = sender as DispatcherTimer; // WPF
if (timer == null)
{
return;
}
// Testing - updates window title
var isbn = timer.Tag.ToString();
windowFrame.Text = isbn; // WinForms
// windowFrame.Title = isbn; // WPF
// The timer must be stopped! We want to act only once per keystroke.
timer.Stop();
}
部分代码来自Roslyn语法可视化工具
答案 1 :(得分:1)
我建议使用Microsoft Reactive Extensions作为nuget包提供的解决方案。
Reactive Extensions是一个使用可观察集合和LINQ样式查询运算符组成异步和基于事件的程序的库。
如果使用RX扩展,只需两行代码即可解决问题:
注册活动:此处有count == 10
IObservable<string> textChangedObservable =
Observable.FromEventPattern(textBox1, "TextChanged")
.Select(evt => ((TextBox)evt.Sender).Text).Where(x => x.Length == 10);
订阅活动:
textChangedObservable.Subscribe(e => MessageBox.Show(e));
答案 2 :(得分:0)
检查这是否有帮助。
private System.Timers.Timer timer;
private void scanBox_TextChanged(object sender, EventArgs e)
{
if (scanBox.Text.Length == 10)
{
//wait for 10 chars and then set the timer
timer = new System.Timers.Timer(2000); //adjust time based on time required to enter the last 3 chars
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
}
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
timer.Enabled = false;
if (scanBox.Text.Length == 10)
{
getRecord10();
}
else if (scanBox.Text.Length == 13)
{
getRecord13();
}
else
{
MessageBox.Show("Not in directory", "Error");
}
}
答案 3 :(得分:0)
我寻求了计时器解决方案,并创建了一个简单的类来将其包装得更加整洁。 然后,如果需要,可以从表单中访问 TypingFinished 事件。
TextChanged 事件包装在 HandleCreated 事件中,以防止在将“应用程序设置”设置为文本框时调用该事件。
之所以调用Settings.Default.Save 是因为它对我一直都是正确的,但也可以将其放入 TypingFinished 事件中。
using YourApp.Properties;
using System;
using System.Windows.Forms;
namespace YourApp.Controls
{
public partial class TypeDelayTextBox : TextBox
{
public TypeDelayTextBox()
{
InitializeComponent();
this.HandleCreated += (senderX, argsX) => { this.TextChanged += OnTextChanged; };
}
private void OnTextChanged(object sender, EventArgs args)
{
_timer.Enabled = true;
_timer.Stop();
_timer.Start();
}
private void _timer_Tick(object sender, EventArgs e)
{
_timer.Stop();
Settings.Default.Save();
OnTypingFinished();
}
public event EventHandler TypingFinished;
protected virtual void OnTypingFinished()
{
TypingFinished?.Invoke(this, EventArgs.Empty);
}
}
}
设计师代码:
namespace YourApp.Controls
{
partial class TypeDelayTextBox
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this._timer = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// _timer
//
this._timer.Interval = 3000;
this._timer.Tick += new System.EventHandler(this._timer_Tick);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Timer _timer;
}
}