Google Suggestish-Textfeld (automatische Vervollständigung)
-
09-06-2019 - |
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.
Lösung
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:
- Ersetzen Sie den Namespace und den Klassennamen in diesem Code durch das, was Sie verwenden.
- Rufen Sie FillFormFromRegistry() für die Formulare auf Belastung -Ereignis und rufen Sie SaveFormToRegistry auf Schließen Ereignis.
- 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("¡", "¡");
}
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;
}
}
}
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.