WPF在处理事件之前等待动画结束

时间:2014-06-20 17:16:43

标签: c# wpf wpf-animation

假设我在屏幕上有一个圆形按钮,我想设置点按它的效果。最初,按钮(椭圆)背景(填充)是透明的,边框画笔(轮廓)具有一些颜色和厚度,使其看起来像一个按钮。

现在,我想在手写笔或鼠标进入时为这个椭圆的背景(填充)设置动画,如果点击它(你在iphone和其他设备上看到它)就会给它带来效果。

我在应用资源中创建了一个样式:

<Style x:Key="circularButton" TargetType="Ellipse">
    <Style.Triggers>
        <EventTrigger RoutedEvent="StylusEnter">
            <BeginStoryboard>
                <Storyboard FillBehavior="Stop">
                    <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="Transparent" To="#993C5E66" Duration="00:00:00.2" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="StylusLeave">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="#993C5E66" To="Transparent" Duration="00:00:00.2" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="MouseEnter">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="Transparent" To="#993C5E66" Duration="00:00:00.2" />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
        <EventTrigger RoutedEvent="MouseLeave">
            <BeginStoryboard>
                <Storyboard>
                    <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="#993C5E66" To="Transparent" Duration="00:00:00.2" />
                </Storyboard>
            </BeginStoryboard>                
        </EventTrigger>
    </Style.Triggers>
</Style>

然后订阅了&#39;&#39; StylusDown&#39;&#39;&#39; MouseDown&#39;&#39;&#39;&#39;&#39;实际处理按钮按下的事件。按钮按下会启动另一种形式。问题是我想在启动此表单之前等待动画完成。这样的事情可能吗?

2 个答案:

答案 0 :(得分:1)

您可以使用Storyboard.Completed事件:

将持续时间设置为00:00:01.2,确保在动画完成之前确实没有打开。

你可以为这个例子改进这一点我决定离开圆圈意味着不打开弹出窗口。

XAML:

  <Window>
      <Window.Resources>

         <Storyboard FillBehavior="Stop" x:Key="StylusEnterSB" Completed="Storyboard_Completed">
            <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="Red" To="#993C5E66" Duration="00:00:00.2" />
         </Storyboard>

         <Storyboard x:Key="StylusLeaveSB" Completed="Storyboard_Completed">
            <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="#993C5E66" To="Transparent" Duration="00:00:00.2" />
         </Storyboard>

         <Storyboard x:Key="MouseEnterSB" Completed="Storyboard_Completed">
            <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="Red" To="#993C5E66" Duration="00:00:00.2" />
         </Storyboard>

         <Storyboard x:Key="MouseLeaveSB" Completed="Storyboard_Completed"> 
            <ColorAnimation Storyboard.TargetProperty="(Ellipse.Fill).Color" From="#993C5E66" To="Red" Duration="00:00:00.2" />
         </Storyboard>

         <Style x:Key="circularButton" TargetType="Ellipse">
            <Style.Triggers>
               <EventTrigger RoutedEvent="StylusEnter">
                   <BeginStoryboard Storyboard="{StaticResource StylusEnterSB}" />                      
                </EventTrigger>
                <EventTrigger RoutedEvent="StylusLeave">
                  <BeginStoryboard Storyboard="{StaticResource StylusLeaveSB}" />                       
                </EventTrigger>
                <EventTrigger RoutedEvent="MouseEnter" >
                  <BeginStoryboard Storyboard="{StaticResource MouseEnterSB}" />                        
                </EventTrigger>
                <EventTrigger RoutedEvent="MouseLeave">
                   <BeginStoryboard Storyboard="{StaticResource MouseLeaveSB}" />                   
                </EventTrigger>
           </Style.Triggers>
       </Style>     
</Window.Resources>

<Grid>      
    <Ellipse Style="{StaticResource circularButton}" Width="25" Height="25" Fill="Red"  MouseLeftButtonUp="Ellipse_MouseLeftButtonUp" MouseLeave="Ellipse_MouseLeave" MouseLeftButtonDown="Ellipse_MouseLeftButtonDown" MouseEnter="Ellipse_MouseEnter"     />      
</Grid>

CS:

    public partial class MainWindow : Window
{
    Popup w = new Popup();  
    public MainWindow()
    {
        InitializeComponent();

        w.Height = 200;
        w.Width = 200;
        w.Child = new Rectangle() { Fill = Brushes.Red, Stretch = Stretch.Fill };
        w.Placement = PlacementMode.Right;
        w.PlacementTarget = this;   
    }

    bool canPress = false;      
    private void Storyboard_Completed(object sender, EventArgs e)
    {
        canPress = true;

        if(isMouseDown)
        {
            w.IsOpen = true;
            isMouseDown = false;
        }
    }


    bool isMouseDown = false;
    private void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (isMouseDown && canPress)
        {
            w.IsOpen = true;
            isMouseDown = false;
        }

    }

    private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        isMouseDown = true;
    }

    private void Ellipse_MouseEnter(object sender, MouseEventArgs e)
    {
        isMouseDown = false;
        canPress = false;
                _currentEllipse = (Ellipse)sender;
    }

    private void Ellipse_MouseLeave(object sender, MouseEventArgs e)
    {
        w.IsOpen = false;       
                    _currentEllipse = null;
    }
}

答案 1 :(得分:0)

这种情况正在发生,因为您正在事件处理程序中打开表单和动画。默认情况下,ui事件处理程序在UI线程(应用程序的唯一线程)中调用,因此UI更新和所有其他事件处理程序任务正在同步完成。由于您的事件处理程序正在等待表单完成,因此线程将暂停,直到表单关闭。要摆脱这种情况,你可以使用 -

  1. Event / Delegates:在对象内部创建另一个事件处理程序并将其附加到自定义事件,只是为了打开表单,然后在调用事件处理程序时触发该事件并在第二个事件处理程序中打开ui。因此,当调用第一个事件处理程序时,它将在新线程中生成表单打开代码,并且它本身可以继续更新ui。然而,这是Async/Await之前的旧方法,如果需要在子线程的UI中更改任何内容,您还需要一些额外的工作来更新UI。
  2. http://msdn.microsoft.com/en-us/library/5z57dxz2(v=vs.90).aspx

    1. 使用新{f}的Async/Await。这是一个链接 -
    2. http://msdn.microsoft.com/en-us/library/hh191443.aspx

      我个人会选择Async / Await选项,因为它的效率很高,并且不会给你从单独的线程更新UI的开销。