开发者

How to Begin a StoryBoard from ViewModel?

开发者 https://www.devze.com 2023-04-13 00:14 出处:网络
I am utilizing Telerik controls in my example. <telerik:RadPanelBarItem Collapsed=\"RadPanelBarItem_Collapsed\"

I am utilizing Telerik controls in my example.

<telerik:RadPanelBarItem Collapsed="RadPanelBarItem_Collapsed"
                                     DropPosition="Inside"
                                     Header="Searching for Clients"
                                     IsExpanded="false"
                                     IsTabStop="True"
                                     TabNavigation="Once">

     <i:Interaction.Triggers>
         <i:EventTrigger EventName="Expanded">
             <i:InvokeCommandAction Command="{Binding ExpandedComand}" />
         </i:EventTrigger>
     </i:Interaction.Triggers>
</telerik:RadPanelBarItem>

I would like to Run code within the ViewModel whenever the Expanded event is triggered. So far so good, but I also need to start an animation upon expanding it. But this is not possible from the ViewModel, but it has to run on the view:

ArrowStoryboard.Begin();

So how开发者_如何学C should I do this?

UPDATE:

Let me elaborate a bit more as it seems it caused some confusion. I don't have to execute the view related animation from the ViewModel. But I have to execute two thing upon expansion event. 1) Begin the Animation and 2) run a set of code on the viewModel.

The only way I know of but isn't great as it ads code to the code-behind is this: Casting the DataContext to the ViewModel and run the according method on the ViewModel right after beginning of Animation.

Thanks,


Why not attach another behavior ControlStoryboardAction aside your InvokeCommandAction?

xmlns:eim="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions" 

 <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Expanded"> 
         <i:InvokeCommandAction Command="{Binding ExpandedComand}" /> 
         <eim:ControlStoryboardAction Storyboard="{StaticResource YourStoryBoard}"/>
     </i:EventTrigger> 
 </i:Interaction.Triggers> 

UPDATE

It's actually not a lot of work to do this kind of animations inside the style using Blend.

What I've done here basically is I used Blend to generate the default style of RadPanelBarItem, then in the Expand visual state, I created an animation that flys out the arrow and made it run forever.

This is not exactly the animation you want (the arrow goes up rather than right) but it may give you some ideas. Hope this helps. :)

Just apply the style name AnimatedRadPanelBarItemStyle.

    <LinearGradientBrush x:Key="ControlItem_Background_Normal" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="White"/>
        <GradientStop Color="Gainsboro" Offset="0.43"/>
        <GradientStop Color="#FFADADAD" Offset="0.44"/>
        <GradientStop Color="#FFD4D4D4" Offset="1"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ControlItem_OuterBorder_Normal" Color="#FF848484"/>
    <SolidColorBrush x:Key="ControlForeground_Normal" Color="#FF000000"/>
    <SolidColorBrush x:Key="ControlItem_InnerBorder_Normal" Color="#FFFFFFFF"/>
    <SolidColorBrush x:Key="ControlItem_OuterBorder_MouseOver" Color="#FFFFC92B"/>
    <SolidColorBrush x:Key="ControlItem_InnerBorder_MouseOver" Color="#FFFFFFFF"/>
    <LinearGradientBrush x:Key="ControlItem_Background_MouseOver" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFFFFBA3" Offset="1"/>
        <GradientStop Color="#FFFFFBDA" Offset="0"/>
        <GradientStop Color="#FFFFD25A" Offset="0.43"/>
        <GradientStop Color="#FFFEEBAE" Offset="0.42"/>
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="ControlItem_OuterBorder_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FF282828"/>
        <GradientStop Color="#FF5F5F5F" Offset="1"/>
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="ControlItem_InnerBorder_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFB69A78"/>
        <GradientStop Color="#FFFFE17A" Offset="0.126"/>
    </LinearGradientBrush>
    <LinearGradientBrush x:Key="ControlItem_Background_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFFFD74E" Offset="0.996"/>
        <GradientStop Color="#FFFFDCAB" Offset="0.17"/>
        <GradientStop Color="#FFFFB062" Offset="0.57"/>
        <GradientStop Color="#FFFFD18F" Offset="0.56"/>
        <GradientStop Color="#FFFFBA74"/>
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ControlOuterBorder_Disabled" Color="#FF989898"/>
    <SolidColorBrush x:Key="ControlInnerBorder_Disabled" Color="Transparent"/>
    <SolidColorBrush x:Key="ControlBackground_Disabled" Color="#FFE0E0E0"/>
    <SolidColorBrush x:Key="ControlElement_Normal" Color="#FF000000"/>
    <SolidColorBrush x:Key="FocusBrushBlack" Color="#FF000000"/>
    <ControlTemplate x:Key="PanelBarItemTopLevelTemplate" TargetType="telerik:RadPanelBarItem">
        <Grid x:Name="RootElement">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal"/>
                    <VisualState x:Name="Disabled">
                        <Storyboard>
                            <DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="NormalVisual"/>
                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisual"/>
                            <DoubleAnimation Duration="0" To="0.5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Header"/>
                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="arrow">
                                <DiscreteObjectKeyFrame KeyTime="0">
                                    <DiscreteObjectKeyFrame.Value>
                                        <Visibility>Collapsed</Visibility>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="MouseOver">
                        <Storyboard>
                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MouseOverVisual"/>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="MouseOut"/>
                </VisualStateGroup>
                <VisualStateGroup x:Name="SelectionStates">
                    <VisualState x:Name="Unselected"/>
                    <VisualState x:Name="Selected">
                        <Storyboard>
                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectVisual"/>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
                <VisualStateGroup x:Name="ExpandStates">
                    <VisualState x:Name="Expanded">
                        <Storyboard RepeatBehavior="Forever">
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ItemsContainer">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                            </ObjectAnimationUsingKeyFrames>
                            <DoubleAnimation Duration="0:0:0.2" From="0.0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ItemsContainer"/>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="arrow">
                                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="-6"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)" Storyboard.TargetName="arrow">
                                <EasingDoubleKeyFrame KeyTime="0" Value="180"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="180"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="180"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="180"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="arrow">
                                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
                                <EasingDoubleKeyFrame KeyTime="0:0:1.4" Value="1"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Collapsed"/>
                </VisualStateGroup>
                <VisualStateGroup x:Name="FocusStates">
                    <VisualState x:Name="Focused">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Unfocused">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid x:Name="HeaderRow">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Border x:Name="NormalVisual" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.ColumnSpan="5">
                    <Border BorderBrush="{StaticResource ControlItem_InnerBorder_Normal}" BorderThickness="1" Background="{TemplateBinding Background}"/>
                </Border>
                <Border x:Name="MouseOverVisual" BorderBrush="{StaticResource ControlItem_OuterBorder_MouseOver}" BorderThickness="1" Grid.ColumnSpan="5" Opacity="0">
                    <Border BorderBrush="{StaticResource ControlItem_InnerBorder_MouseOver}" BorderThickness="1" Background="{StaticResource ControlItem_Background_MouseOver}"/>
                </Border>
                <Border x:Name="SelectVisual" BorderBrush="{StaticResource ControlItem_OuterBorder_Selected}" BorderThickness="1" Grid.ColumnSpan="5" Opacity="0">
                    <Border BorderBrush="{StaticResource ControlItem_InnerBorder_Selected}" BorderThickness="1" Background="{StaticResource ControlItem_Background_Selected}"/>
                </Border>
                <Border x:Name="DisabledVisual" BorderBrush="{StaticResource ControlOuterBorder_Disabled}" BorderThickness="1" Grid.ColumnSpan="5" Opacity="0">
                    <Border BorderBrush="{StaticResource ControlInnerBorder_Disabled}" BorderThickness="1" Background="{StaticResource ControlBackground_Disabled}"/>
                </Border>
                <Path x:Name="arrow" Grid.Column="5" Data="M 1,1.5 L 4.5,5 L 8,1.5" HorizontalAlignment="Right" Margin="7 0" Opacity="1" RenderTransformOrigin="0.5 0.5" Stretch="None" Stroke="{StaticResource ControlElement_Normal}" StrokeThickness="2" VerticalAlignment="Center">
                    <Path.RenderTransform>
                        <CompositeTransform Rotation="0"/>
                    </Path.RenderTransform>
                </Path>
                <ContentPresenter x:Name="Header" Grid.ColumnSpan="4" ContentTemplate="{TemplateBinding HeaderTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                <Rectangle x:Name="FocusVisual" Grid.ColumnSpan="5" Grid.Column="0" IsHitTestVisible="False" Stroke="{StaticResource FocusBrushBlack}" StrokeThickness="1" StrokeDashArray="1 2" Visibility="Collapsed"/>
            </Grid>
            <Grid x:Name="ItemsContainer" Grid.Row="1" Visibility="Collapsed">
                <telerik:LayoutTransformControl x:Name="transformationRoot">
                    <ItemsPresenter/>
                </telerik:LayoutTransformControl>
            </Grid>
        </Grid>
    </ControlTemplate>
    <SolidColorBrush x:Key="ControlSubItem_OuterBorder_MouseOver" Color="#FFFFC92B"/>
    <Thickness x:Key="ControlSubItem_OuterBorderThickness">1</Thickness>
    <SolidColorBrush x:Key="ControlSubItem_InnerBorder_MouseOver" Color="#FFFFFFFF"/>
    <Thickness x:Key="ControlSubItem_InnerBorderThickness">1</Thickness>
    <LinearGradientBrush x:Key="ControlSubItem_Background_MouseOver" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFFFFBA3" Offset="1"/>
        <GradientStop Color="#FFFFFBDA" Offset="0"/>
    </LinearGradientBrush>
    <CornerRadius x:Key="ControlSubItem_InnerCornerRadius">0</CornerRadius>
    <CornerRadius x:Key="ControlSubItem_OuterCornerRadius">1</CornerRadius>
    <SolidColorBrush x:Key="ControlSubItem_OuterBorder_Selected" Color="#FFFFC92B"/>
    <SolidColorBrush x:Key="ControlSubItem_InnerBorder_Selected" Color="#FFFFFFFF"/>
    <LinearGradientBrush x:Key="ControlSubItem_Background_Selected" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FFFCE79F" Offset="1"/>
        <GradientStop Color="#FFFDD3A8"/>
    </LinearGradientBrush>
    <ControlTemplate x:Key="PanelBarItemSecondLevelTemplate" TargetType="telerik:RadPanelBarItem">
        <Grid x:Name="RootElement">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                    <VisualState x:Name="Normal"/>
                    <VisualState x:Name="Disabled">
                        <Storyboard>
                            <DoubleAnimation Duration="0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisual"/>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="MouseOver">
                        <Storyboard>
                            <DoubleAnimation Duration="0:0:0.2" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MouseOverVisual"/>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="MouseOut">
                        <Storyboard>
                            <DoubleAnimation Duration="0:0:0.2" To="0.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="MouseOverVisual"/>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
                <VisualStateGroup x:Name="SelectionStates">
                    <VisualState x:Name="Unselected"/>
                    <VisualState x:Name="Selected">
                        <Storyboard>
                            <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectionVisual"/>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
                <VisualStateGroup x:Name="ExpandStates">
                    <VisualState x:Name="Expanded">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ItemsContainer">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                            </ObjectAnimationUsingKeyFrames>
                            <DoubleAnimation Duration="0:0:0.2" From="0.0" To="1.0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ItemsContainer"/>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Collapsed"/>
                </VisualStateGroup>
                <VisualStateGroup x:Name="FocusStates">
                    <VisualState x:Name="Focused">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                    <VisualState x:Name="Unfocused">
                        <Storyboard>
                            <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisual">
                                <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid x:Name="HeaderRow" Background="Transparent">
                <Border x:Name="MouseOverVisual" BorderBrush="{StaticResource ControlSubItem_OuterBorder_MouseOver}" BorderThickness="{StaticResource ControlSubItem_OuterBorderThickness}" CornerRadius="{StaticResource ControlSubItem_OuterCornerRadius}" Opacity="0">
                    <Border BorderBrush="{StaticResource ControlSubItem_InnerBorder_MouseOver}" BorderThickness="{StaticResource ControlSubItem_InnerBorderThickness}" Background="{StaticResource ControlSubItem_Background_MouseOver}" CornerRadius="{StaticResource ControlSubItem_InnerCornerRadius}"/>
                </Border>
                <Border x:Name="SelectionVisual" BorderBrush="{StaticResource ControlSubItem_OuterBorder_Selected}" BorderThickness="{StaticResource ControlSubItem_OuterBorderThickness}" CornerRadius="{StaticResource ControlSubItem_OuterCornerRadius}" Opacity="0">
                    <Border BorderBrush="{StaticResource ControlSubItem_InnerBorder_Selected}" BorderThickness="{StaticResource ControlSubItem_InnerBorderThickness}" Background="{StaticResource ControlSubItem_Background_Selected}" CornerRadius="{StaticResource ControlSubItem_InnerCornerRadius}"/>
                </Border>
                <Border x:Name="DisabledVisual" BorderBrush="{StaticResource ControlOuterBorder_Disabled}" BorderThickness="{StaticResource ControlSubItem_OuterBorderThickness}" CornerRadius="{StaticResource ControlSubItem_OuterCornerRadius}" Opacity="0">
                    <Border BorderBrush="{StaticResource ControlInnerBorder_Disabled}" BorderThickness="{StaticResource ControlSubItem_InnerBorderThickness}" Background="{StaticResource ControlBackground_Disabled}" CornerRadius="{StaticResource ControlSubItem_InnerCornerRadius}"/>
                </Border>
                <ContentPresenter x:Name="Header" ContentTemplate="{TemplateBinding HeaderTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                <Rectangle x:Name="FocusVisual" IsHitTestVisible="False" RadiusY="2" RadiusX="2" Stroke="{StaticResource FocusBrushBlack}" StrokeThickness="1" StrokeDashArray="1 2" Visibility="Collapsed"/>
            </Grid>
            <Grid x:Name="ItemsContainer" Grid.Row="1" Visibility="Collapsed">
                <ItemsPresenter/>
            </Grid>
        </Grid>
    </ControlTemplate>
    <Style x:Key="AnimatedRadPanelBarItemStyle" TargetType="telerik:RadPanelBarItem">
        <Setter Property="Background" Value="{StaticResource ControlItem_Background_Normal}"/>
        <Setter Property="BorderBrush" Value="{StaticResource ControlItem_OuterBorder_Normal}"/>
        <Setter Property="BorderThickness" Value="1"/>
        <Setter Property="Foreground" Value="{StaticResource ControlForeground_Normal}"/>
        <Setter Property="TabNavigation" Value="Once"/>
        <Setter Property="IsTabStop" Value="True"/>
        <Setter Property="Template" Value="{StaticResource PanelBarItemTopLevelTemplate}"/>
        <Setter Property="Padding" Value="3"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="ChildItemsTemplate" Value="{StaticResource PanelBarItemSecondLevelTemplate}"/>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <telerik:PanelBarPanel/>
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
    </Style>


It's a bad idea to raise view specific action from ViewModel since storyboard has nothing with view model. There're two ways to achieve what you want to do.

  1. You can inject View into ViewModel but I really don't like this idea since MVVM try to make View and ViewModel less coupling.
  2. Use Message Service to send and retrieve data between View and ViewModel this way they don't know each other. I adopt MVVMLight to my project and use its Messenger class. MVVMLight is very easy to use.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号