当前位置: 首页 > news >正文

关于WPF中ComboBox文本查询功能

一种方法是使用事件(包括MVVM的绑定)

<ComboBox TextBoxBase.TextChanged="ComboBox_TextChanged" />

然而运行时就会发现,这个事件在疯狂的触发,很频繁

在实际应用中,如果关联查询数据库,网络吞吐什么的,就会卡顿

另一种方法是使用IsTextSearchEnabled属性,在文本框敲键盘会自动选择相关项

<ComboBox IsTextSearchEnabled="True" IsTextSearchCaseSensitive="False" TextSearch.TextPath="Name" />

然而又有新的问题,选择项不会显示到文本框(文本框仍然是键盘敲的内容,当然还可能跟Framework版本有关),于是我们需要更深入

试验数据含 3 个项

                    <ComboBox TextBoxBase.TextChanged="ComboBox_TextChanged"><ComboBoxItem>啊啊啊</ComboBoxItem><ComboBoxItem>哦哦哦</ComboBoxItem><ComboBoxItem>呃呃呃</ComboBoxItem></ComboBox>

试验一:绑定 TextChanged 和 SelectionChanged 调试

        private void Combobox_TextChanged(object sender, TextChangedEventArgs e){// e.OriginalSource == TextBox, e.Source == sender == Comboboxvar tb = e.OriginalSource as TextBox;var cb = e.Source as ComboBox;var cs = e.Changes.ToArray();int alen = -1, offs = -1, rlen = -1;if (cs.Length > 0) { alen = cs[0].AddedLength; offs = cs[0].Offset; rlen = cs[0].RemovedLength; }var str1 = TextSearch.GetText(cmbStudios);System.Diagnostics.Debug.Print($"TextBox.Text={tb.Text},ComboBox.Text={cb.Text},TextSearch.Text={str1},Action={e.UndoAction}, Changes={cs.Length}: [0]={{{alen},{offs},{rlen}}}\r\n");}private void Combobox_SelectionChanged(object sender, SelectionChangedEventArgs e){var cb = e.Source as ComboBox;System.Diagnostics.Debug.Print($"ComboBox.Text={cb.Text},SelectedItem={cb.SelectedItem}\r\n");}

记录

TextBox.Text=a,ComboBox.Text=,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,0}
TextBox.Text=啊,ComboBox.Text=啊,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,1}
TextBox.Text=啊,ComboBox.Text=啊,TextSearch.Text=,Action=None, Changes=0: [0]={-1,-1,-1}
TextBox.Text=啊,ComboBox.Text=啊,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,1}
ComboBox.Text=啊,SelectedItem=啊啊啊
TextBox.Text=啊啊啊,ComboBox.Text=啊啊啊,TextSearch.Text=,Action=Create, Changes=1: [0]={3,0,1}

也就是选择项目正常设置Text属性,但是现在我们要让Text改变自动选择项目

试验二:启用IsTextSearchEnabled属性

TextBox.Text=a,ComboBox.Text=,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,0}
ComboBox.Text=,SelectedItem=啊啊啊
TextBox.Text=啊,ComboBox.Text=啊啊啊,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,1}
TextBox.Text=啊,ComboBox.Text=啊,TextSearch.Text=,Action=None, Changes=0: [0]={-1,-1,-1}
TextBox.Text=啊,ComboBox.Text=啊,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,1}
TextBox.Text=啊,ComboBox.Text=啊,TextSearch.Text=,Action=Create, Changes=1: [0]={1,0,1}

敲a一次,空格变成“啊”自动选择“啊啊啊”项目,然后就开始抽,完全看不到适当的介入时机

用过Win10的都知道,文件夹右上角的搜索框,能在输入法完成后才开始搜索,所以一定是可以实现的

换网,查英文资料发现Win11中有TextCompositionEnded事件,但是WPF中找不到,类似的TextCompositionManager外挂

实验三:启用TextComposition事件

<TextBox TextCompositionManager.TextInputStart="TextBox_TextInputStart" TextCompositionManager.TextInputUpdate="TextBox_TextInputUpdate" TextCompositionManager.TextInput="TextBox_TextInput" />

事件响应代码

        private void TextBox_TextInputStart(object sender, TextCompositionEventArgs e){var tc = e.TextComposition;string text = $" CompositionText={tc.CompositionText},ControlText={tc.ControlText},ControlText={tc.SystemText},Text={tc.Text} ";System.Diagnostics.Debug.Print($"TextInputStart() ControlText={e.ControlText},SystemText={e.SystemText},Text={e.Text},TextComposition={{{text}}}\r\n");}private void TextBox_TextInputUpdate(object sender, TextCompositionEventArgs e){var tc = e.TextComposition;string text = $" CompositionText={tc.CompositionText},ControlText={tc.ControlText},ControlText={tc.SystemText},Text={tc.Text} ";System.Diagnostics.Debug.Print($"TextInputUpdate() ControlText={e.ControlText},SystemText={e.SystemText},Text={e.Text},TextComposition={{{text}}}\r\n");}private void TextBox_TextInput(object sender, TextCompositionEventArgs e){var tc = e.TextComposition;string text = $" CompositionText={tc.CompositionText},ControlText={tc.ControlText},ControlText={tc.SystemText},Text={tc.Text} ";System.Diagnostics.Debug.Print($"TextInput() ControlText={e.ControlText},SystemText={e.SystemText},Text={e.Text},TextComposition={{{text}}}\r\n");}

记录

TextInputStart() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=,ControlText=,ControlText=,Text= }
TextInputUpdate() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=a,ControlText=,ControlText=,Text= }
TextInputUpdate() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=啊,ControlText=,ControlText=,Text= }

没有TextInput事件!

英文资料显示,会依次触发 TextCompositionStarted、TextChanging、TextChanged、TextCompositionChanged、TextCompositionEnded 事件

思考是隧道事件的问题:

如上面提到的外挂,WPF中的控件其实都外挂的,而且还可以自己给现有的类添加属性、方法和事件(参考:Binding Property)

由于可以任意的排布所有的控件,因此事件的响应与传统的MFC控件就开始有差异

如图,如果鼠标点在2上,传统的事件会由2响应,容器1对此一无所知

这有什么问题?有没有问题就看你怎么看问题。

所谓路由事件是把响应规则扩展为3类:

1.直接事件:等同传统事件

2.冒泡事件:从內向外依次触发,直到Handled被设置

3.隧道事件:从外向内依次触发,直到Handled被设置,这样容器就有机会在内部控件之前做出响应,事件一般以Preview开头,常见的如多个带滚动条的控件互相包含

试验四:加入Preview事件

PreviewTextInputStart() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=,ControlText=,ControlText=,Text= }
TextInputStart() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=,ControlText=,ControlText=,Text= }
PreviewTextInputUpdate() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=a,ControlText=,ControlText=,Text= }
TextInputUpdate() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=a,ControlText=,ControlText=,Text= }
PreviewTextInputUpdate() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=啊,ControlText=,ControlText=,Text= }
TextInputUpdate() ControlText=,SystemText=,Text=,TextComposition={ CompositionText=啊,ControlText=,ControlText=,Text= }
PreviewTextInput() ControlText=,SystemText=,Text=啊,TextComposition={ CompositionText=,ControlText=,ControlText=,Text=啊 }

所有的都可以不管,只看PreviewTextInput检查Text属性就是输入法敲出完整的文本时

策略响应的也就简单了

1.加入一个Timer

2.在TextInput事件启动计时器,其它如Start和Update时停止计时器

3.计时器响应执行过滤逻辑,然后停止计时器

当然这是Windows文件搜索框的逻辑,也就是你敲键盘很快的话,中途不会执行搜索,你也可以根据需要进行调整,比如Start也开始计时器,如果Update过一段时间未触发,一样执行逻辑

http://www.lryc.cn/news/525294.html

相关文章:

  • 07_游戏加载窗口
  • awk命令进阶
  • 解锁Java中的国密算法:安全保障的密钥
  • 基于迁移学习的ResNet50模型实现石榴病害数据集多分类图片预测
  • 在现有 Docker Desktop 环境下安装与配置独立 Kubernetes环境(Mac)
  • Linux探秘坊-------3.开发工具详解(1)
  • Spring Boot整合Thymeleaf、JDBC Template与MyBatis配置详解
  • 白玉微瑕:闲谈 SwiftUI 过渡(Transition)动画的“口是心非”(下)
  • 论文:深度可分离神经网络存内计算处理芯片
  • hdrnet,Deep Bilateral Learning for Real-Time Image Enhancement解读
  • Android系统开发(十五):从 60Hz 到 120Hz,多刷新率进化简史
  • js判断一个数组对象中是否有相同的值
  • 基于深度学习的视觉检测小项目(十五) 用户的登录界面
  • redis-排查命中率降低问题
  • ui文件转py程序的工具
  • Alluxio 联手 Solidigm 推出针对 AI 工作负载的高级缓存解决方案
  • Oracle 数据库常见字段类型大全及详细解析
  • U3D的.Net学习
  • Tomcat下载配置
  • adb常用指令(完整版)
  • 大数据学习(36)- Hive和YARN
  • C# ASP.NET MVC项目内使用ApiController
  • Kafka 入门与应用实战:吞吐量优化与与 RabbitMQ、RocketMQ 的对比
  • “推理”(Inference)在深度学习和机器学习的语境
  • 字节腾讯阿里大厂面经汇总:Java集合(容器)大厂面试题及参考答案
  • 数据结构(初阶)(一)----算法复杂度
  • 构建高效稳定的网络环境
  • 使用Edge打开visio文件
  • ChatGPT Prompt 编写指南
  • 蚁群算法 (Ant Colony Optimization) 算法详解及案例分析