wpf - How to thread a viewlist custom view binding so that the UI doesn't freeze -
wpf - How to thread a viewlist custom view binding so that the UI doesn't freeze -
i new wpf, though have tried read much can, newbie in need of wisdom wpf sages here.
i have viewlist custom view display tileview of linecharts. user selects item in separate listbox, sets datasource used in listview. problem ui freezes while listivew generating view. here how layout looks:
((sorry, new @ site can not post images, yet, here link: screenshot))
the datasource consist of class contains descriptive properties , list of list of datapoints (x,y). tileview takes list of list of datapoints , generates 1 line chart each listitem using list of datapoints draw line.
currently have datasource list holding 200 items , each item has 200 datapoints (x,y).
when select item in listbox of left, utilize selectionchanged event set itemssource property listview new dataset. problem ui freezes until charts generated.
i have been trying different approaches without success. tried set datasource asynchronous one:
dataseries="{binding isasync=true, path=data}"
this helps tinny tinny bit releasing ui before view rendered. means after changing datasource freeze ui moment, release showing view 200 empty charts , after bit refreshing view populated charts.
i tried set binding within thread this:
private void list_selectionchanged(object sender, selectionchangedeventargs e) { //find selected itemsource string runname = (string)experimentlist.selecteditem; experimentalrun selectedrun = _experimentruns.find(item => item.name == runname); //bind datasource thru new thread thread newthread = new thread(lstproductsnewsource); newthread.start(selectedrun); } private void lstproductsnewsource(object selectedrun) { this.dispatcher.begininvoke(dispatcherpriority.background, (threadstart)delegate() { lstproducts.itemssource = ((experimentalrun)selectedrun).rungraphdata; }); }
lstproducts name of listview has tileview of charts. rungraphdata porperty points @ list of list of datapoints.
i hoping release ui did not work. in case there no time consuming process before databind, info readily available in memory, time consuming creation of viewitems , databinding of them, not rendering.
as additional details specify charts generated usercontrol , here how xml of tile view looks:
<local:tileview x:key="imageview"> <local:tileview.itemtemplate> <datatemplate> <stackpanel width="150" verticalalignment="top"> <local:graph dataseries="{binding isasync=true, path=data}"/> <textblock textwrapping="wrap" horizontalalignment="center" text="{binding >isasync=true, path=containername}" ></textblock> </stackpanel> </datatemplate> </local:tileview.itemtemplate> </local:tileview>
the graph usercontrol typical chart command receives dataset , binds it.
i seek advice on how manage maintain ui responsive while listview binding. can help me?
edit:
i forgot mention tried utilize virtualization on listview without noticeable difference:
<listview name="lstproducts" view="{staticresource gridview}" >virtualizingstackpanel.isvirtualizing="true" > </listview>
i expecting load current window worth of items , when scroll downwards start loading new items, when utilize isvirtualizing property set true seems load @ once, same delay , if scroll downwards there no delay giving me impression items present.
edit 2: found question in site reply provided type of solution: link
following advice provided in after mentioned thread, modified previous threading effort trying encapsulate entire databinding event single background thread pumping info 1 graph @ time, taking advantage of observablecollection auto-updating properties. create empty datasource , assign it, add together elements datasource 1 1 creating thread background priority every time add together point. looks this:
private void experimentlist_selectionchanged(object sender, selectionchangedeventargs e) { //find selected itemsource string runname = (string)experimentlist.selecteditem; experimentalrun selectedrun = _experimentruns.find(item => item.name == runname); //create , empty datasource filled 1 item @ time experimentalrun pumprun = new experimentalrun(((experimentalrun)selectedrun).name); lstproducts.itemssource = pumprun.rungraphdata; //fill emtpy source using new thread per item added foreach (var item in selectedrun.rungraphdata) { pumpexperimentalrundata pump = new pumpexperimentalrundata(pumprun, item); thread newthread = new thread(pumpadd); newthread.start(pump); } } private void pumpadd(object pumpexperimentalrundata) { this.dispatcher.begininvoke(dispatcherpriority.background, (threadstart)delegate() { ((pumpexperimentalrundata)pumpexperimentalrundata).pumprun.rungraphdata.add(((pumpexperimentalrundata)pumpexperimentalrundata).item); }); }
this approach seems work, worried creates many threads (200) every time alter datasource ... have read far recommends utilize few threads, , doesn't qualify few think. differently, out of ideas.
can see error of ways or point out improve approach?
you have utilize virtualizingstackpanel.
<listview.itemspanel> <itemspaneltemplate> <virtualizingstackpanel/> </itemspaneltemplate> </listview.itemspanel>
wpf multithreading data-binding listview asynchronous
Comments
Post a Comment