2008-09-04 35 views

Trả lời

3

@Ethan

tôi quên mất thực tế là bạn sẽ muốn lưu đó để nó không phải là một trong mỗi phiên chỉ điều: P Nhưng có, bạn hoàn toàn chính xác.

Điều này có thể dễ dàng thực hiện, đặc biệt vì nó chỉ là chuỗi cơ bản, chỉ cần ghi nội dung của AutoCompleteCustomSource từ TextBox vào tệp văn bản, trên các dòng riêng biệt.

Tôi đã có một vài phút, vì vậy tôi đã viết một ví dụ mã hoàn chỉnh ... Tôi đã có trước khi tôi luôn cố gắng để hiển thị mã, nhưng không có thời gian. Dù sao, đây là toàn bộ điều (trừ mã thiết kế).

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(); 
     } 
    } 
} 

Mã này sẽ làm việc chính xác như là, bạn chỉ cần để tạo ra các giao diện với một TextBox tên txtMain và treo lên các KeyDown, đóng và các sự kiện Load để TextBox và hình thức chính. Cũng cần lưu ý rằng, đối với ví dụ này và để làm cho nó đơn giản, tôi chỉ cần chọn để phát hiện phím Enter đang được nhấn làm trình kích hoạt của tôi để lưu chuỗi vào bộ sưu tập. Quay lại đầu trang Có thể có nhiều sự kiện khác nhau sẽ tốt hơn, tùy thuộc vào nhu cầu của bạn.

Ngoài ra, mô hình được sử dụng để điền tập hợp không phải là rất "thông minh". Nó chỉ đơn giản là xóa chuỗi cũ nhất khi bộ sưu tập được giới hạn là 10. Điều này có thể không lý tưởng, nhưng hoạt động cho ví dụ.Bạn có thể muốn một số loại hệ thống xếp hạng (đặc biệt nếu bạn thực sự muốn nó là Google-ish)

Lưu ý cuối cùng, các đề xuất sẽ thực sự hiển thị theo thứ tự trong bộ sưu tập. Nếu vì một số lý do bạn muốn chúng hiển thị khác nhau, chỉ cần sắp xếp danh sách theo cách bạn muốn.

Hy vọng điều đó sẽ hữu ích!

6

Điều này thực sự khá dễ dàng, đặc biệt là về việc hiển thị phần "Tự động hoàn tất" của nó. Về việc nhớ số x mục nhập cuối cùng, bạn sẽ chỉ phải quyết định một sự kiện cụ thể (hoặc sự kiện) mà bạn xem là một mục được hoàn thành và ghi mục nhập đó vào danh sách ... một AutoCompleteStringCollection sẽ là tóm lược.

Lớp TextBox có 3 thuộc tính sau đó bạn sẽ cần:

  • AutoCompleteCustomSource
  • AutoCompleteMode
  • AutoCompleteSource

Set AutoCompleteMode để SuggestAppend và AutoCompleteSource để CustomSource. Sau đó, tại thời gian chạy, mỗi lần một mục mới được thực hiện, sử dụng phương thức Add() của AutoCompleteStringCollection để thêm mục đó vào danh sách (và bật ra bất kỳ mục cũ nào nếu bạn muốn). Bạn thực sự có thể thực hiện thao tác này trực tiếp trên thuộc tính AutoCompleteCustomSource của TextBox miễn là bạn đã khởi tạo nó.

Bây giờ, mỗi khi bạn gõ vào TextBox nó sẽ gợi ý mục trước :)

Xem bài viết này cho một ví dụ hoàn chỉnh hơn: http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

AutoComplete cũng có một số được xây dựng trong các tính năng như FileSystem và URL (mặc dù nó chỉ làm những thứ mà đã được gõ vào IE ...)

1

Tôi lưu trữ danh sách hoàn thành trong sổ đăng ký.

Mã tôi sử dụng ở bên dưới. Có thể sử dụng lại, theo ba bước:

  1. thay thế không gian tên và tên lớp trong mã này bằng bất kỳ thứ gì bạn sử dụng.
  2. Gọi FillFormFromRegistry() trên các sự kiện Tải của Biểu mẫu và gọi SaveFormToRegistry theo sự kiện Đóng.
  3. biên dịch điều này vào dự án của bạn.

Bạn cần phải trang trí lắp ráp với hai thuộc tính: [assembly: AssemblyProduct("...")][assembly: AssemblyCompany("...")]. (Các thuộc tính này thường được đặt tự động trong các dự án được tạo trong Visual Studio, vì vậy tôi không tính đây là bước.)

Quản lý trạng thái này hoàn toàn tự động và minh bạch cho người dùng.

Bạn có thể sử dụng cùng một mẫu để lưu trữ bất kỳ loại trạng thái nào cho ứng dụng WPF hoặc WinForms của mình. Giống như trạng thái của hộp văn bản, hộp kiểm, menu thả xuống. Ngoài ra, bạn có thể store/restore the size of the window - thực sự tiện dụng - vào lần tiếp theo người dùng chạy ứng dụng, ứng dụng sẽ mở ở cùng một nơi và với cùng kích thước, như khi họ đóng. Bạn có thể store the number of times an app has been run. Rất nhiều khả năng.

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; 
     } 
    } 
} 

Một số người shy away from using the Registry for storing state, nhưng tôi thấy nó thực sự dễ dàng và thuận tiện. Nếu bạn thích, bạn có thể dễ dàng xây dựng một trình cài đặt để loại bỏ tất cả các khóa registry khi gỡ cài đặt.

Các vấn đề liên quan