Google Suggestish テキスト ボックス (オートコンプリート)
-
09-06-2019 - |
質問
最後に入力された x 個のエントリを記憶するテキスト ボックスを開発する最善の方法は何でしょうか。これは C# で書かれたスタンドアロン アプリです。
解決
それを保存したいという事実を忘れていたので、それはセッションごとだけのものではありませんでした: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();
}
}
}
このコードはそのままで動作します。txtMain という名前の TextBox を使用して GUI を作成し、KeyDown、Closed、および Load イベントを TextBox と Main フォームに接続するだけです。
また、この例では、わかりやすくするために、文字列をコレクションに保存するトリガーとして Enter キーの押下を検出することを選択しただけであることに注意してください。あなたのニーズに応じて、おそらくもっと良い、またはより異なるイベントがあるでしょう。
また、コレクションの居住に使用されるモデルは、それほど「スマート」ではありません。コレクションが10の限界に達すると、単に最古の文字列を削除します。これは理想的ではない可能性がありますが、この例では機能します。おそらく、何らかの評価システムが必要になるでしょう (特にそれを本当に Google 風にしたい場合)
最後の注意点として、提案は実際にはコレクション内の順序で表示されます。何らかの理由で、別の方法で表示したい場合は、リストを好きなように並べ替えてください。
お役に立てば幸いです!
他のヒント
これは、特に「オートコンプリート」部分を表示するという点では、実際には非常に簡単です。最後の x 個のエントリを記憶するという点では、完了したエントリと見なす特定のイベントを決定し、そのエントリをリストに書き込むだけです。正確には AutoCompleteStringCollection です。
TextBox クラスには、必要となる次の 3 つのプロパティがあります。
- AutoCompleteカスタムソース
- オートコンプリートモード
- オートコンプリートソース
AutoCompleteMode を SuggestAppend に設定し、AutoCompleteSource を CustomSource に設定します。
その後、実行時に新しいエントリが作成されるたびに、AutoCompleteStringCollection の Add() メソッドを使用してそのエントリをリストに追加します (必要に応じて古いエントリを削除します)。実際には、すでに初期化されている限り、TextBox の AutoCompleteCustomSource プロパティに対してこの操作を直接実行できます。
これで、TextBox に入力するたびに、以前のエントリが提案されます :)
より完全な例については、この記事を参照してください。 http://www.c-sharpcorner.com/UploadFile/mahesh/AutoCompletion02012006113508AM/AutoCompletion.aspx
AutoComplete には、FileSystem や URL などのいくつかの組み込み機能もあります (ただし、IE に入力されたものだけを実行します...)
完了リストをレジストリに保存します。
私が使用するコードは以下です。次の 3 つの手順で再利用できます。
- このコード内の名前空間とクラス名を、使用するものに置き換えてください。
- フォームの FillFormFromRegistry() を呼び出します。 負荷 イベントを呼び出し、SaveFormToRegistry を呼び出します。 閉鎖 イベント。
- これをプロジェクトにコンパイルします。
アセンブリを 2 つの属性で修飾する必要があります。 [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;
}
}
}
一部の人々 状態を保存するためにレジストリを使用することを避ける, でも本当に簡単で便利だと思います。必要に応じて、アンインストール時にすべてのレジストリ キーを削除するインストーラーを非常に簡単に構築できます。