wpf - Best way to "group" items "virtually"? -
i'm working on custom items based wpf control. "normal" layout, think vertical stackpanel, xaml like:
<mycontrol> <item1 /> <item2 /> <item3 /> </mycontrol>
in case, simple, 3 item containers created , good. control like:
[item1] [item2] [item3]
use case #2 is, need support horizontal "grouping"... ideally xaml like:
<mycontrol> <item1 /> <stackpanel orientation=horizontal> <item2a /> <item2b /> <item2c /> </stackpanel> <item3 /> </mycontrol>
and in case, render as:
[item1] [item2a] [item2b] [item2c] [item3]
so, i'm going 5 item containers being generated. i've worked out custom layout panel , part works.
the issue is, if use stackpanel, i'll 3 item containers makes sense, duh, breaks keyboard interface of control. hacky intercept keyboard , mouse stuff , "re-route" in case, seems hacky , difficult work in generic way.
is there obscure built wpf deal this? "sub items" getting generated thier own containers?
the way i'm heading like:
<item1 /> <item2a isgrouped=true /> <item2b isgrouped=true /> <item2c isgrouped=true /> <item3 />
so, when hit first isgrouped=true, it'll start grouping until hits false, i'm not crazy either because i'll have make isgrouped 3 state enum can have 1 group right below group. also, hierarchy not clear in xaml.
any suggestions?
i able more or less going using hierarchicaldatatemplate within treeview uses custom treeviewitem
control template. control template, copied example template , made few modifications. of containers in right place, keyboard navigation doesn't work on nested items (because treeview
not expecting layout guess). here came with:
<treeview itemssource="{binding items}"> <treeview.resources> <color x:key="selectedbackgroundcolor">#ffc5cbf9</color> <color x:key="selectedunfocusedcolor">#ffdddddd</color> <style targettype="{x:type treeviewitem}"> <setter property="itemspanel"> <setter.value> <itemspaneltemplate> <stackpanel orientation="horizontal" /> </itemspaneltemplate> </setter.value> </setter> <setter property="isexpanded" value="true" /> <setter property="template"> <setter.value> <!-- template came example template , has few modifications. example at: https://msdn.microsoft.com/en-us/library/ms752048.aspx --> <controltemplate targettype="{x:type treeviewitem}"> <grid> <!-- changed grid configuration --> <grid.columndefinitions> <columndefinition width="auto" /> <columndefinition width="*" /> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="auto" /> </grid.rowdefinitions> <!-- entire visualstategroups section direct copy+paste example template --> <visualstatemanager.visualstategroups> <visualstategroup x:name="selectionstates"> <visualstate x:name="selected"> <storyboard> <coloranimationusingkeyframes storyboard.targetname="bd" storyboard.targetproperty="(panel.background).(solidcolorbrush.color)"> <easingcolorkeyframe keytime="0" value="{staticresource selectedbackgroundcolor}" /> </coloranimationusingkeyframes> </storyboard> </visualstate> <visualstate x:name="unselected" /> <visualstate x:name="selectedinactive"> <storyboard> <coloranimationusingkeyframes storyboard.targetname="bd" storyboard.targetproperty="(panel.background).(solidcolorbrush.color)"> <easingcolorkeyframe keytime="0" value="{staticresource selectedunfocusedcolor}" /> </coloranimationusingkeyframes> </storyboard> </visualstate> </visualstategroup> <visualstategroup x:name="expansionstates"> <visualstate x:name="expanded"> <storyboard> <objectanimationusingkeyframes storyboard.targetproperty="(uielement.visibility)" storyboard.targetname="itemshost"> <discreteobjectkeyframe keytime="0" value="{x:static visibility.visible}" /> </objectanimationusingkeyframes> </storyboard> </visualstate> <visualstate x:name="collapsed" /> </visualstategroup> </visualstatemanager.visualstategroups> <!-- removed togglebutton --> <!-- tweaked placement of items in grid --> <border x:name="bd" background="{templatebinding background}" borderbrush="{templatebinding borderbrush}" borderthickness="{templatebinding borderthickness}" padding="{templatebinding padding}"> <contentpresenter x:name="part_header" contentsource="header" horizontalalignment="{templatebinding horizontalcontentalignment}"/> </border> <itemspresenter x:name="itemshost" grid.column="1" /> </grid> <controltemplate.triggers> <!-- removed isexpanded trigger --> <multitrigger> <multitrigger.conditions> <condition property="hasheader" value="false" /> <condition property="width" value="auto" /> </multitrigger.conditions> <setter targetname="part_header" property="minwidth" value="75" /> </multitrigger> <multitrigger> <multitrigger.conditions> <condition property="hasheader" value="false" /> <condition property="height" value="auto" /> </multitrigger.conditions> <setter targetname="part_header" property="minheight" value="19" /> </multitrigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> </treeview.resources> <treeview.itemtemplate> <hierarchicaldatatemplate datatype="{x:type local:myitem}" itemssource="{binding children}"> <textblock text="{binding name}" /> </hierarchicaldatatemplate> </treeview.itemtemplate> </treeview>
for reference, itemssource
property bound collection containing items this:
internal class myitem { public string name { get; private set; } public list<myitem> children { get; private set; } public myitem(string name = null) { name = name; children = new list<myitem>(); } }
this done without creating custom control, gives idea of can do. combination of heirarchicaldatatemplate
, specialized container type (in case treeviewitem
custom control template) key way did it.
here data tested , result:
public ienumerable<myitem> items { get; private set; } ... var items = new myitem[] { new myitem("[first]"), new myitem(), new myitem("[third]") }; items[1].children.add(new myitem("[second_0]")); items[1].children.add(new myitem("[second_1]")); items[1].children.add(new myitem("[second_2]")); items = items;
i sure visualization improved. threw in under 10 minutes.
Comments
Post a Comment