Question

Quelle serait la meilleure façon de développer une zone de texte qui mémorise le dernier nombre x d'entrées qui y ont été insérées.Il s'agit d'une application autonome écrite en C#.

Était-ce utile?

La solution

@Éthan

J'ai oublié le fait que vous voudriez sauvegarder cela pour que ce ne soit pas uniquement une chose par session :P Mais oui, vous avez tout à fait raison.

Cela se fait facilement, d'autant plus qu'il ne s'agit que de chaînes de base, il suffit d'écrire le contenu de AutoCompleteCustomSource de TextBox dans un fichier texte, sur des lignes séparées.

J'avais quelques minutes, alors j'ai rédigé un exemple de code complet... Je l'aurais fait avant car j'essaie toujours d'afficher le code, mais je n'ai pas eu le temps.Quoi qu'il en soit, voici le tout (moins le code du concepteur).

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

Ce code fonctionnera exactement tel quel, il vous suffit de créer l'interface graphique avec une TextBox nommée txtMain et de connecter les événements KeyDown, Closed et Load au TextBox et au formulaire Main.

Notez également que, pour cet exemple et pour faire simple, j'ai simplement choisi de détecter l'appui sur la touche Entrée comme déclencheur pour enregistrer la chaîne dans la collection.Il y a probablement plus d'événements différents qui seraient meilleurs, en fonction de vos besoins.

De plus, le modèle utilisé pour remplir la collection n'est pas très «intelligent». Il supprime simplement la chaîne la plus ancienne lorsque la collection atteint la limite de 10.Ce n'est probablement pas idéal, mais cela fonctionne pour l'exemple.Vous voudriez probablement une sorte de système de notation (surtout si vous voulez vraiment qu'il ressemble à Google)

Une dernière remarque : les suggestions apparaîtront dans l'ordre dans lequel elles se trouvent dans la collection.Si, pour une raison quelconque, vous souhaitez qu'ils s'affichent différemment, triez simplement la liste comme bon vous semble.

J'espère que cela pourra aider!

Autres conseils

C'est en fait assez simple, notamment en termes d'affichage de la partie "AutoComplete".Pour ce qui est de mémoriser le dernier nombre x d'entrées, vous devrez simplement décider d'un ou plusieurs événements particuliers que vous considérez comme une entrée en cours de réalisation et rayer cette entrée sur une liste...un AutoCompleteStringCollection pour être précis.

La classe TextBox possède les 3 propriétés suivantes dont vous aurez besoin :

  • AutoCompleteCustomSource
  • Mode de saisie semi-automatique
  • Source de saisie semi-automatique

Définissez AutoCompleteMode sur SuggestAppend et AutoCompleteSource sur CustomSource.

Ensuite, au moment de l'exécution, chaque fois qu'une nouvelle entrée est créée, utilisez la méthode Add() de AutoCompleteStringCollection pour ajouter cette entrée à la liste (et supprimez les anciennes si vous le souhaitez).Vous pouvez en fait effectuer cette opération directement sur la propriété AutoCompleteCustomSource du TextBox tant que vous l'avez déjà initialisé.

Désormais, chaque fois que vous tapez dans TextBox, des entrées précédentes seront suggérées :)

Voir cet article pour un exemple plus complet : http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

AutoComplete possède également des fonctionnalités intégrées telles que FileSystem et les URL (bien qu'il ne fasse que des éléments saisis dans IE...)

Je stocke la liste d'achèvement dans le registre.

Le code que j'utilise est ci-dessous.Il est réutilisable, en trois étapes :

  1. remplacez l'espace de noms et le nom de classe dans ce code par ce que vous utilisez.
  2. Appelez FillFormFromRegistry() sur le formulaire Charger événement et appelez SaveFormToRegistry sur le Fermeture événement.
  3. compilez-le dans votre projet.

Vous devez décorer l'assemblage avec deux attributs : [assembly: AssemblyProduct("...")] et [assembly: AssemblyCompany("...")] .(Ces attributs sont normalement définis automatiquement dans les projets créés dans Visual Studio, je ne considère donc pas cela comme une étape.)

Cette gestion de l'état est totalement automatique et transparente pour l'utilisateur.

Vous pouvez utiliser le même modèle pour stocker n'importe quel type d'état pour votre application WPF ou WinForms.Comme l'état des zones de texte, des cases à cocher, des listes déroulantes.Aussi vous pouvez stocker/restaurer la taille de la fenêtre - très pratique - la prochaine fois que l'utilisateur exécutera l'application, elle s'ouvrira au même endroit et avec la même taille que lorsqu'il l'a fermée.Tu peux stocker le nombre de fois qu'une application a été exécutée.Beaucoup de possibilités.

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

Certaines personnes évitez d'utiliser le registre pour stocker l'état, mais je trouve que c'est vraiment simple et pratique.Si vous le souhaitez, vous pouvez très facilement créer un programme d'installation qui supprime toutes les clés de registre lors de la désinstallation.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top