2008-09-04 102 views

回答

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文本框的GUI和挂钩在KeyDown,关闭和加载事件的文本框和主要形式。

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

另外,用于填充集合的模型不是很“聪明”。它只是在集合达到10的限制时删除最旧的字符串。这可能不是理想的,但适用于该示例。你可能会需要某种等级制度(特别是如果你真的希望它是谷歌十岁上下)

最后需要说明的,该建议实际上将他们集合中的顺序显示。如果出于某种原因,您希望它们以不同的方式显示,请按照您的喜好对列表进行排序。

希望有帮助!

6

这实际上相当容易,特别是在显示“自动完成”部分方面。关于最后x个条目的记忆,您只需决定一个特定事件(或多个事件),您将其视为一个正在完成的条目,然后将该条目写入列表中;将AutoCompleteStringCollection设置为精确。

TextBox类具有以下3个属性,你将需要:

  • AutoCompleteCustomSource
  • AutoCompleteMode
  • AutoCompleteSource

设置AutoCompleteMode到SuggestAppend和AutoCompleteSource到CustomSource。

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

,每次你在文本框中键入时它会提示以前的条目:)

一个更完整的示例,请参见这篇文章:http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

自动完成也有一些内置的像文件系统和URL特征(虽然它只做东西,被输入到IE浏览器...)

1

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

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

  1. 替换此代码中的命名空间和类名称与您使用的任何。
  2. 调用窗体的加载事件上的FillFormFromRegistry(),并调用关闭事件中的SaveFormToRegistry。
  3. 编译成你的项目。

您需要装饰具有两个属性的组件:[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,但我觉得这很容易和方便。如果你喜欢,你可以很容易地建立一个安装程序,删除卸载所有注册表项。