【问题标题】:Using VisualStateManager to start and stop Storyboards使用 VisualStateManager 启动和停止 Storyboard
【发布时间】:2013-07-18 11:39:43
【问题描述】:

我有一个动画,它通过无限期地旋转 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>

【问题讨论】:

  • 看看这个 :) 也许对你有一点帮助 ;) stackoverflow.com/questions/2009880/…
  • 那太棒了..但那是 WPF 而不是 Silverlight...我似乎无法让 ControlTemplate.Triggers 在 silverlight 中工作

标签: c# silverlight xaml visualstatemanager


【解决方案1】:

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

你可以这样做:

  1. 使用扩展ContentControl 的模板控件来玩 IsEnabled 内容(在等待期间阻止操作);
  2. 创建一个 DP IsWaiting 来切换您的控制视觉状态;
  3. 在 XAML 中创建两种状态:使用 DoubleAnimationRepeatBehavior="Forever"

在您可以添加叠加层和等待消息依赖属性后,例如繁忙指示器控件...

我使用图片作为 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>

【讨论】:

  • 这基本上就是我所做的,谢谢。我最初只是在寻找 XAML 唯一选项,但你的方式几乎就是我让​​它工作的方式
猜你喜欢
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-21
  • 2012-06-20
  • 2016-07-19
  • 2016-12-19
相关资源
最近更新 更多