【问题标题】:WPF Waiting for animation to end before handling eventWPF在处理事件之前等待动画结束
【发布时间】:2014-06-20 17:16:42
【问题描述】:

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

现在,我想为这个椭圆的背景(填充)设置动画,当触控笔或鼠标进入它时,如果你点击它(你在 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>

然后订阅 ''StylusDown''/''MouseDown'' 事件来实际处理按钮按下。按下按钮启动另一个表单。问题是我想在启动此表单之前等待动画完成。这样的事情可能吗?

【问题讨论】:

  • 您是否尝试在事件处理程序中设置睡眠?它不是 WPF 中的一种形式。你可能想在休假中取消。
  • 真的有必要取消事件(例如 e.Handled=true)吗?

标签: c# wpf wpf-animation


【解决方案1】:

您可以使用 Storyboard.Completed 事件:

将 Duration 设置为 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;
    }
}

【讨论】:

  • 有没有办法从特定的椭圆中获取对故事板的引用?我宁愿没有一个全局故事板完成事件来处理,而是附加到特定的椭圆,然后是它的故事板。
  • 我无法按照您指定的方式进行操作。但如果椭圆是发送者,您可以检查全局事件处理程序。
  • 谢谢,我看看能不能再修改一下并发布我的发现。
  • 如果您知道如何为特定椭圆分配事件,请告诉我。
【解决方案2】:

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

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

http://msdn.microsoft.com/en-us/library/5z57dxz2(v=vs.90).aspx

  1. 使用Async/Await 的新功能。这是它的链接 -

http://msdn.microsoft.com/en-us/library/hh191443.aspx

就我个人而言,我会选择 Async/Await 选项,因为它高效且不会给您带来从单独线程更新 UI 的开销。

【讨论】:

  • 我意识到这一点,但我不确定这正是问题所在。我不是在等待表单完成它的工作,基本上我希望点击动画发生然后弹出打开表单。但是,我似乎无法引用包含动画指令的情节提要,因为它通过按钮/椭圆的样式引用松散耦合。
猜你喜欢
  • 1970-01-01
  • 2016-11-26
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
  • 1970-01-01
相关资源
最近更新 更多