Google Suggestish文本框(自动填充)

时间:2008-09-04 01:06:51

标签: c# winforms autocomplete

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

3 个答案:

答案 0 :(得分:6)

这实际上相当容易,特别是在显示“自动完成”部分方面。在记住最后x个条目时,您只需要决定您认为是完成的条目的特定事件(或事件),并将该条目写入列表... AutoCompleteStringCollection将是精确。

TextBox类具有以下3个属性:

  • AutoCompleteCustomSource
  • AutoCompleteMode
  • AutoCompleteSource

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

然后在运行时,每次创建一个新条目时,使用AutoCompleteStringCollection的Add()方法将该条目添加到列表中(如果需要,弹出任何旧条目)。实际上,您可以直接在TextBox的AutoCompleteCustomSource属性上执行此操作,只要您已经初始化它。

现在,每次输入TextBox时,都会建议以前的条目:)

有关更完整的示例,请参阅此文章:http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

AutoComplete还有一些内置功能,如FileSystem和URL(尽管它只会输入输入到IE中的内容......)

答案 1 :(得分:3)

@Ethan

我忘了这样一个事实:你想要保存它,所以它不是每个会话唯一的东西:P但是,是的,你是完全正确的。

这很容易完成,特别是因为它只是基本的字符串,只需将TextBox中的AutoCompleteCustomSource的内容写入文本文件中,就行了。

我有几分钟的时间,所以我写了一个完整的代码示例...我会在之前尝试显示代码,但没有时间。无论如何,这是整个事情(减去设计师代码)。

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的TextBox创建GUI,并将KeyDown,Closed和Load事件连接到TextBox和Main表单。

另请注意,对于此示例并使其简单,我只是选择检测按下的Enter键作为我的触发器以将字符串保存到集合中。根据您的需要,可能有更多/不同的事件会更好。

此外,用于填充集合的模型不是很“聪明”。它只是在集合达到10的限制时删除最旧的字符串。这可能不太理想,但适用于该示例。您可能需要某种评级系统(特别是如果您真的希望它是Google-ish)

最后一点,这些建议实际上会按照它们在集合中的顺序显示。如果由于某种原因您希望它们以不同方式显示,只需按照您喜欢的方式对列表进行排序。

希望有所帮助!

答案 2 :(得分:1)

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

我使用的代码如下。它可以通过三个步骤重复使用:

  1. 将此代码中的命名空间和类名替换为您使用的任何内容。
  2. 在表单的加载事件中调用FillFormFromRegistry(),并在关闭事件上调用SaveFormToRegistry。
  3. 将其编译到您的项目中。
  4. 您需要使用两个属性装饰程序集:[assembly: AssemblyProduct("...")][assembly: AssemblyCompany("...")]。 (这些属性通常在Visual Studio中创建的项目中自动设置,因此我不将其视为一个步骤。)

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

    您可以使用相同的模式为WPF或WinForms应用程序存储任何类型的状态。就像文本框状态,复选框,下拉列表一样。你也可以store/restore the size of the window - 非常方便 - 下次用户运行应用程序时,它会在同一个地方打开,并且大小与打开时相同。你可以store the number of times an app has been run。很多可能性。

    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("¡", "&#161;");
                }
                return s;
            }
            public static string XmlUnescapeIexcl(this String s)
            {
                while (s.Contains("&#161;"))
                {
                    s = s.Replace("&#161;", "¡");
                }
                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;
            }
        }
    }
    

    有些人shy away from using the Registry for storing state,但我发现它非常简单方便。如果您愿意,可以非常轻松地构建一个安装程序,在卸载时删除所有注册表项。