如何为System.Windows.Input.KeyEventArgs编写过滤器?修复C++类名输入校验问题
修复C# WPF TextBox的C++类名输入过滤问题
问题分析
你的代码失效原因在于仅通过Key枚举判断按键,却忽略了大量非法符号是通过Shift+数字/字母组合输入的(比如Shift+2输入@、Shift+3输入#),且原逻辑只处理了Shift+OemMinus(下划线)的合法情况,未拦截其他Shift组合的非法输入;同时完全没实现「首字符不能为数字」的规则。
修复方案
推荐改用PreviewTextInput事件直接处理输入的文本内容(比判断按键更可靠),同时结合DataObject.Pasting事件拦截非法粘贴操作,导航编辑键的功能会自动保留,无需额外处理。
完整修复代码
using Microsoft.VisualStudio.PlatformUI; using System.Windows.Controls; using System.Windows.Input; using System.Text.RegularExpressions; public partial class AddCppClassDialog : DialogWindow { // 匹配合法C++类名的正则:首字符为字母/下划线,后续为字母/数字/下划线 private readonly Regex _validCppClassNameRegex = new Regex(@"^[a-zA-Z_][a-zA-Z0-9_]*$"); public AddCppClassDialog() { InitializeComponent(); // 处理实时输入 ClassNameTextBox.PreviewTextInput += ClassNameTextBox_PreviewTextInput; // 处理粘贴操作 DataObject.AddPastingHandler(ClassNameTextBox, ClassNameTextBox_Pasting); } private void ClassNameTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e) { var textBox = sender as TextBox; if (textBox == null) return; // 模拟输入后的完整文本 var newText = GetTextAfterInput(textBox, e.Text); // 验证是否符合规则,不符合则禁止输入 if (!_validCppClassNameRegex.IsMatch(newText)) { e.Handled = true; } } private void ClassNameTextBox_Pasting(object sender, DataObjectPastingEventArgs e) { var textBox = sender as TextBox; if (textBox == null || !e.DataObject.GetDataPresent(typeof(string))) { e.CancelCommand(); return; } var pastedText = e.DataObject.GetData(typeof(string)) as string; var newText = GetTextAfterInput(textBox, pastedText); // 验证粘贴内容是否合法,非法则取消粘贴 if (!_validCppClassNameRegex.IsMatch(newText)) { e.CancelCommand(); } } // 辅助方法:计算输入/粘贴后的完整文本 private string GetTextAfterInput(TextBox textBox, string inputText) { var currentText = textBox.Text; if (textBox.SelectionLength > 0) { // 替换选中内容 return currentText.Remove(textBox.SelectionStart, textBox.SelectionLength).Insert(textBox.SelectionStart, inputText); } else { // 在光标位置插入内容 return currentText.Insert(textBox.CaretIndex, inputText); } } }
方案优势
- 直接基于文本内容验证,规避了按键组合判断的遗漏问题,覆盖输入法输入、粘贴等所有输入场景。
- 正则表达式
^[a-zA-Z_][a-zA-Z0-9_]*$严格符合C++类名的语法规则。 - Home、Delete、Back等导航编辑键不会触发
PreviewTextInput事件,功能自动保留,无需额外逻辑处理。
内容的提问来源于stack exchange,提问作者qloq
相关产品推荐
相关产品推荐

