WinForms ComboBox自定义文本与筛选功能触发异常问题
WinForms 低操作成本ComboBox实现异常问题
我希望实现一款低操作成本的WinForms ComboBox,需满足以下行为要求:
- 用户通过Tab切换、点击、输入等交互操作时,自动展开下拉列表
- 根据ComboBox中的输入文本筛选下拉项(获焦时显示全部项)
- 允许用户输入未在下拉列表中的自定义文本
已完成相关实现,但存在异常问题:当输入未匹配任何项的自定义文本后,若下拉列表处于展开状态,通过Esc键或点击外部控件使ComboBox失焦时,会触发ComboBox.ObjectCollection.cs文件第227行或第230行的异常。
注:实际场景中需处理对象列表,获取选中对象或自定义文本,但简化版仍会触发异常。已升级至WinForms 9版本,问题依旧;仅通过Tab键失焦时无异常,仅Esc或外部点击触发。
简化版实现代码
using System.Data; namespace SearchComboBox { public class MainForm : Form { private ComboBox itemsComboBox; private BindingSource itemsBindingSource; private DataTable itemsTable; private TextBox initialFocusTextBox; private static string[] items = { "First item", "Second item", "Third item", "Item 4", "Item 5", }; public MainForm() { SuspendLayout(); ClientSize = new Size(300, 150); initialFocusTextBox = new TextBox() { Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Left, Location = new Point(12, 12), Size = new Size(276, 23), TabIndex = 0, }; Controls.Add(initialFocusTextBox); itemsComboBox = new ComboBox() { Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Left, Location = new Point(12, 41), Size = new Size(276, 23), TabIndex = 1, }; Controls.Add(itemsComboBox); itemsTable = new DataTable(); itemsTable.Columns.Add("Item", typeof(string)); itemsTable.Columns.Add("Search", typeof(string)); foreach (string item in items) { itemsTable.Rows.Add(item, item.ToLower()); } itemsBindingSource = new BindingSource(); itemsBindingSource.DataSource = itemsTable; itemsComboBox.DisplayMember = "Item"; itemsComboBox.DataSource = itemsBindingSource; itemsComboBox.Click += itemsComboBox_Click; itemsComboBox.Enter += itemsComboBox_Enter; itemsComboBox.TextUpdate += itemsComboBox_TextUpdate; itemsComboBox.SelectedIndex = -1; itemsComboBox.Text = string.Empty; ResumeLayout(false); PerformLayout(); } private void itemsComboBox_Click(object? sender, EventArgs e) { itemsComboBox.DroppedDown = true; } private void itemsComboBox_Enter(object? sender, EventArgs e) { var selectText = itemsComboBox.Text; itemsBindingSource.Filter = null; itemsComboBox.SelectedIndex = -1; itemsComboBox.Text = selectText; itemsComboBox.SelectAll(); itemsComboBox.DroppedDown = true; } private void itemsComboBox_TextUpdate(object? sender, EventArgs e) { var selectText = itemsComboBox.Text; var selectionStart = itemsComboBox.SelectionStart; var selectionLength = itemsComboBox.SelectionLength; if (string.IsNullOrWhiteSpace(selectText)) { itemsBindingSource.Filter = null; } else { itemsBindingSource.Filter = string.Format("Search LIKE '*{0}*'", selectText); } itemsComboBox.Text = selectText; itemsComboBox.SelectionStart = selectionStart; itemsComboBox.SelectionLength = selectionLength; itemsComboBox.DroppedDown = true; } } }
.csproj配置
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net7.0-windows</TargetFramework> <Nullable>enable</Nullable> <UseWindowsForms>true</UseWindowsForms> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> </Project>
异常堆栈信息
> [Exception] System.Windows.Forms.dll!System.Windows.Forms.ComboBox.ObjectCollection.this[int].get(int index) Line 230 C# [Exception] System.Windows.Forms.dll!System.Windows.Forms.ComboBox.Text.get() Line 1250 C# [Exception] SearchComboBox.dll!SearchComboBox.MainForm.itemsComboBox_Enter(object sender, System.EventArgs e) Line 71 C# [Exception] System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.UpdateFocusedControl() Line 1644 C# [Exception] System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.AssignActiveControlInternal(System.Windows.Forms.Control value) Line 558 C# [Exception] System.Windows.Forms.dll!System.Windows.Forms.ContainerControl.ActivateControl(System.Windows.Forms.Control control, bool originator) Line 423 C# [Exception] System.Windows.Forms.dll!System.Windows.Forms.ComboBox.ChildWndProc(ref System.Windows.Forms.Message m) Line 1713 C# [Exception] System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(nint hWnd, Interop.User32.WM msg, nint wparam, nint lparam) Line 369 C# System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(nint hWnd, Interop.User32.WM msg, nint wparam, nint lparam) Line 380 C# [Native to Managed Transition] [Managed to Native Transition] System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.DefWndProc(ref System.Windows.Forms.Message m) Line 515 C# System.Windows.Forms.dll!System.Windows.Forms.ComboBox.ChildWndProc(ref System.Windows.Forms.Message m) Line 1810 C# System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Callback(nint hWnd, Interop.User32.WM msg, nint wparam, nint lparam) Line 369 C# [Native to Managed Transition] [Managed to Native Transition] System.Windows.Forms.dll!System.Windows.Forms.Application.ComponentManager.Interop.Mso.IMsoComponentManager.FPushMessageLoop(nuint dwComponentID, Interop.Mso.msoloop uReason, void* pvLoopData) Line 345 C# System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Interop.Mso.msoloop reason, System.Windows.Forms.ApplicationContext context) Line 1117 C# System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Interop.Mso.msoloop reason, System.Windows.Forms.ApplicationContext context) Line 981 C# SearchComboBox.dll!SearchComboBox.Program.Main() Line 14 C#
内容的提问来源于stack exchange,提问作者Milan Majer
相关产品推荐
相关产品推荐

