c# - what is the best way of providing instant search functionality as a user types in a textbox -
i want user search employee name or employee number. have provided textbox. user types in textbox, handle _textchanged event , update datagridview list of employees employee name or employee number contains text user entering in textbox.
the problem having slows typing , the datagridview update because every time text changes in textbox, search query hits database. makes form how un responsive.
does 1 know of better approach?
- simple: delay querying db half second or second ensure user has stopped typing remembering last time text has changed.
- better in long term: if db query takes long time (more second) can outsource querying db thread (task or backgroundworker). can fill datagrid in own task if it's data drawing takes long. able implement canceling mechanism , have main gui elements remain responsive.
i thought in democode below:
using system; using system.collections.generic; using system.threading; using system.threading.tasks; using system.windows.forms; namespace windowsformsapplication19 { public partial class form1 : form { cancellationtokensource tokensource = new cancellationtokensource(); public form1() { initializecomponent(); } private void textbox1_textchanged(object sender, eventargs e) { // cancel old query , datagrid update tokensource.cancel(); tokensource = new cancellationtokensource(); var token = tokensource.token; task.factory.startnew((s) => { var q = task.factory.startnew<ienumerable<demodata>>(() => longlastingdataquery(textbox1.text, token), token); if (!token.iscancellationrequested) task.factory.startnew(() => binddata(q.result)); }, token); } private ienumerable<demodata> longlastingdataquery(string search, cancellationtoken token) { list<demodata> l = new list<demodata>(); (int = 0; < 10000 * search.length; i++) { if (token.iscancellationrequested) return l; l.add(new demodata { id = i, text = search + i, text1 = search + + i, text2 = search + + + i, text3 = search + + + + }); } thread.sleep(1000); return l; } private void binddata(ienumerable<demodata> enumerable) { if (datagridview1.invokerequired) datagridview1.invoke(new methodinvoker(() => binddata(enumerable))); else { demodatabindingsource.datasource = null; demodatabindingsource.datasource = enumerable; } } public class demodata { public string text { get; set; } public string text1 { get; set; } public string text2 { get; set; } public string text3 { get; set; } public int id { get; set; } } } }