开发一个文本框以记住上次输入的最后x个条目的最佳方法是什么。这是一个用C#编写的独立应用程序。
这实际上是相当容易的,特别是在显示其中的"自动完成"部分方面。就记住最后的x个条目而言,您只需要确定一个或多个特定事件(将其视为已完成的条目)并将该条目写到列表中即可... AutoCompleteStringCollection将精确。
TextBox类具有您需要的以下3个属性:
-
AutoCompleteCustomSource
-
自动完成模式
-
自动完成源
将AutoCompleteMode设置为RecommendationAppend,将AutoCompleteSource设置为CustomSource。
然后在运行时,每次创建新条目时,请使用AutoCompleteStringCollection的Add()方法将该条目添加到列表中(并根据需要弹出所有旧条目)。实际上,只要您已经初始化了TextBox,就可以直接在TextBox的AutoCompleteCustomSource属性上直接执行此操作。
现在,每次您在文本框中键入内容时,都会提示以前的输入内容:)
有关更多完整示例,请参见本文:http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx
AutoComplete还具有一些内置功能,例如FileSystem和URL(尽管它只处理键入IE的内容...)
@Ethan
我忘记了您要保存它的事实,所以这不是每个会话唯一的事情:P但是,是的,您是完全正确的。
这很容易做到,特别是因为它只是基本的字符串,只需将AutoCompleteCustomSource的内容从TextBox写到文本文件中的不同行上即可。
我花了几分钟时间,所以我写了一个完整的代码示例……我以前一直会尝试显示代码,但是没有时间。无论如何,这就是全部(减去设计者代码)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| 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的文本框创建GUI,并将KeyDown,Closed和Load事件挂接到TextBox和Main窗体。
还要注意,对于本示例来说,为了简单起见,我只是选择检测按下Enter键作为触发,以将字符串保存到集合中。根据您的需求,可能会有更多/不同的事件会更好。
此外,用于填充集合的模型也不是很"智能"。当集合达到10的限制时,它只是删除最旧的字符串。这可能不是理想的方法,但可以用于示例。您可能需要某种评级系统(特别是如果您确实希望它是Google式的)
最后的注释,建议实际上将按照它们在集合中的顺序显示。如果出于某些原因您希望它们以不同的方式显示,则可以按自己喜欢的方式对列表进行排序。
希望有帮助!
我将完成列表存储在注册表中。
我使用的代码如下。它可重复使用,分三个步骤:
用您使用的任何内容替换此代码中的名称空间和类名。
在Form的Load事件上调用FillFormFromRegistry(),在Closing事件上调用SaveFormToRegistry。
将其编译到您的项目中。
您需要用两个属性装饰装配件:[assembly: AssemblyProduct("...")]和[assembly: AssemblyCompany("...")]。 (这些属性通常是在Visual Studio中创建的项目中自动设置的,因此我不认为这是一个步骤。)
以这种方式管理状态是完全自动的,并且对用户透明。
您可以使用相同的模式为WPF或WinForms应用程序存储任何状态。像文本框,复选框,下拉菜单的状态。此外,您还可以存储/恢复窗口的大小-非常方便-下次用户运行该应用程序时,它会在与关闭窗口时相同的位置以相同的大小打开。您可以存储应用程序已运行的次数。很多可能性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| 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;
}
}
} |
有些人回避使用注册表来存储状态,但是我发现它确实非常容易和方便。如果愿意,您可以轻松地构建一个安装程序,以在卸载时删除所有注册表项。