wpf 如何在 ViewModel 中播放 Storyboard?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17769849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to play Storyboard in ViewModel?
提问by ar.gorgin
I defiend a storyborad in View
我在 View 中定义了一个故事板
<Storyboard x:Key="ExpandAdd" >
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="AddUsers" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{x:Static Visibility.Collapsed}"/>
<DiscreteObjectKeyFrame KeyTime="00:00:00.3000000" Value="{x:Static Visibility.Visible}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="DetailBorder" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0.4"/>
</DoubleAnimationUsingKeyFrames>
<BooleanAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="DetailBorder" Storyboard.TargetProperty="(UIElement.IsEnabled)">
<DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
I have a button and bind to a relaycommand .
我有一个按钮并绑定到一个 relaycommand 。
<Button x:Name="AddUserButton" Content="?????">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding AddUsers}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
I want to play storyboard when RelayCommand(AddUsers) is execute.
我想在执行 RelayCommand(AddUsers) 时播放情节提要。
回答by Rohit Vats
You should not access Storyboardfrom your ViewModel. It defeats the purpose of MVVMaltogether.
您不应该Storyboard从您的ViewModel. 它MVVM完全违背了目的。
You can apply storyboard on Button.LostMouseCaptureevent which gets raised after your command gets called on Clickevent -
您可以在Button.LostMouseCapture事件上应用故事板,该事件在您的命令被Click事件调用后引发-
<Button x:Name="AddUserButton" Content="?????">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand Command="{Binding AddUsers}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.LostMouseCapture">
<BeginStoryboard Storyboard="{StaticResource ExpandAdd}">
</EventTrigger>
</Button.Triggers>
</Button>
回答by Richard Haggard
Actually, this is relatively easy to do by using a DataTrigger that is bound to a property in the ViewModel, thus triggering the Storyboard from the MV while still maintaining separation of concerns. Here's a very brief example where a Storyboard grows an image in size in response to a bool in the VM changing to True.
实际上,通过使用绑定到 ViewModel 中的属性的 DataTrigger,这相对容易做到,从而在仍然保持关注点分离的同时从 MV 触发 Storyboard。这是一个非常简短的示例,其中 Storyboard 增大图像的大小以响应 VM 中的 bool 更改为 True。
<Image
Grid.Row="0"
x:Name="LockImage"
Source="/StoryboardManagerExample;component/Resources/LockedPadlock.png"
Width="50"
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="ptScale" ScaleX="1" ScaleY="1"/>
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</Image.RenderTransform>
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger
Binding="{Binding RunStoryboard}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Width"
From="50"
To="100"
Duration="0:0:1"
RepeatBehavior="1x"
AutoReverse="True"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
回答by New Dev
You could call the Storyboard from a code-behind as long as you assigned it x:Name. But then, you'd need to implement a button_click event handler, not a command for the ViewModel.
您可以从代码隐藏中调用 Storyboard,只要您为其指定了 x:Name。但是,您需要实现一个 button_click 事件处理程序,而不是 ViewModel 的命令。
If you're using MVVM then you should really abide by the principle that the ViewModel should not "know" about specifics of the View.
如果您使用的是 MVVM,那么您应该真正遵守 ViewModel 不应该“知道”View 的细节的原则。
回答by slugster
Please don't trigger the storyboard from the viewmodel. If you do then there is no point having a viewmodel.
请不要从视图模型触发故事板。如果你这样做了,那么拥有一个视图模型是没有意义的。
Implement any code for the relay command in the code behind of the view, then if needed you can call through to the viewmodel to do anything that is viewmodel specific. When you reference the storyboard from the code behind of the view you can just refer to it by name.
在视图背后的代码中实现任何中继命令的代码,然后如果需要,您可以调用视图模型来执行任何特定于视图模型的操作。当您从视图背后的代码中引用故事板时,您只需按名称引用它。
回答by Alamakanambra
For UWP: You can define your storyboard in VisualStatesand run it by changing property in ViewModel. If you change IsRefreshWorkingproperty to trueanimation begins.
对于 UWP:您可以在其中定义故事板VisualStates并通过更改 ViewModel 中的属性来运行它。如果将IsRefreshWorking属性更改为true动画开始。
Define VisualState, using IsTrueTrigger:
使用 IsTrueTrigger 定义 VisualState:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="RefreshProgressVisualStates">
<VisualState x:Name="NotWorkingVisualState" />
<VisualState x:Name="WorkingVisualState">
<Storyboard AutoReverse="False" RepeatBehavior="Forever">
<DoubleAnimation Duration="0:0:1" To="360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="RefreshIcon" />
</Storyboard>
<VisualState.StateTriggers>
<StateTrigger IsActive="{x:Bind ViewModel.IsRefreshWorking, Mode=OneWay}" />
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
AppBarButton with animation:
带动画的 AppBarButton:
<AppBarButton>
<AppBarButton.Icon>
<SymbolIcon x:Name="RefreshIcon" Symbol="Refresh" RenderTransformOrigin="0.5,0.5" >
<SymbolIcon.RenderTransform>
<CompositeTransform/>
</SymbolIcon.RenderTransform>
</SymbolIcon>
</AppBarButton.Icon>
</AppBarButton>

