c# - How to overlay items in StackPanel or ListView? -
i making card game , want display cards in player's hand half-covered each other. how can using listview or stackpanel? here example how display player hand.
<grid background="green" > <image x:name="one" width="100" height="100" margin="10,10,250,210"/> <image x:name="two" width="100" height="100" margin="10,10,210,210"/> </grid>
update
i set margins listview's itemcontainerstyle , worked, have problem. width of listview items doesn't fit image , there spacing. how remove that. see image below xaml code.
<listview grid.row="0" grid.column="0"> <listview.itemspanel> <itemspaneltemplate> <stackpanel orientation="horizontal" /> </itemspaneltemplate> </listview.itemspanel> <listview.itemcontainerstyle> <style targettype="listviewitem"> <setter property="margin" value="0, 0, -80, 0"></setter> <setter property="height" value="100"></setter> <setter property="width" value="100"></setter> </style> </listview.itemcontainerstyle> <image x:name="one" maxwidth="100" height="100" /> <image x:name="two" maxwidth="100" height="100" /> </listview>
i use canvas in list, , draw card canvas, because things drawn in canvas not clipped, , instead managed through canvas zindex etc.
size canvas based on desired spacing, , oversize contents. i'd recommend binding items-source when using listboxes , using templates.
btw i'm defining cards using solidcolorbrushes can draw rectangles, replace image source. i've defined source in resources, in reality bound observablecollection (say, playerscurrenthand or something):
<usercontrol.resources> <x:array type="{x:type solidcolorbrush}" x:key="cards"> <solidcolorbrush color="blue"/> <solidcolorbrush color="red"/> <solidcolorbrush color="white"/> <solidcolorbrush color="white"/> <solidcolorbrush color="white"/> <solidcolorbrush color="white"/> </x:array> </usercontrol.resources>
now, presume using listbox because want support selection? if so, way wpf highlights list box items mess overlap, need replace it. if don't want selection, use itemscontrol , can skip selection stuff.
here's our basic listbox:
<listview itemssource="{staticresource cards}" horizontalalignment="center" verticalalignment="center" margin="112,98,-325,-25" width="513" height="227"> <listview.itemspanel> <itemspaneltemplate> <stackpanel orientation="horizontal" isitemshost="true" verticalalignment="top"/> </itemspaneltemplate> </listview.itemspanel> <listview.itemtemplate> <datatemplate> <border borderbrush="black" borderthickness="1"> <rectangle fill="{binding}" width="60" height="100"/> </border> </datatemplate> </listview.itemtemplate> </listview>
which gives this:
now, want have list items drawn in canvas, let's define our itemcontainerstyle:
<listview.itemcontainerstyle> <style targettype="listviewitem"> <setter property="template"> <setter.value> <controltemplate targettype="{x:type listviewitem}"> <stackpanel> <canvas width="15" height="100"> <contentpresenter /> </canvas> </stackpanel> </controltemplate> </setter.value> </setter> </style> </listview.itemcontainerstyle>
see how we've set canvas width 15? defines spacing of our cards. canvases stacked @ intervals of 15. however, rectangles drawing in our datetemplate width 60, these spill off right.
we've overridden messy standard selection , highlighting styles. no don't know what's highlighted , selected, let's add functionality in. can add things shadows etc:
<controltemplate targettype="{x:type listviewitem}"> <stackpanel> <canvas width="15" height="100"> <rectangle x:name="highlight" width="60" height="5" canvas.top="105"/> <rectangle fill="#50000000" width="60" height="100" margin="5,0,-5,0"/> <contentpresenter /> </canvas> </stackpanel> <controltemplate.triggers> <trigger property="isselected" value="true"> <setter targetname="highlight" property="fill" value="yellow"/> </trigger> <trigger property="ismouseover" value="true"> <setter property="panel.zindex" value="99"/> </trigger> </controltemplate.triggers> </controltemplate>
so have this:
note, gif didn't render selection right. width issue going tricky fix without code behind think. 1 option make ivalueconverter calculates width given list of cards, , binding listview's width property.
edit
found way around size issue! padding! of course. however, found scroll viewer clips canvas contains (which makes sense if think it) leaves our effort hidden:
so have overwrite scroll viewer functionality setting controltemplate manually:
<listbox.template> <controltemplate> <border padding="5,25,55,15" borderbrush="gray" borderthickness="1"> <itemspresenter /> </border> </controltemplate> </listbox.template>
so padding accounts last card sticking out 50.
total code, more visual tweaks:
<listview itemssource="{staticresource cards}" horizontalalignment="center" verticalalignment="center" margin="20" borderbrush="black"> <listbox.template> <controltemplate> <border padding="5,25,55,15" borderbrush="gray" borderthickness="1"> <itemspresenter /> </border> </controltemplate> </listbox.template> <listview.itemspanel> <itemspaneltemplate> <stackpanel orientation="horizontal" isitemshost="true" cliptobounds="false" /> </itemspaneltemplate> </listview.itemspanel> <listview.itemcontainerstyle> <style targettype="listviewitem"> <setter property="template"> <setter.value> <controltemplate targettype="{x:type listviewitem}"> <stackpanel> <canvas width="15" height="100"> <rectangle x:name="highlight" width="60" height="5" canvas.top="105"/> <contentpresenter x:name="cardpresenter"/> </canvas> </stackpanel> <controltemplate.triggers> <trigger property="ismouseover" value="true"> <setter property="panel.zindex" value="99"/> <setter targetname="cardpresenter" property="canvas.top" value="-5"/> </trigger> <trigger property="isselected" value="true"> <setter targetname="highlight" property="fill" value="yellow"/> <setter targetname="cardpresenter" property="canvas.top" value="-20"/> </trigger> </controltemplate.triggers> </controltemplate> </setter.value> </setter> </style> </listview.itemcontainerstyle> <listview.itemtemplate> <datatemplate> <grid> <border background="#60000000" borderthickness="0" cornerradius="5" height="100" margin="5,0,-5,0"/> <border borderbrush="black" borderthickness="1" cornerradius="5" background="{binding}" width="60" height="100"/> </grid> </datatemplate> </listview.itemtemplate> </listview>
it's pretty flexible, easy add "sticking out" functionality. animations next big step.
edit 2
i'm playing now. i'm not sure "jump front" functionality, better if peeked out. also, fanning them out (using multi-binding):
using following template:
<controltemplate targettype="{x:type listviewitem}"> <stackpanel> <canvas width="15" height="100"> <rectangle x:name="highlight" width="60" height="5" canvas.top="105"/> <contentpresenter x:name="cardpresenter"> <contentpresenter.rendertransform> <transformgroup> <translatetransform x:name="translatetransformhighlight"/> <rotatetransform x:name="rotatetransformhighlight" centery="100"/> <translatetransform x:name="translatetransformselect"/> </transformgroup> </contentpresenter.rendertransform> </contentpresenter> </canvas> </stackpanel> <controltemplate.triggers> <trigger property="ismouseover" value="true" > <trigger.enteractions> <beginstoryboard> <storyboard> <doubleanimation storyboard.targetname="translatetransformhighlight" duration="0:0:0.200" to="-5" storyboard.targetproperty="y" /> <doubleanimation storyboard.targetname="rotatetransformhighlight" duration="0:0:0.200" to="-5" storyboard.targetproperty="angle" /> </storyboard> </beginstoryboard> </trigger.enteractions> <trigger.exitactions> <beginstoryboard> <storyboard> <doubleanimation storyboard.targetname="translatetransformhighlight" duration="0:0:0.200" to="0" storyboard.targetproperty="y" /> <doubleanimation storyboard.targetname="rotatetransformhighlight" duration="0:0:0.200" to="0" storyboard.targetproperty="angle" /> </storyboard> </beginstoryboard> </trigger.exitactions> </trigger> <trigger property="isselected" value="true"> <setter targetname="highlight" property="fill" value="yellow"/> <trigger.enteractions> <beginstoryboard> <storyboard> <doubleanimation storyboard.targetname="translatetransformselect" duration="0:0:0.200" to="-15" storyboard.targetproperty="y" /> </storyboard> </beginstoryboard> </trigger.enteractions> <trigger.exitactions> <beginstoryboard> <storyboard> <doubleanimation storyboard.targetname="translatetransformselect" duration="0:0:0.200" to="0" storyboard.targetproperty="y" /> </storyboard> </beginstoryboard> </trigger.exitactions> </trigger> </controltemplate.triggers> </controltemplate>
Comments
Post a Comment