WPF 可编辑ComboBox移除列表项时如何保留已选文本不被清空
可编辑ComboBox移除已选列表项时保留显示文本的实现
这个问题不需要第三方库,也不用hack依赖属性,用原生Dispatcher调度就能解决,代码非常简单。
核心原因是你之前同步回写值的时机不对:ComboBox响应ItemsSource集合变更、清空选中值的逻辑是排在调度队列里的,你在当前同步代码块里给绑定属性赋值,等你代码跑完控件才会执行内部重置逻辑,直接把你赋的值覆盖掉。
实现步骤
- 修改选项列表前,直接取ComboBox控件的
Text属性暂存当前显示内容,不要取绑定的SelectedItem/SelectedValue - 正常执行你的列表修改操作:不管是调用
Clear()、移除指定项、还是替换整个ObservableCollection都可以 - 用
Dispatcher.BeginInvoke把回写文本的操作投递到低优先级队列,等ComboBox内部的重置逻辑执行完成后再赋值,这时候回写的文本不在选项列表中,会被控件自动识别为用户自定义输入,不会再被清空。
参考代码如下:
// 暂存当前显示的文本 string holdText = MyEditableComboBox.Text; // 执行你需要的列表变更操作 ListOptions.Clear(); // 移除单个项逻辑示例:ListOptions.Remove(targetItem); // 替换整个集合逻辑示例:ListOptions = new ObservableCollection<string>(newList); // 低优先级调度回写,绕开控件内部的重置逻辑 Dispatcher.BeginInvoke(new Action(() => { MyEditableComboBox.Text = holdText; // 双向绑定场景下可同步赋值给绑定源 SelectedListString = holdText; }), System.Windows.Threading.DispatcherPriority.Background);
补充说明
- 不要尝试拦截
SourceUpdated事件:这个事件只有在绑定设置了NotifyOnSourceUpdated=True、且绑定源主动触发更新时才会触发,ComboBox内部清空选中值的流程不会触发该事件,完全拦不住。 - 这个方案完全复用控件原生的自定义输入逻辑,没有副作用:回写后控件状态和用户手动输入不在列表内的自定义项完全一致,后续如果再往列表中添加同值选项,也能正常匹配选中。
内容的提问来源于stack exchange,提问作者Stephen Teodori
相关产品推荐
相关产品推荐

