Domanda

Quale sarebbe il modo migliore per sviluppare una casella di testo che ricordi l'ultimo numero x di voci inserite al suo interno.Questa è un'app autonoma scritta con C#.

È stato utile?

Soluzione

@Ethan

Avevo dimenticato il fatto che avresti voluto salvarlo, quindi non era solo una cosa per sessione: P Ma sì, hai completamente ragione.

Questo è facile, soprattutto perché si tratta solo di stringhe di base, basta scrivere il contenuto di AutoCompleteCustomSource dal TextBox in un file di testo, su righe separate.

Avevo qualche minuto, quindi ho scritto un esempio di codice completo... lo avrei fatto prima perché cerco sempre di mostrare il codice, ma non ho avuto tempo.Comunque, ecco tutto (meno il codice del designer).

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

Questo codice funzionerà esattamente così com'è, devi solo creare la GUI con una casella di testo denominata txtMain e collegare gli eventi KeyDown, Closed e Load alla casella di testo e al modulo principale.

Si noti inoltre che, per questo esempio e per semplificare, ho semplicemente scelto di rilevare la pressione del tasto Invio come trigger per salvare la stringa nella raccolta.Probabilmente ci sono più/diversi eventi che sarebbero migliori, a seconda delle tue esigenze.

Inoltre, il modello utilizzato per popolare la collezione non è molto "intelligente". Elimina semplicemente la stringa più antica quando la collezione arriva al limite di 10.Questo probabilmente non è l'ideale, ma funziona per l'esempio.Probabilmente vorresti una sorta di sistema di valutazione (soprattutto se vuoi davvero che sia simile a Google)

Un'ultima nota: i suggerimenti verranno effettivamente visualizzati nell'ordine in cui si trovano nella raccolta.Se per qualche motivo desideri che vengano visualizzati in modo diverso, ordina semplicemente l'elenco come preferisci.

Spero che aiuti!

Altri suggerimenti

In realtà questo è abbastanza semplice, soprattutto in termini di visualizzazione della parte "Completamento automatico".In termini di ricordare l'ultimo numero x di voci, dovrai semplicemente decidere un particolare evento (o eventi) che consideri come una voce in fase di completamento e scrivere quella voce in un elenco...un AutoCompleteStringCollection per essere precisi.

La classe TextBox ha le 3 seguenti proprietà di cui avrai bisogno:

  • Completamento automaticoCustomSource
  • Modalità di completamento automatico
  • AutoCompleteSource

Imposta AutoCompleteMode su SuggestAppend e AutoCompleteSource su CustomSource.

Quindi in fase di esecuzione, ogni volta che viene creata una nuova voce, utilizzare il metodo Add() di AutoCompleteStringCollection per aggiungere quella voce all'elenco (e, se lo si desidera, eliminare quelle vecchie).Puoi effettivamente eseguire questa operazione direttamente sulla proprietà AutoCompleteCustomSource di TextBox purché l'abbia già inizializzata.

Ora, ogni volta che digiti nella casella di testo, verranno suggerite le voci precedenti :)

Vedi questo articolo per un esempio più completo: http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

Il completamento automatico ha anche alcune funzionalità integrate come FileSystem e URL (anche se fa solo cose che sono state digitate in IE...)

Memorizzo l'elenco di completamento nel registro.

Il codice che utilizzo è riportato di seguito.È riutilizzabile, in tre passaggi:

  1. sostituisci lo spazio dei nomi e il nome classe in questo codice con qualunque cosa usi.
  2. Chiama FillFormFromRegistry() nel modulo Carico evento e chiamare SaveFormToRegistry sul file Chiusura evento.
  3. compilalo nel tuo progetto.

Devi decorare l'assieme con due attributi: [assembly: AssemblyProduct("...")] E [assembly: AssemblyCompany("...")] .(Questi attributi vengono normalmente impostati automaticamente nei progetti creati in Visual Studio, quindi non lo considero un passaggio.)

La gestione dello stato in questo modo è totalmente automatica e trasparente per l'utente.

Puoi utilizzare lo stesso modello per archiviare qualsiasi tipo di stato per la tua app WPF o WinForms.Come lo stato delle caselle di testo, delle caselle di controllo, dei menu a discesa.Inoltre puoi memorizzare/ripristinare la dimensione della finestra - davvero utile: la prossima volta che l'utente esegue l'app, si apre nello stesso posto e con le stesse dimensioni di quando l'ha chiusa.Puoi memorizzare il numero di volte in cui un'app è stata eseguita.Molte possibilità.

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

Alcune persone evitare di utilizzare il Registro di sistema per archiviare lo stato, ma trovo che sia davvero facile e conveniente.Se lo desideri, puoi creare molto facilmente un programma di installazione che rimuova tutte le chiavi di registro durante la disinstallazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top