Google Suggestish текстовое поле (автозаполнение) - PullRequest
5 голосов
/ 04 сентября 2008

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

Ответы [ 3 ]

6 голосов
/ 04 сентября 2008

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

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

  • AutoCompleteCustomSource
  • AutoCompleteMode
  • AutoCompleteSource

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

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

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

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

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

3 голосов
/ 05 сентября 2008

@ Этан

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

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

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

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

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

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

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

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

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

1 голос
/ 18 сентября 2009

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...