c# - Eliminating the Storyboard Completed handler in code behind -
a little background:
i'm building window , i've got storyboard use show briefly popup upon completion of user-initiated task without need user confirmation. looks so:
<usercontrol.resources> <storyboard x:name="fadingfeedback" x:key="fadingfeedback" completed="fadingfeedback_completed"> <doubleanimation storyboard.targetproperty="opacity" from="0.5" to="0" begintime="0:0:0" duration="0:0:2.0"> <doubleanimation.easingfunction> <exponentialease exponent="10" easingmode="easein" /> </doubleanimation.easingfunction> </doubleanimation> </storyboard> </usercontrol.resources>
the popup i'm using defined so:
<popup name="popup" placement="center" popupanimation="fade" allowstransparency="true" isopen="{binding doshowmessage}"> <popup.style> <style> <style.triggers> <datatrigger binding="{binding doshowmessage}" value="true"> <setter property="popup.isopen" value="true" /> <datatrigger.enteractions> <beginstoryboard storyboard="{staticresource fadingfeedback}" /> </datatrigger.enteractions> </datatrigger> </style.triggers> </style> </popup.style> <border background="black" borderbrush="white" borderthickness="1" cornerradius="5"> <grid background="transparent"> <grid name="popupgrid" background="black" grid.column="0" grid.row="0" /> <label name="popuplabel" horizontalalignment="center" foreground="white" verticalalignment="center" background="transparent" grid.column="0" grid.row="0" fontsize="16" content="{binding textmessage}"/> </grid> </border> </popup>
there's viewmodel datacontext , it's got couple of properties (referenced there in bindings) provide textmessage string , doshowmessage bool. defined this:
private string _textmessage; public string textmessage { { return _textmessage; } set { _textmessage = value; onpropertychanged("textmessage"); } } private bool _doshowmessage; public bool doshowmessage { { return _doshowmessage; } set { _doshowmessage = value; onpropertychanged("doshowmessage"); } }
and when appropriate viewmodel set doshowmessage
property , binding in xaml show popup , begin storyboard.
right now, i've got completed
handler in code behind popup this:
void statusfader_completed(object sender, eventargs e) { popup.isopen = false; }
and works enough, , since popup.isopen
bound underlying property on viewmodel doshowmessage
, reset boolean.
the question have:
is there "better" way handle reset of doshowmessage property when storyboard done? or perhaps differently put, there way in xaml itself? i've read opinion/convention code behind should (mostly) devoid of code views seems (at least me) (the event handler) reasonable way it. wondering if there's way in xaml though.
yes, of course can in way. setting popup.isopen="false"
via objectanimationusingkeyframes
.
for example:
storyboard
<storyboard x:name="fadingfeedback" x:key="fadingfeedback"> <doubleanimation storyboard.targetproperty="opacity" from="0.5" to="0" begintime="0:0:0" duration="0:0:2.0"> <doubleanimation.easingfunction> <exponentialease exponent="10" easingmode="easein" /> </doubleanimation.easingfunction> </doubleanimation> <objectanimationusingkeyframes begintime="0:0:2.0" storyboard.targetproperty="(popup.isopen)"> <discreteobjectkeyframe keytime="0:0:0"> <discreteobjectkeyframe.value> <sys:boolean>false</sys:boolean> </discreteobjectkeyframe.value> </discreteobjectkeyframe> </objectanimationusingkeyframes> </storyboard> <popup name="popup" placement="center" popupanimation="fade" allowstransparency="true" isopen="{binding doshowmessage}"> <popup.style> <style> <style.triggers> <datatrigger binding="{binding doshowmessage}" value="true"> <!--<setter property="popup.isopen" value="true" />--> <!-- not necessarily, because have popup.isopen = true --> <datatrigger.enteractions> <beginstoryboard storyboard="{staticresource fadingfeedback}" /> </datatrigger.enteractions> </datatrigger> </style.triggers> </style> </popup.style> ... </popup>
but in case, opening popup
outside animation problematic, because of properties of animation first priority, other sources, such code, designate not. quote msdn
:
in order have practical effect, animation of property must able have precedence on base (unanimated) value, if value set locally.
so accessed through code, remove animation property, therefore allowing access property, so:
xaml
<grid> <grid.triggers> <eventtrigger sourcename="closebutton" routedevent="button.click"> <beginstoryboard> <storyboard> <booleananimationusingkeyframes storyboard.targetname="mypopup" storyboard.targetproperty="(popup.isopen)" duration="0:0:0"> <discretebooleankeyframe keytime="0:0:0" value="false" /> </booleananimationusingkeyframes> </storyboard> </beginstoryboard> </eventtrigger> </grid.triggers> <popup x:name="mypopup" width="200" height="200" isopen="true"> <grid background="azure"> <label content="test label" /> </grid> </popup> <button name="openbutton" content="openbuttonfromcode" width="140" height="30" click="openbutton_click" /> <button name="closebutton" content="closebuttonfromeventtrigger" width="180" height="30" margin="0,80,0,0" /> </grid>
code behind
private void openbutton_click(object sender, routedeventargs e) { mypopup.beginanimation(popup.isopenproperty, null); mypopup.isopen = true; }
there choice, or drop in popup.isopen
of false in event storyboard_completed
, or in animation, access code, must removed.
for myself, so, create attached dependency property (boolean), bound trigger animation property. if value of true, starts animation, re-run, in event storyboard_completed
had fold property false. me, it's easier way.
Comments
Post a Comment