mvvm - Loading the list of items asynchronously in a WPF listbox using Dispatcher -


i working on creating wpf solution uses mvvm pattern load searched items in search control asynchronously. search control wpf usercontrol created textbox enter search text , search button , hidden listbox visible when loads searched items list in it. user control in turn embedded wpf view has treeview of items. view has view model in logic load searched items of tree view loaded in search control. while, has been happening synchronously without use of dispatcher call. but, after change request, make happen asynchronously in different thread using dispatcher.

could please let me know how handle of dispatcher of search control in view model class call begininvoke on using mvvm pattern wherein view model not aware of view? clue highly appreciated.

public observablecollection<details> catalogsearchresults { get; private set; }  private void executesearchcommand(object parameter)     {         catalogsearchresults.clear();         if (string.isnullorempty(parameter.tostring())) return;          searchtext = (string)parameter;         searchtext.trim();          setsearchresults();     }  private void setsearchresults()      {      backgroundworker bw = new backgroundworker();       bw.dowork += loadresults;      bw.runworkercompleted += this.loadresultscompleted;       bw.runworkerasync();      }   private void loadresults(object sender, doworkeventargs args)  {          issearchinprogress = true;         foreach (var category in _rootcategory.recurse(findchildren))         {             if (category.commentdetails != null)             {                 //limitation - there no direct way add range observable collection.                 //using linq query result in 2 loops rather one.                 foreach (var node in category.details)                 {                     if (node.name.indexof(searchtext, stringcomparison.currentcultureignorecase) >= 0                         || node.precannedtext.indexof(searchtext,            stringcomparison.currentcultureignorecase) >= 0)                     {                         application.current.dispatcher.begininvoke(dispatcherpriority.normal,                             (threadstart)delegate { catalogsearchresults.add(node); });                            thread.sleep(100);                      }                 }             }         }         issearchinprogress = false; } 

in xaml, biding items property of search control catalogsearchresults:

 <ctrl:searchcontrol x:name="ctrl" grid.rowspan="2" horizontalalignment="stretch" verticalalignment="top"   tooltip="search" command="{binding searchcommand}"   grid.columnspan="3"                                                                                          commandparameter="{binding text, relativesource={relativesource self}}"                                                                                             items ="{binding catalogsearchresults}" > </ctrl:searchcontrol> 

thanks, sowmya

here's simple implementation showing how use backgroundworker update objects on ui thread while dowork running - in example, there's listbox in ui that's bound filtereditems, , itemssource property of usercontrol of type ienumerable:

    filtereditems = new observablecollection<object>();     backgroundworker bw = new backgroundworker();     bw.workerreportsprogress = true;     bw.dowork += bw_dowork;     bw.runworkercompleted += bw_runworkercompleted;     bw.progresschanged += bw_progresschanged;     bw.runworkerasync();      private void bw_dowork(object sender, doworkeventargs e)     {         backgroundworker bw = (backgroundworker) sender;         var result = itemssource            .oftype<object>()            .where(x => x.tostring().contains(_filtertext));         foreach (object o in result)         {             // pass each object found bw_progresschanged in userstate argument.             // updates ui each item found.             bw.reportprogress(0, o);         }     }      void bw_progresschanged(object sender, progresschangedeventargs e)     {         // filtereditems bound ui, it's ok update here because         // progresschanged event handler runs on ui thread.         filtereditems.add(e.userstate);     }      private void bw_runworkercompleted(object sender, runworkercompletedeventargs e)     {         if (e.error != null)         {             messagebox.show(e.error.message);         }     } 

note calling reportprogress every time find item pretty inefficient, you're marshalling every item found across threads invoke call. depending on how long filtering taking, may better accumulate bunch of results , pass list<object> bw_reportprogress instead of single object.


Comments

Popular posts from this blog

ASP.NET/SQL find the element ID and update database -

jquery - appear modal windows bottom -

c++ - Compiling static TagLib 1.6.3 libraries for Windows -