Frage

Was wäre der beste Weg, ein Textfeld zu entwickeln, das sich die letzten x Einträge merkt, die darin eingefügt wurden?Dies ist eine eigenständige App, die mit C# geschrieben wurde.

War es hilfreich?

Lösung

@Ethan

Ich habe vergessen, dass Sie das speichern möchten, also war es nicht nur eine Sache pro Sitzung :P Aber ja, Sie haben völlig Recht.

Dies ist einfach zu bewerkstelligen, insbesondere da es sich nur um einfache Zeichenfolgen handelt. Schreiben Sie einfach den Inhalt von AutoCompleteCustomSource aus der TextBox in separate Zeilen in eine Textdatei.

Ich hatte ein paar Minuten Zeit, also habe ich ein vollständiges Codebeispiel geschrieben ... Das hätte ich früher getan, da ich immer versuche, Code anzuzeigen, aber ich hatte keine Zeit.Wie auch immer, hier ist das Ganze (abzüglich des Designercodes).

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

Dieser Code funktioniert genau so, wie er ist. Sie müssen lediglich die GUI mit einer TextBox namens txtMain erstellen und die Ereignisse KeyDown, Closed und Load mit der TextBox und dem Main-Formular verknüpfen.

Beachten Sie außerdem, dass ich in diesem Beispiel der Einfachheit halber nur die Erkennung der gedrückten Eingabetaste als Auslöser zum Speichern der Zeichenfolge in der Sammlung ausgewählt habe.Abhängig von Ihren Bedürfnissen gibt es wahrscheinlich mehr/verschiedene Veranstaltungen, die besser wären.

Außerdem ist das Modell, das zur Bevölkerung der Sammlung verwendet wird, nicht sehr "intelligent". Es löscht einfach die älteste Zeichenfolge, wenn die Sammlung an die Grenze von 10 erreicht wird.Das ist wahrscheinlich nicht ideal, funktioniert aber für das Beispiel.Sie möchten wahrscheinlich eine Art Bewertungssystem (insbesondere, wenn Sie möchten, dass es wirklich an Google erinnert).

Eine letzte Anmerkung: Die Vorschläge werden tatsächlich in der Reihenfolge angezeigt, in der sie sich in der Sammlung befinden.Wenn Sie aus irgendeinem Grund möchten, dass sie anders angezeigt werden, sortieren Sie die Liste einfach nach Ihren Wünschen.

Hoffentlich hilft das!

Andere Tipps

Das ist eigentlich ziemlich einfach, insbesondere im Hinblick auf die Anzeige des „AutoComplete“-Teils.Was das Merken der letzteneine AutoCompleteStringCollection, um genau zu sein.

Die TextBox-Klasse verfügt über die drei folgenden Eigenschaften, die Sie benötigen:

  • AutoCompleteCustomSource
  • AutoCompleteMode
  • AutoCompleteSource

Setzen Sie AutoCompleteMode auf SuggestAppend und AutoCompleteSource auf CustomSource.

Verwenden Sie dann zur Laufzeit jedes Mal, wenn ein neuer Eintrag erstellt wird, die Add()-Methode von AutoCompleteStringCollection, um diesen Eintrag zur Liste hinzuzufügen (und entfernen Sie alle alten, wenn Sie möchten).Sie können diesen Vorgang tatsächlich direkt für die AutoCompleteCustomSource-Eigenschaft der TextBox ausführen, sofern Sie sie bereits initialisiert haben.

Jetzt werden bei jeder Eingabe in die TextBox frühere Einträge vorgeschlagen :)

Ein ausführlicheres Beispiel finden Sie in diesem Artikel: http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

AutoComplete verfügt auch über einige integrierte Funktionen wie Dateisystem und URLs (obwohl es nur Dinge ausführt, die in den IE eingegeben wurden ...)

Die Vervollständigungsliste speichere ich in der Registry.

Der Code, den ich verwende, ist unten.Es ist in drei Schritten wiederverwendbar:

  1. Ersetzen Sie den Namespace und den Klassennamen in diesem Code durch das, was Sie verwenden.
  2. Rufen Sie FillFormFromRegistry() für die Formulare auf Belastung -Ereignis und rufen Sie SaveFormToRegistry auf Schließen Ereignis.
  3. Kompilieren Sie dies in Ihr Projekt.

Sie müssen die Baugruppe mit zwei Attributen dekorieren: [assembly: AssemblyProduct("...")] Und [assembly: AssemblyCompany("...")] .(Diese Attribute werden normalerweise automatisch in Projekten festgelegt, die in Visual Studio erstellt wurden, daher zähle ich dies nicht als Schritt.)

Die Statusverwaltung erfolgt auf diese Weise völlig automatisch und für den Benutzer transparent.

Sie können dasselbe Muster verwenden, um beliebige Status für Ihre WPF- oder WinForms-App zu speichern.Wie der Status von Textfeldern, Kontrollkästchen und Dropdowns.Du kannst auch Speichern/Wiederherstellen der Größe des Fensters – wirklich praktisch – wenn der Benutzer die App das nächste Mal ausführt, wird sie an derselben Stelle und in derselben Größe geöffnet wie beim Schließen.Du kannst Speichern Sie, wie oft eine App ausgeführt wurde.Viele Möglichkeiten.

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

Einige Leute Scheuen Sie sich davor, die Registry zum Speichern des Status zu verwenden, aber ich finde es wirklich einfach und praktisch.Wenn Sie möchten, können Sie ganz einfach ein Installationsprogramm erstellen, das bei der Deinstallation alle Registrierungsschlüssel entfernt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top