使用VisualStateManager启动和停止Storyboard

时间:2013-07-19 08:49:10

标签: c# silverlight xaml visualstatemanager

我有一个动画,通过无限期地旋转360度来动画Canvas(它基本上旋转)。我想要的是这个动画在显示控件时启动,然后在隐藏控件时停止。我想我可以用某种方式把它绑在VisualStateManager上。我已经看到了一个淡入淡出控件here的例子,它可以工作但我不知道如何使用VSM来启动和停止故事板

<Canvas.Resources>
    <Storyboard x:Name="spinnerBoard">
        <DoubleAnimation
            Storyboard.TargetName="SpinnerRotate"
            Storyboard.TargetProperty="Angle"
            From="0" To="360" Duration="0:0:01.3"
            RepeatBehavior="Forever" />
    </Storyboard>
</Canvas.Resources>

<Canvas.RenderTransform>
    <RotateTransform x:Name="SpinnerRotate" Angle="0" />
</Canvas.RenderTransform>

示例VSM

<VisualState x:Name="Show">
    <Storyboard>
        <!-- Start the story board here -->
    </Storyboard>
</VisualState>
<VisualState x:Name="Hide">
    <Storyboard>
        <!-- Stop the story board here -->
    </Storyboard>
</VisualState>

1 个答案:

答案 0 :(得分:3)

您对不同问题的全球答案:
ExtendedVisualStateManager.GoToElementState returns false in Silverlight
Default binding to UserControl for custom DP

您可以这样做:

  1. 使用扩展ContentControl的模板控件进行播放 IsEnabled内容(阻止等待期间的操作);
  2. 创建一个用于切换控件可视状态的DP IsWaiting;
  3. 在XAML中创建两个状态:将DoubleAnimationRepeatBehavior="Forever"
  4. 一起使用

    您可以添加覆盖和等待消息依赖属性,如忙指标控件...

    我为Waiting视觉部分使用了一张图片,但你可以使用画布,网格等......

    <强> C#

    [TemplateVisualState(GroupName = "WaitGroup", Name = WaitSpinner.IsWaitingStateName)]
    [TemplateVisualState(GroupName = "WaitGroup", Name = WaitSpinner.NotWaitingStateName)]
    public class WaitSpinner : ContentControl
    {
        #region States names
        internal const String IsWaitingStateName = "IsWaitingState";
        internal const String NotWaitingStateName = "NotWaitingState";
        #endregion States names
    
        public bool IsWaiting
        {
            get { return (bool)GetValue(IsWaitingProperty); }
            set { SetValue(IsWaitingProperty, value); }
        }
    
        public static readonly DependencyProperty IsWaitingProperty =
            DependencyProperty.Register("IsWaiting", typeof(bool), typeof(WaitSpinner), new PropertyMetadata(false, OnIsWaitingPropertyChanged));
    
        private static void OnIsWaitingPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            WaitSpinner waitSpinner = (WaitSpinner)sender;
            waitSpinner.ChangeVisualState(true);
        }
    
        public WaitSpinner()
        {
            DefaultStyleKey = typeof(WaitSpinner);
        }
    
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            ChangeVisualState(false);
        }
    
        protected virtual void ChangeVisualState(bool useTransitions)
        {
            VisualStateManager.GoToState(this, IsWaiting ? IsWaitingStateName : NotWaitingStateName, useTransitions);
        }
    }
    

    Xaml:

    <VisualStateGroup x:Name="WaitGroup">
        <VisualState x:Name="NotWaitingState" >
            <Storyboard>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Control.IsEnabled)" Storyboard.TargetName="content">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <System:Boolean>True</System:Boolean>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
        <VisualState x:Name="IsWaitingState">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="WaitPart">
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.200" Value="Visible"/>
                </ObjectAnimationUsingKeyFrames>
                <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" Storyboard.TargetName="WaitPart" To="360" RepeatBehavior="Forever" Duration="0:0:1" />
                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Control.IsEnabled)" Storyboard.TargetName="content">
                    <DiscreteObjectKeyFrame KeyTime="0">
                        <DiscreteObjectKeyFrame.Value>
                            <System:Boolean>False</System:Boolean>
                        </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
    </VisualStateGroup>
    <!-- ............. -->
    <ContentControl
        IsTabStop="False"
        x:Name="content"
        Content="{TemplateBinding Content}"
        ContentTemplate="{TemplateBinding ContentTemplate}"
        HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
        VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
        Foreground="{TemplateBinding Foreground}"
        ScrollViewer.HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
        ScrollViewer.VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"/>
    <Image Source="CirclePicture.png"
        x:Name="WaitPart"
        RenderTransformOrigin="0.5,0.5"
        Width="16"
        Height="16"
        Visibility="Collapsed"
        IsHitTestVisible="False">
        <Image.RenderTransform>
            <RotateTransform  />
        </Image.RenderTransform>
    </Image>