我希望找到一种支持我的WPF TextBox控件的键盘楔形扫描的通用方法。
(当谈到更高级的WPF功能时,我真的很新手,所以在我花大量时间研究之前,我想问一下我是否正朝着正确的方向前进。)
我想要做的是在我的TextBox中添加一个附加属性(或其他东西),这将导致它读取所有输入到框中,然后使用扫描输入调用自定义“ScanCompleted”命令。
如果附加属性不适合这个,那么有没有办法在TextBox上获取此命令而不降低我自己的自定义“ScanableTextBox”?
(注意:扫描的标准(而不是类型化数据)是它将以暂停键(#19)开头,以Return键(#13)结束。)
答案 0 :(得分:4)
我认为这可能是通过附加属性(行为)完成的,但是简单而简单地简化子类TextBox
并覆盖OnTextChanged
,OnKeyDown
,{{ 1}}以及添加自定义功能的类似方法。
为什么不想以这种方式创建自己的控件?
如果你真的不想要一个派生控件,这里有一个附加的行为来完成这个(下面的解释):
OnKeyUp
通过声明 public class ScanReading
{
private static readonly IDictionary<TextBox, ScanInfo> TrackedTextBoxes = new Dictionary<TextBox, ScanInfo>();
public static readonly DependencyProperty ScanCompletedCommandProperty =
DependencyProperty.RegisterAttached("ScanCompletedCommand", typeof (ICommand), typeof (ScanReading),
new PropertyMetadata(default(ICommand), OnScanCompletedCommandChanged));
public static void SetScanCompletedCommand(TextBox textBox, ICommand value)
{
textBox.SetValue(ScanCompletedCommandProperty, value);
}
public static ICommand GetScanCompletedCommand(TextBox textBox)
{
return (ICommand) textBox.GetValue(ScanCompletedCommandProperty);
}
private static void OnScanCompletedCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var textBox = d as TextBox;
if (textBox == null)
return;
var command = (ICommand) e.NewValue;
if (command == null)
{
textBox.Unloaded -= OnTextBoxUnloaded;
textBox.KeyUp -= OnTextBoxKeyUp;
TrackedTextBoxes.Remove(textBox);
}
else
{
textBox.Unloaded += OnTextBoxUnloaded;
TrackedTextBoxes.Add(textBox, new ScanInfo(command));
textBox.KeyUp += OnTextBoxKeyUp;
}
}
static void OnTextBoxKeyUp(object sender, KeyEventArgs e)
{
var textBox = (TextBox) sender;
var scanInfo = TrackedTextBoxes[textBox];
if (scanInfo.IsTracking)
{
if (e.Key == Key.Return)
{
scanInfo.ScanCompletedCommand.Execute(textBox.Text);
scanInfo.IsTracking = false;
}
}
else if (string.IsNullOrEmpty(textBox.Text) && e.Key == Key.Pause)
{
TrackedTextBoxes[textBox].IsTracking = true;
}
}
static void OnTextBoxUnloaded(object sender, RoutedEventArgs e)
{
var textBox = (TextBox) sender;
textBox.KeyUp -= OnTextBoxKeyUp;
textBox.Unloaded -= OnTextBoxUnloaded;
TrackedTextBoxes.Remove(textBox);
}
}
public class ScanInfo
{
public ScanInfo(ICommand scanCompletedCommand)
{
ScanCompletedCommand = scanCompletedCommand;
}
public bool IsTracking { get; set; }
public ICommand ScanCompletedCommand { get; private set; }
}
之类的方式来消费这一点(其中TextBox
是附加属性的命名空间,local
是视图模型上的ScanCompleted
:
ICommand
现在,当设置此属性时,我们会将<TextBox local:ScanReading.ScanCompletedCommand="{Binding ScanCompleted}" />
及其关联的TextBox
添加到静态集合中。
每按一次键,我们检查它是否是 Pause 键。如果是,,如果ICommand
为空,我们会设置一个标记TextBox
以开始查找 Enter 键。
现在每次按下一个键,我们都会检查它是否为 Enter 键。如果是,我们执行命令,传入true
值,并将标志重置为TextBox.Text
的{{1}}。
我们还为false
事件添加了一个处理程序来清理我们的事件订阅,并从静态列表中删除TextBox
。