You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WinForms .NET PropertyGrid的自定义UITypeEditor下拉框中实现自动补全?

在WinForms .NET PropertyGrid中实现输入时自动选中自定义下拉项

我需要实现:用户在PropertyGrid的组合框编辑字段中输入内容时,自动从自定义下拉列表中选中匹配的项。

目前已经通过派生UITypeEditor类在PropertyGrid中托管了自定义下拉列表,但不知道如何捕获PropertyGrid组合框的TextChanged事件来获取输入文本,进而选中下拉列表中对应的项。推测PropertyGrid本身不提供直接的事件支持,需要特殊方法实现,但暂未找到具体方案。

我的自定义C#类代码如下:

class UIDropdownTypeEditor : UITypeEditor
{
    private IWindowsFormsEditorService _editorService = null;
    TypeConverter.StandardValuesCollection _list = null;

    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        // drop down mode
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        _editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

        // Use a list box
        ListBox lb = new ListBox();
        more...
        more...

        // Show dropdown
        _editorService.DropDownControl(lb);
        return lb.SelectedItem;
    }
}

实现方案

方法1:利用ListBox原生自动搜索特性

WinForms的ListBox自带输入匹配定位功能,只需开启相关配置即可实现前缀匹配选中:
在创建ListBox的代码段中添加以下设置:

lb.Sorted = true; // 可选,排序后匹配更精准
lb.SelectionMode = SelectionMode.One;
// 启用原生输入响应,按下字符时自动定位到第一个匹配项
lb.SetStyle(ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true);

这种方式无需额外处理事件,依赖控件原生逻辑,适合简单的前缀匹配场景。

方法2:手动捕获编辑框TextChanged事件实现自定义匹配

如果需要模糊匹配等自定义逻辑,可通过反射获取PropertyGrid内部的文本编辑控件,绑定TextChanged事件:

修改EditValue方法,在创建ListBox后添加以下代码:

// 初始化下拉列表数据(确保_list已填充选项)
_list = new TypeConverter.StandardValuesCollection(/* 你的选项集合 */);
lb.DataSource = _list;

// 通过反射获取PropertyGrid内部的文本编辑框
PropertyGrid propertyGrid = context.Container.Components.OfType<PropertyGrid>().FirstOrDefault();
if (propertyGrid != null)
{
    var gridViewField = propertyGrid.GetType().GetField("gridView", BindingFlags.NonPublic | BindingFlags.Instance);
    if (gridViewField != null)
    {
        var gridView = gridViewField.GetValue(propertyGrid);
        var textEditField = gridView.GetType().GetField("textEdit", BindingFlags.NonPublic | BindingFlags.Instance);
        if (textEditField != null)
        {
            var textEdit = textEditField.GetValue(gridView) as TextBox;
            if (textEdit != null)
            {
                // 绑定文本变更事件
                EventHandler textChangedHandler = null;
                textChangedHandler = (sender, e) =>
                {
                    string input = textEdit.Text.Trim();
                    if (string.IsNullOrEmpty(input)) return;

                    // 自定义匹配逻辑:查找包含输入文本的项(忽略大小写)
                    var matchedItem = _list.Cast<object>()
                        .FirstOrDefault(item => item.ToString().IndexOf(input, StringComparison.OrdinalIgnoreCase) >= 0);
                    
                    if (matchedItem != null)
                    {
                        lb.SelectedItem = matchedItem;
                        lb.TopIndex = lb.SelectedIndex; // 滚动到选中项
                    }
                };

                textEdit.TextChanged += textChangedHandler;

                // 下拉关闭时移除事件,避免内存泄漏
                lb.Disposed += (sender, e) => textEdit.TextChanged -= textChangedHandler;
            }
        }
    }
}

注意事项

  • 反射依赖PropertyGrid的内部实现,不同.NET版本可能存在结构差异,需测试兼容性;
  • 确保_list已正确初始化并填充所有下拉选项;
  • 事件绑定后需在下拉控件销毁时移除事件,防止内存泄漏。

内容的提问来源于stack exchange,提问作者Ray White

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 05:04:51