Given a Storyboard started by the VisualStateManager as part of a ControlTemplate, how would I adjust the SpeedRatio of that animation based on property changes of the control?
<ControlTemplate>
<Grid>
<VisualStateManager.Visu开发者_C百科alStateGroups>
<VisualStateGroup>
<VisualState>
<Storyboard Name="SpinningThing"
SpeedRatio="{Binding SpinningSpeedRatio}">
...
This needs to work in both WPF and Silverlight.
I don't think I can set a binding there for a number of reasons. Foremost, Storyboard is Freezable so you can't just go setting the SpeedRatio all willy-nilly in WPF. But, if it's started by the VisualStateManager, can I call SetSpeedRatio on it?
Also, since its parent is a VisualState, doesn't that mean there would be no governing FrameworkElement to relate to for it?
So, if I can't do it with a binding, how can this be done?
For those arriving here looking for a UWP solution, you can use an {x:Bind}
on the SpeedRatio
property of a Storyboard
and it does dynamically change the speed ratio as you would expect.
<Storyboard SpeedRatio="{x:Bind ViewModel.SpinningSpeedRatio, Mode=OneWay}">
Edit: One caveat is you need to ensure you set the ratio on the UIThread
, otherwise it will be ignored by the VisualStateManager
.
The Storyboard
will still play, but not at the speed you have set.
Normally you would use a {TemplateBinding...} rather than a {Binding...}, but that only works for simple, compatible, types.
You should also be able to bind to the templated control using a "relative binding source". This also allows you to use a value convertor if the types do not match.
SpeedRation={Binding SomeProperty, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource SomeConverter}}"
I have not tested this in WPF, but Silverlight is normally the feature-restricted one.
Alright, so it looks like there really is no way to handle this strictly with a binding. So to account for it, I have hooked events in the code-behind to start/adjust the animations as appropriate.
精彩评论