Вопрос

Каков был бы наилучший способ создать текстовое поле, которое запоминает последнее x количество записей, которые были в него введены?Это отдельное приложение, написанное на C #.

Это было полезно?

Решение

@Итан

Я забыл о том факте, что вы хотели бы сохранить это, чтобы это было не только для каждого сеанса: P Но да, вы полностью правы.

Это легко сделать, тем более что это всего лишь базовые строки, просто выпишите содержимое AutoCompleteCustomSource из текстового поля в текстовый файл отдельными строками.

У меня было несколько минут, поэтому я написал полный пример кода...Я бы сделал это раньше, поскольку я всегда стараюсь показывать код, но у меня не было времени.В любом случае, вот все это (за вычетом дизайнерского кода).

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

Этот код будет работать точно так, как есть, вам просто нужно создать графический интерфейс с текстовым полем с именем txtMain и подключить события KeyDown, Closed и Load к текстовому полю и основной форме.

Также обратите внимание, что для этого примера и для упрощения я просто выбрал обнаружение нажатия клавиши Enter в качестве триггера для сохранения строки в коллекции.Вероятно, есть больше различных мероприятий, которые были бы лучше, в зависимости от ваших потребностей.

Кроме того, модель, используемая для заполнения коллекции, не очень "умна". Он просто удаляет самую старую строку, когда коллекция достигает предела в 10.Это, вероятно, не идеально, но работает для примера.Вероятно, вам понадобилась бы какая-то рейтинговая система (особенно, если вы действительно хотите, чтобы она была ориентирована на Google).

И последнее замечание: предложения на самом деле будут отображаться в том порядке, в каком они находятся в коллекции.Если по какой-то причине вы хотите, чтобы они отображались по-другому, просто отсортируйте список так, как вам нравится.

Надеюсь, это поможет!

Другие советы

На самом деле это довольно просто, особенно с точки зрения отображения части "автозаполнения".С точки зрения запоминания последнего x количества записей, вам просто нужно будет выбрать конкретное событие (или events), которое вы рассматриваете как завершаемую запись, и записать эту запись в список...AutoCompleteStringCollection, если быть точным.

Класс TextBox имеет 3 следующих свойства, которые вам понадобятся:

  • AutoCompleteCustomSource Автозаполнение пользовательского источника
  • Режим автозаполнения
  • Автозаполняемый источник

Установите для AutoCompleteMode значение SuggestAppend, а для AutoCompleteSource - значение CustomSource.

Затем во время выполнения, каждый раз, когда создается новая запись, используйте метод Add() AutoCompleteStringCollection, чтобы добавить эту запись в список (и удалить все старые, если хотите).На самом деле вы можете выполнить эту операцию непосредственно в свойстве AutoCompleteCustomSource текстового поля, если вы уже инициализировали его.

Теперь, каждый раз, когда вы вводите текстовое поле, оно будет предлагать предыдущие записи :)

Смотрите эту статью для получения более полного примера: http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx

Автозаполнение также имеет некоторые встроенные функции, такие как файловая система и URL-адреса (хотя оно выполняет только то, что было введено в IE ...)

Я храню список завершения в реестре.

Код, который я использую, приведен ниже.Это многоразовый процесс, состоящий из трех этапов:

  1. замените пространство имен и имя_класса в этом коде на все, что вы используете.
  2. Вызовите FillFormFromRegistry() в форме Нагрузка событие, и вызовите SaveFormToRegistry на Закрытие событие.
  3. скомпилируйте это в свой проект.

Вам нужно украсить сборку двумя атрибутами: [assembly: AssemblyProduct("...")] и [assembly: AssemblyCompany("...")] .(Эти атрибуты обычно устанавливаются автоматически в проектах, созданных в Visual Studio, поэтому я не считаю это шагом.)

Управление состоянием таким образом полностью автоматизировано и прозрачно для пользователя.

Вы можете использовать тот же шаблон для сохранения любого состояния для вашего приложения WPF или WinForms.Например, состояние текстовых полей, флажков, выпадающих списков.Также вы можете сохранить / восстановить размер окна - действительно удобно - при следующем запуске приложения пользователем оно открывается в том же месте и с тем же размером, что и при закрытии.Ты можешь храните количество запусков приложения.Множество возможностей.

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

Некоторые люди избегайте использования Реестра для хранения состояния, но я нахожу, что это действительно легко и удобно.Если хотите, Вы можете очень легко создать программу установки, которая удаляет все разделы реестра при удалении.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top