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

Windows Forms自动完成TextBox无匹配时显示默认值问题求助

解决方案:WinForms AutoComplete TextBox 无匹配时显示新增提示并响应点击

问题根源

默认的AutoCompleteCustomSource更新后需重新绑定才能触发列表刷新,且系统级自动完成列表无法通过常规事件捕获点击操作,必须通过拦截Windows消息实现。


步骤1:实时更新自动完成数据源

在TextBox的TextChanged事件中,根据输入内容动态调用存储过程获取数据,确保无匹配时的提示文本被加入列表并生效:

private void txtClient_TextChanged(object sender, EventArgs e)
{
    var textBox = sender as TextBox;
    if (textBox == null || string.IsNullOrWhiteSpace(textBox.Text))
    {
        textBox.AutoCompleteCustomSource.Clear();
        return;
    }

    // 调用存储过程获取匹配数据(含无匹配时的提示)
    var clientItems = GetClientListFromDB(textBox.Text);
    var autoCompleteColl = new AutoCompleteStringCollection();
    autoCompleteColl.AddRange(clientItems.ToArray());

    // 重新绑定数据源,触发列表刷新
    textBox.AutoCompleteCustomSource = autoCompleteColl;
}

// 封装数据库调用逻辑
private List<string> GetClientListFromDB(string searchText)
{
    var result = new List<string>();
    // 替换为你的数据库连接字符串和存储过程调用代码
    using (var conn = new SqlConnection("YourConnectionString"))
    {
        conn.Open();
        using (var cmd = new SqlCommand("SearchClient", conn))
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@SearchText", searchText);
            
            using (var reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                    result.Add(reader.GetString(0));
                }
            }
        }
    }

    // 若存储过程未返回提示文本,手动添加(根据实际情况调整)
    if (result.Count == 0)
    {
        result.Add("No record found, Click to add new");
    }
    return result;
}

步骤2:捕获自动完成列表的点击事件

WinForms的自动完成列表属于系统控件,需通过拦截WM_COMMAND消息监听选中操作:

自定义TextBox控件(推荐,复用性强)

public class CustomAutoCompleteTextBox : TextBox
{
    private const int WM_COMMAND = 0x0111;
    private const int CBN_SELENDOK = 0x0009;

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        // 拦截自动完成项选中的消息
        if (m.Msg == WM_COMMAND)
        {
            int notifyCode = m.WParam.ToInt32() >> 16;
            if (notifyCode == CBN_SELENDOK)
            {
                string selectedText = this.Text;
                // 判断是否为新增提示项
                if (selectedText.Equals("No record found, Click to add new", StringComparison.OrdinalIgnoreCase))
                {
                    // 打开新增窗体
                    using (var addForm = new AddClientForm())
                    {
                        if (addForm.ShowDialog() == DialogResult.OK)
                        {
                            // 新增成功后刷新数据源
                            RefreshAutoCompleteSource(this.Text);
                        }
                    }
                }
            }
        }
    }

    // 刷新自动完成数据源的方法
    public void RefreshAutoCompleteSource(string searchText)
    {
        var items = GetClientListFromDB(searchText);
        var coll = new AutoCompleteStringCollection();
        coll.AddRange(items.ToArray());
        this.AutoCompleteCustomSource = coll;
    }

    // 复用之前的数据库调用方法
    private List<string> GetClientListFromDB(string searchText)
    {
        // 同步骤1中的实现
    }
}

若不自定义控件,可在窗体中重写WndProc

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    const int WM_COMMAND = 0x0111;
    const int CBN_SELENDOK = 0x0009;

    if (m.Msg == WM_COMMAND)
    {
        int notifyCode = m.WParam.ToInt32() >> 16;
        if (notifyCode == CBN_SELENDOK && m.HWnd == txtClient.Handle)
        {
            string selectedText = txtClient.Text;
            if (selectedText.Equals("No record found, Click to add new", StringComparison.OrdinalIgnoreCase))
            {
                using (var addForm = new AddClientForm())
                {
                    if (addForm.ShowDialog() == DialogResult.OK)
                    {
                        // 刷新数据源
                        txtClient_TextChanged(txtClient, EventArgs.Empty);
                    }
                }
            }
        }
    }
}

关键注意事项

  1. 确保TextBox属性设置正确:
    txtClient.AutoCompleteMode = AutoCompleteMode.Suggest;
    txtClient.AutoCompleteSource = AutoCompleteSource.CustomSource;
    
  2. 存储过程校验:确认无匹配时确实返回了提示文本,或在代码中手动添加(避免空列表无法弹出)。
  3. 新增后刷新:打开新增窗体并成功添加数据后,需重新调用数据源获取方法,更新自动完成列表。

内容的提问来源于stack exchange,提问作者V.Prasad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:45:44