使用“附属物”是输入捕获的好习惯吗?

时间:2012-04-30 20:45:43

标签: wpf xaml attached-properties

我希望找到一种支持我的WPF TextBox控件的键盘楔形扫描的通用方法。

(当谈到更高级的WPF功能时,我真的很新手,所以在我花大量时间研究之前,我想问一下我是否正朝着正确的方向前进。)

我想要做的是在我的TextBox中添加一个附加属性(或其他东西),这将导致它读取所有输入到框中,然后使用扫描输入调用自定义“ScanCompleted”命令。

如果附加属性不适合这个,那么有没有办法在TextBox上获取此命令而不降低我自己的自定义“ScanableTextBox”?

(注意:扫描的标准(而不是类型化数据)是它将以暂停键(#19)开头,以Return键(#13)结束。)

1 个答案:

答案 0 :(得分:4)

我认为这可能是通过附加属性(行为)完成的,但是简单而简单地简化子类TextBox并覆盖OnTextChangedOnKeyDown,{{ 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