关于c#:Google推荐文本框(自动完成)

关于c#:Google推荐文本框(自动完成)

Google Suggestish text box (autocomplete)

开发一个文本框以记住上次输入的最后x个条目的最佳方法是什么。这是一个用C#编写的独立应用程序。


这实际上是相当容易的,特别是在显示其中的"自动完成"部分方面。就记住最后的x个条目而言,您只需要确定一个或多个特定事件(将其视为已完成的条目)并将该条目写到列表中即可... AutoCompleteStringCollection将精确。

TextBox类具有您需要的以下3个属性:

  • AutoCompleteCustomSource
  • 自动完成模式
  • 自动完成源

将AutoCompleteMode设置为RecommendationAppend,将AutoCompleteSource设置为CustomSource。

然后在运行时,每次创建新条目时,请使用AutoCompleteStringCollection的Add()方法将该条目添加到列表中(并根据需要弹出所有旧条目)。实际上,只要您已经初始化了TextBox,就可以直接在TextBox的AutoCompleteCustomSource属性上直接执行此操作。

现在,每次您在文本框中键入内容时,都会提示以前的输入内容:)

有关更多完整示例,请参见本文:http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

AutoComplete还具有一些内置功能,例如FileSystem和URL(尽管它只处理键入IE的内容...)


@Ethan

我忘记了您要保存它的事实,所以这不是每个会话唯一的事情:P但是,是的,您是完全正确的。

这很容易做到,特别是因为它只是基本的字符串,只需将AutoCompleteCustomSource的内容从TextBox写到文本文件中的不同行上即可。

我花了几分钟时间,所以我写了一个完整的代码示例……我以前一直会尝试显示代码,但是没有时间。无论如何,这就是全部(减去设计者代码)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
namespace AutoComplete
{
    public partial class Main : Form
    {
        //so you don't have to address"txtMain.AutoCompleteCustomSource" every time
        AutoCompleteStringCollection acsc;
        public Main()
        {
            InitializeComponent();

            //Set to use a Custom source
            txtMain.AutoCompleteSource = AutoCompleteSource.CustomSource;
            //Set to show drop down *and* append current suggestion to end
            txtMain.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            //Init string collection.
            acsc = new AutoCompleteStringCollection();
            //Set txtMain's AutoComplete Source to acsc
            txtMain.AutoCompleteCustomSource = acsc;
        }

        private void txtMain_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                //Only keep 10 AutoComplete strings
                if (acsc.Count < 10)
                {
                    //Add to collection
                    acsc.Add(txtMain.Text);
                }
                else
                {
                    //remove oldest
                    acsc.RemoveAt(0);
                    //Add to collection
                    acsc.Add(txtMain.Text);
                }
            }
        }

        private void Main_FormClosed(object sender, FormClosedEventArgs e)
        {
            //open stream to AutoComplete save file
            StreamWriter sw = new StreamWriter("AutoComplete.acs");

            //Write AutoCompleteStringCollection to stream
            foreach (string s in acsc)
                sw.WriteLine(s);

            //Flush to file
            sw.Flush();

            //Clean up
            sw.Close();
            sw.Dispose();
        }

        private void Main_Load(object sender, EventArgs e)
        {
            //open stream to AutoComplete save file
            StreamReader sr = new StreamReader("AutoComplete.acs");

            //initial read
            string line = sr.ReadLine();
            //loop until end
            while (line != null)
            {
                //add to AutoCompleteStringCollection
                acsc.Add(line);
                //read again
                line = sr.ReadLine();
            }

            //Clean up
            sr.Close();
            sr.Dispose();
        }
    }
}

此代码将完全按原样工作,您只需要使用名为txtMain的文本框创建GUI,并将KeyDown,Closed和Load事件挂接到TextBox和Main窗体。

还要注意,对于本示例来说,为了简单起见,我只是选择检测按下Enter键作为触发,以将字符串保存到集合中。根据您的需求,可能会有更多/不同的事件会更好。

此外,用于填充集合的模型也不是很"智能"。当集合达到10的限制时,它只是删除最旧的字符串。这可能不是理想的方法,但可以用于示例。您可能需要某种评级系统(特别是如果您确实希望它是Google式的)

最后的注释,建议实际上将按照它们在集合中的顺序显示。如果出于某些原因您希望它们以不同的方式显示,则可以按自己喜欢的方式对列表进行排序。

希望有帮助!


我将完成列表存储在注册表中。

我使用的代码如下。它可重复使用,分三个步骤:

  • 用您使用的任何内容替换此代码中的名称空间和类名。
  • 在Form的Load事件上调用FillFormFromRegistry(),在Closing事件上调用SaveFormToRegistry。
  • 将其编译到您的项目中。
  • 您需要用两个属性装饰装配件:[assembly: AssemblyProduct("...")][assembly: AssemblyCompany("...")]。 (这些属性通常是在Visual Studio中创建的项目中自动设置的,因此我不认为这是一个步骤。)

    以这种方式管理状态是完全自动的,并且对用户透明。

    您可以使用相同的模式为WPF或WinForms应用程序存储任何状态。像文本框,复选框,下拉菜单的状态。此外,您还可以存储/恢复窗口的大小-非常方便-下次用户运行该应用程序时,它会在与关闭窗口时相同的位置以相同的大小打开。您可以存储应用程序已运行的次数。很多可能性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    namespace Ionic.ExampleCode
    {
        public partial class NameOfYourForm
        {
            private void SaveFormToRegistry()
            {
                if (AppCuKey != null)
                {
                    // the completion list
                    var converted = _completions.ToList().ConvertAll(x => x.XmlEscapeIexcl());
                    string completionString = String.Join("??", converted.ToArray());
                    AppCuKey.SetValue(_rvn_Completions, completionString);
                }
            }

            private void FillFormFromRegistry()
            {
                if (!stateLoaded)
                {
                    if (AppCuKey != null)
                    {
                        // get the MRU list of .... whatever
                        _completions = new System.Windows.Forms.AutoCompleteStringCollection();
                        string c = (string)AppCuKey.GetValue(_rvn_Completions,"");
                        if (!String.IsNullOrEmpty(c))
                        {
                            string[] items = c.Split('??');
                            if (items != null && items.Length > 0)
                            {
                                //_completions.AddRange(items);
                                foreach (string item in items)
                                    _completions.Add(item.XmlUnescapeIexcl());
                            }
                        }

                        // Can also store/retrieve items in the registry for
                        //   - textbox contents
                        //   - checkbox state
                        //   - splitter state
                        //   - and so on
                        //
                        stateLoaded = true;
                    }
                }
            }

            private Microsoft.Win32.RegistryKey AppCuKey
            {
                get
                {
                    if (_appCuKey == null)
                    {
                        _appCuKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(AppRegistryPath, true);
                        if (_appCuKey == null)
                            _appCuKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(AppRegistryPath);
                    }
                    return _appCuKey;
                }
                set { _appCuKey = null; }
            }

            private string _appRegistryPath;
            private string AppRegistryPath
            {
                get
                {
                    if (_appRegistryPath == null)
                    {
                        // Use a registry path that depends on the assembly attributes,
                        // that are presumed to be elsewhere. Example:
                        //
                        //   [assembly: AssemblyCompany("Dino Chiesa")]
                        //   [assembly: AssemblyProduct("XPathVisualizer")]

                        var a = System.Reflection.Assembly.GetExecutingAssembly();
                        object[] attr = a.GetCustomAttributes(typeof(System.Reflection.AssemblyProductAttribute), true);
                        var p = attr[0] as System.Reflection.AssemblyProductAttribute;
                        attr = a.GetCustomAttributes(typeof(System.Reflection.AssemblyCompanyAttribute), true);
                        var c = attr[0] as System.Reflection.AssemblyCompanyAttribute;

                        _appRegistryPath = String.Format("Software\\\\{0}\\\\{1}",
                                                         p.Product, c.Company);
                    }
                    return _appRegistryPath;
                }
            }

            private Microsoft.Win32.RegistryKey _appCuKey;
            private string _rvn_Completions ="Completions";
            private readonly int _MaxMruListSize = 14;
            private System.Windows.Forms.AutoCompleteStringCollection _completions;
            private bool stateLoaded;
        }

        public static class Extensions
        {
            public static string XmlEscapeIexcl(this String s)
            {
                while (s.Contains("??"))
                {
                    s = s.Replace("??","");
                }
                return s;
            }
            public static string XmlUnescapeIexcl(this String s)
            {
                while (s.Contains(""))
                {
                    s = s.Replace("","??");
                }
                return s;
            }

            public static List<String> ToList(this System.Windows.Forms.AutoCompleteStringCollection coll)
            {
                var list = new List<String>();
                foreach (string  item in coll)
                {
                    list.Add(item);
                }
                return list;
            }
        }
    }

    有些人回避使用注册表来存储状态,但是我发现它确实非常容易和方便。如果愿意,您可以轻松地构建一个安装程序,以在卸载时删除所有注册表项。


    推荐阅读