Текстовое поле Google Suggestish (автозаполнение)
-
09-06-2019 - |
Вопрос
Каков был бы наилучший способ создать текстовое поле, которое запоминает последнее 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 ...)
Я храню список завершения в реестре.
Код, который я использую, приведен ниже.Это многоразовый процесс, состоящий из трех этапов:
- замените пространство имен и имя_класса в этом коде на все, что вы используете.
- Вызовите FillFormFromRegistry() в форме Нагрузка событие, и вызовите SaveFormToRegistry на Закрытие событие.
- скомпилируйте это в свой проект.
Вам нужно украсить сборку двумя атрибутами: [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("¡", "¡");
}
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;
}
}
}
Некоторые люди избегайте использования Реестра для хранения состояния, но я нахожу, что это действительно легко и удобно.Если хотите, Вы можете очень легко создать программу установки, которая удаляет все разделы реестра при удалении.