忽略重音的文本框上的自动完成

Posted

技术标签:

【中文标题】忽略重音的文本框上的自动完成【英文标题】: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 与建议 【参考方案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);
    

【讨论】:

以上是关于忽略重音的文本框上的自动完成的主要内容,如果未能解决你的问题,请参考以下文章

成功完成初始自动完成后,如何在 WinForm 文本框上重新启动自动完成?

如何在访问中禁用组合框上的自动完成功能?

禁用文本框后 JQuery UI 自动完成功能不起作用

jquery自动完成数据源更改

jquerymobile自动完成列表未隐藏

jquery 自动完成功能不适用于重音