【问题标题】:AutoComplete on a TextBox ignoring accentuation忽略重音的文本框上的自动完成
【发布时间】:2021-06-20 02:43:59
【问题描述】:

我有一个自定义的 TextBox 控件(它是一个自定义控件,而不是常规控件,可以在其上显示提示文本),其中我有一个 AutoComplete 从我的数据库中获取数据像这样使用DataSet

string[] postSource = aux.Tables[0].AsEnumerable().Select<System.Data.DataRow, String>(x => x.Field<String>("nm_industria")).ToArray();
            var source = new AutoCompleteStringCollection();
            source.AddRange(postSource);

txb_regClientData.AutoCompleteCustomSource = source;
            txb_regClientData.AutoCompleteMode = AutoCompleteMode.Suggest;
            txb_regClientData.AutoCompleteSource = AutoCompleteSource.CustomSource;

它给了我这个结果 Image 如果我输入“João”,它会给我正确的结果,但如果我输入“Joao”,它不会出现,从一些关于此事的阅读中我知道 AutoComplete 中没有任何内容可以自动忽略重音,所以我需要自己编写代码。我的问题是,我从哪里开始?我理想的解决方案是覆盖我的自定义控件的AutoComplete 代码中的某些内容,我阅读了 TextBox 的文档但找不到任何内容,所以如果有人能告诉我正确的方向,以便我可以阅读和学习如何做到这一点,将不胜感激。

【问题讨论】:

  • 看来this answer 对你来说是一个好的开始。至于其余的,我可能会建议编写一个包含字符串表示形式的包装类,甚至是字典。并在 textchanged 事件中进行过滤?
  • 这是一个很好的线索,也通过制作包装器和过滤 textchanged,您的意思是自己制作整个 AutoComplete,或者类似于更改 AutoComplete 获取的输入的东西?
  • " 或类似于更改自动完成输入的内容"实际上这是我的第一个想法。给出一种表示用于过滤和一种表示用于显示。但后来我认为,这可能是不可能的,你必须经历“自己制作整个自动完成”的麻烦
  • 设法获得一个更改为最佳建议的标签,整个代码都在我的自定义控件中,我想我会看看我是否可以将listbox 附加到textbox 与建议

标签: c# winforms autocomplete textbox custom-controls


【解决方案1】:

仍有待改进,但此代码实现了解决方案,它将listBox“附加”到textBox,由于命名而存在多个这些问题时会出现问题,但这应该是对于寻找类似东西的人来说,这是一个很好的起点/参考。

public class ExTextBox : TextBox
{
    private bool alreadyRun = false;
    ListBox suggestions = new ListBox();
    int maxSize = 10;
    string[] source;
    public string Hint

    public int MaxSuggestionBoxSize
    {
        get { return maxSize; }
        set { maxSize = value; this.Invalidate(); }
    }

    protected override void OnCreateControl()
    {
        if (alreadyRun == false) // This is only supposed to be run once, but in some situations depending on the design of the main form,
        {// this might need to be somewhere that gets called multiple times, this variable makes so this code is only run once even in those situations
            suggestions.Name = "suggList_" + this.Name;
            suggestions.Location = new Point(this.Location.X, (this.Location.Y + this.Size.Height));
            suggestions.Size = new Size(this.Size.Width, this.Size.Height);
            this.Parent.Controls.Add(suggestions);
            this.Parent.Controls["suggList_" + this.Name].MouseDoubleClick += suggList_MouseDoubleClick;
            this.Parent.Controls["suggList_" + this.Name].Hide();
            alreadyRun = true;
        }
        base.OnCreateControl();
    }

    private void suggList_MouseDoubleClick(object sender, System.EventArgs e)
    {
        this.Text = this.Parent.Controls["suggList_" + this.Name].Text;
    }

    protected override void OnLeave(EventArgs e)
    {
        base.OnLeave(e);
        if(source != null) // Makes sure this code is only executed when the suggestion box is being used, by checking the existance of the source
        {
            try
            {
                if (this.Parent.Controls["suggList_" + this.Name].Focused == false)
                {
                    this.Parent.Controls["suggList_" + this.Name].Hide();
                }
            }
            catch
            {

            }
        }
    }

    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        AutoCompleteSmart();
    }

    public void AutoCompleteSmart()
    {
        if (source != null)
        {
            suggestions.Items.Clear();
            if (this.Text != "")
            {
                foreach (string a in source)
                {
                    if (RemoveDiacritics(a.ToLower()).Contains(RemoveDiacritics(this.Text.ToLower())))
                    {
                        suggestions.Items.Add(a);
                    }
                }
                this.Parent.Controls.Remove(suggestions);
                if (suggestions.Items.Count < maxSize) // Optional code, defines a limit size for the suggestion box
                {
                    suggestions.Size = new Size(this.Size.Width, ((suggestions.ItemHeight * suggestions.Items.Count) + suggestions.ItemHeight));
                }
                else
                {
                    suggestions.Size = new Size(this.Size.Width, ((suggestions.ItemHeight * maxSize) + suggestions.ItemHeight));
                }

                this.Parent.Controls.Add(suggestions);
                this.Parent.Controls["suggList_" + this.Name].BringToFront();
                this.Parent.Controls["suggList_" + this.Name].Show();
            }
            else
            {
                this.Parent.Controls["suggList_" + this.Name].Hide();
            }
        }
    }

    public void AutoCompleteSmartSource(string[] _source)
    {
        source = _source;   
    }

    private static string RemoveDiacritics(string text)
    {
        var normalizedString = text.Normalize(NormalizationForm.FormD);
        var stringBuilder = new StringBuilder();

        foreach (var c in normalizedString)
        {
            var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
            if (unicodeCategory != UnicodeCategory.NonSpacingMark)
            {
                stringBuilder.Append(c);
            }
        }

        return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
    }
}

【讨论】:

    猜你喜欢
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 2015-05-21
    • 1970-01-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    相关资源
    最近更新 更多