wpf - Strange out of order behavior for TreeView and compound data -
the follow code loads hierarchical collection of compoundobjects of strings. unfortunately inserts strings @ top of tree instead of @ bottom(which behavior i've seen.
i've tried change order of enumerators, notifiers, etc , produce same results. i've pre-load list looks normal(using same code in thread).
any ideas whats going on?
compoundobject.cs
using system; using system.collections.generic; using system.collections.objectmodel; using system.collections.specialized; using system.linq; using system.text; namespace complextreeviewlazyloadingtest { public class compoundobject : ienumerable<object>, inotifycollectionchanged { public string name { get; set; } public observablecollection<compoundobject> objects { get; private set; } public observablecollection<string> items { get; private set; } void onchanged(object sender, notifycollectionchangedeventargs e) { if (collectionchanged != null) app.current.dispatcher.invoke((action<object, notifycollectionchangedeventargs>)((senderr, ee) => { collectionchanged(senderr, ee); }), sender, e); } public compoundobject(string name) { name = name; items = new observablecollection<string>(); objects = new observablecollection<compoundobject>(); items.collectionchanged += new notifycollectionchangedeventhandler(onchanged); objects.collectionchanged += new notifycollectionchangedeventhandler(onchanged); } public ienumerator<object> getenumerator() { if (objects != null) foreach(var in objects) yield return a; if (items != null) foreach (var in items) yield return a; yield break; } system.collections.ienumerator system.collections.ienumerable.getenumerator() { return getenumerator(); } public event notifycollectionchangedeventhandler collectionchanged; } } mainwindow.xaml.cs
using system; using system.collections.generic; using system.linq; using system.text; using system.windows; using system.windows.controls; using system.windows.data; using system.windows.documents; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using system.windows.navigation; using system.windows.shapes; using system.threading; namespace complextreeviewlazyloadingtest { public partial class mainwindow : window { compoundobject c = new compoundobject("root"); public mainwindow() { initializecomponent(); treeview.datacontext = c; treeview.itemssource = c; threadpool.queueuserworkitem(new waitcallback(update)); } void update(object data) { (int = 0; < 10; i++) { application.current.dispatcher.invoke((action<compoundobject>)((cc) => { c.objects.add(cc); }), new compoundobject("object " + i)); (int j = 0; j < 5; j++) { thread.sleep(100); application.current.dispatcher.invoke((action<compoundobject>)((cc) => { c.objects[i].objects.add(cc); }), new compoundobject("subobject " + j)); } } (int = 0; < 8; i++) { thread.sleep(250); application.current.dispatcher.invoke((action<string>)((ii) => { c.items.add("item " + ii); }), i.tostring()); } } } // mainwindow public class dts : datatemplateselector { public override datatemplate selecttemplate(object item, dependencyobject container) { frameworkelement element = container frameworkelement; if (element != null && item != null) { if (item compoundobject) { return element.findresource("compoundtemplate") datatemplate; } if (item int) { return element.findresource("defaulttemplate") datatemplate; } } return null; } } } mainwindow.xaml
<window x:class="complextreeviewlazyloadingtest.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:complextreeviewlazyloadingtest;assembly=" title="mainwindow" height="350" width="525"> <window.resources> <local:dts x:key="dts"/> <hierarchicaldatatemplate x:key="compoundtemplate" itemssource="{binding path=.}"> <textblock text="{binding name}" /> </hierarchicaldatatemplate> <hierarchicaldatatemplate x:key="defaulttemplate" itemssource="{binding path=.}"> <textblock text="{binding path=.}" background="aqua" /> </hierarchicaldatatemplate> </window.resources> <grid> <treeview name="treeview" itemtemplateselector="{staticresource dts}"/> </grid> </window>
because you're combining 2 collections , subscribing collectionchanged directly, change notifications sub-lists instead of 'combined' list. means you'll notification 'string added @ 0' when want added @ end of list. in order make work, you'll need subscribe collectionchanged each sub-collection , implement own collectionchanged callback (to add first collection's count indices reported when adding/removing strings.)
Comments
Post a Comment