.NET Core 3.0 is the latest version of .NET Core and now supports WinForms and WPF. This sample shows how you can perform fill data to Autocomplete TextBox in another thread without slowing down the main UI (User Interface). With this sample, you can create a better user experience for the end-user.
TextBox Autocomplete
Autocomplete helps the user to search/type from a known list. In my application, I built a list to Autocomplete with > 10.000 items and is very fast even on slow computers.
Autocomplete is an old feature, but this post will demonstrate how to perform this to load data quickly in NET Core 3.0.
When you fill a Collection, if you have a huge suggestion list, this will make the UI (User Interface) freeze. But if you process it in another thread the UI will not have any issues.
More technical information is
here.
How it works
Like the other POST that uses a delegate,
here, we use another thread to load data and delegate to bind the Autocomplete Collection in the current UI thread.
- using System;
- using System.Data.SqlClient;
- using System.Drawing;
- using System.Windows.Forms;
-
- namespace TextBoxWithAutoComplete
- {
-
-
-
-
- public partial class Form1 : Form
- {
-
- private TextBox textBox1;
- public Form1()
- {
- InitializeComponent();
-
- textBox1 = new TextBox
- {
- Location = new Point(0, 0),
- Size = new Size(100, 32),
- Visible = true,
- TabIndex = 0
- };
- Controls.Add(textBox1);
-
- Load += Form1_Load;
- }
-
- public void Form1_Load(object sender, EventArgs e)
- {
- Show();
-
- LoadData();
- }
-
- private SqlConnection GetConnection()
- {
-
- var oCnn = new SqlConnection
- {
- ConnectionString = "YOUR_CONNECTION_STRING"
- };
- oCnn.Open();
- return oCnn;
- }
-
-
- #region TreadSafeLoading
- private delegate void UpdateUIDelegate(AutoCompleteStringCollection myCollection);
-
-
-
-
- private void LoadData()
- =>
- new System.Threading.Thread(() => OutOfThreadProcess()).Start();
-
-
-
-
-
- private void OutOfThreadProcess()
- {
-
- var myCollection = new AutoCompleteStringCollection();
- using var oCnn = GetConnection();
-
-
- var cmd = new SqlCommand($"Select [FirstName] + ' ' + [LastName] as [contactName] From [AdventureWorks].[Person].[Contact] Order By [FirstName], [LastName]", oCnn);
-
-
- using var reader = cmd.ExecuteReader();
- while (reader.Read())
- myCollection.Add(reader.GetString(0));
-
-
- _ = Invoke(new UpdateUIDelegate(UpdateUIInvoke), myCollection);
- }
-
-
-
-
-
- private void UpdateUIInvoke(AutoCompleteStringCollection myCollection)
- {
-
- textBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
- textBox1.AutoCompleteSource = AutoCompleteSource.CustomSource;
- textBox1.AutoCompleteCustomSource = myCollection;
- #if (IS_TELERIK_RadTextBoxControl)
-
-
- if (ParentForm != null)
- ParentForm.FormClosing += new FormClosingEventHandler(UIFormClosing);
- #endif
- }
- #if (IS_TELERIK_RadTextBoxControl)
- private void UIFormClosing(object sender, FormClosingEventArgs e) => textBox1.AutoCompleteCustomSource = null;
-
- #endif
- #endregion
-
- }
- }
Observation
When you use this technique you may receive errors if you run the new thread without firing the Show() method from the form, this occurs because the current window(form) hasn't initialized.
Conclusion
I designed this technique when I upgraded to .NET Core 3 and developed a fix for the FileSystemWatcher event that fires in a new thread, so I took the same idea to make Autocomplete load collection work in a new thread.
I hope you can bring a better experience to your end-users.
Happy coding.