c# - How could I animate one stack panel item at a time? -
say have stackpanel few items in it. when load view, want apply animation them. want each item animate in sequence, 1 after other. how go doing this? in particular, there clean way in mvvm framework?
edit - should mention items databound stackpanel through itemscontrol, might make things substantially more difficult. looks this
<itemscontrol x:name="items"> <itemscontrol.itemspanel> <itemspaneltemplate> <stackpanel /> </itemspaneltemplate> </itemscontrol.itemspanel> <itemscontrol.itemtemplate> <datatemplate> <button content="{binding buttonname}"/> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol> some ui code omitted clarity.
copy/paste/compile/run : i'd throw explanation many topics cover. sample shows how multitrigger, animate, load items in background without freezing ui , use of propertychanged notify ui. enjoy.
here's xaml
<window x:class="wpfapplication1.mainwindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525" x:name="wnd"> <window.resources> <booleantovisibilityconverter x:key="booltovisibility" /> </window.resources> <itemscontrol x:name="items" itemssource="{binding testitems, elementname=wnd}" loaded="items_loaded"> <itemscontrol.itemtemplate> <datatemplate> <button x:name="item" content="{binding displaystring}" margin="5"> <button.style> <style targettype="{x:type button}"> <setter property="opacity" value="0"/> <setter property="visibility" value="{binding path=isvisible, converter={staticresource booltovisibility}}"/> <style.triggers> <multidatatrigger> <multidatatrigger.conditions> <condition binding="{binding isloading}" value="true"/> <condition binding="{binding isvisible}" value="true"/> </multidatatrigger.conditions> <multidatatrigger.enteractions> <beginstoryboard> <storyboard > <doubleanimation storyboard.targetproperty="opacity" from="0" to="1" duration="0:0:1.5" accelerationratio="0.3"/> </storyboard> </beginstoryboard> </multidatatrigger.enteractions> </multidatatrigger> </style.triggers> </style> </button.style> </button> </datatemplate> </itemscontrol.itemtemplate> </itemscontrol> then here's code behind it:
using system.collections.generic; using system.componentmodel; using system.globalization; using system.threading; using system.threading.tasks; using system.windows; namespace wpfapplication1 { public partial class mainwindow : window { private list<testitem> _items; public list<testitem> testitems { { if(_items == null) { _items = new list<testitem>(); for(int = 0; < 10; i++) _items.add(new testitem{ displaystring = i.tostring(cultureinfo.invariantculture), isvisible = true}); } return _items; } } public mainwindow() { initializecomponent(); } private void items_loaded(object sender, routedeventargs e) { /*in background not freeze ui thread*/ task.factory .startnew(() => { foreach (var item in testitems) { item.isloading = true; item.isvisible = true; /*using sleep quick , dirty slow down loading , show animation (otherwise it's no-no )*/ thread.sleep(500); } } ); } } public class testitem : inotifypropertychanged { private string _displaystring; private bool _isvisible; private bool _isloading; public string displaystring { { return _displaystring; } set { if (_displaystring == value) return; _displaystring = value; raisepropertychanged("displaystring"); } } public bool isvisible { { return _isvisible; } set { if (_isvisible == value) return; _isvisible = value; raisepropertychanged("isvisible"); } } public bool isloading { { return _isloading; } set { if (_isloading == value) return; _isloading = value; raisepropertychanged("isloading"); } } public event propertychangedeventhandler propertychanged; private void raisepropertychanged(string propertyname) { if(propertychanged != null) propertychanged(this, new propertychangedeventargs(propertyname)); } } }
Comments
Post a Comment