WPF 通用按钮动画如何执行完毕再执行后台代码

ilikeff8 2017-05-12 05:53:20
资源字典里定义了一个通用按钮样式,以及动画效果

<Style TargetType="Button" x:Key="BigButton" BasedOn="{StaticResource BaseButton}">
<Setter Property="Height" Value="80"/>
<Setter Property="Width" Value="80"/>

<Style.Triggers>
<EventTrigger RoutedEvent="ButtonBase.PreviewMouseDown">
<BeginStoryboard Storyboard="{StaticResource OnButtonClickStoryboard}"/>
</EventTrigger>
</Style.Triggers>
</Style>

<Storyboard x:Key="OnButtonClickStoryboard">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<EasingDoubleKeyFrame KeyTime= "0:0:0.2" Value= "1.1" />
<EasingDoubleKeyFrame KeyTime= "0:0:0.4" Value= "1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty= "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime= "0:0:0.2" Value= "1.1" />
<EasingDoubleKeyFrame KeyTime= "0:0:0.4" Value= "1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>


样式应用于某个按钮

<Button Style="{StaticResource BigButton}" Name="btnUSBCANConfig" Click="btnUSBCANConfig_Click" RenderTransformOrigin="0.5,0.5" >
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
控制器设置
</Button>


想点击这个按钮时,先执行完动画,再运行click事件,否则动画和click里的代码一起运行,动画就会卡

如果注册动画完成事件需要类似

Storyboard1.Completed += new EventHandler(Storyboard1_Completed);
}

void Storyboard1_Completed(object sender, EventArgs e)
{
buttonclick...
}

但我现在怎么获得按钮的storyboard呢
...全文
577 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
exception92 2017-05-15
  • 打赏
  • 举报
回复
引用 7 楼 ilikeff8 的回复:
最好是资源字典里这个通用按钮动画能自动堵塞,执行完再执行对应的按钮的各种操作,如果不行就只能异步了
-》可以! 资源字典也支持后台code, 就像普通的window窗口一样,必须设定一个对应的x:Class 后台类,在后台类中 执行要执行的代码。
ilikeff8 2017-05-15
  • 打赏
  • 举报
回复
最好是资源字典里这个通用按钮动画能自动堵塞,执行完再执行对应的按钮的各种操作,如果不行就只能异步了
ilikeff8 2017-05-15
  • 打赏
  • 举报
回复
引用 4 楼 duanzi_peng 的回复:
否则动画和click里的代码一起运行 ->click里的代码应该比较耗时,造成UI线程卡顿才出现的动画卡顿。都是些什么操作 或者把样式放到窗口中,在后台使用FindResource查询出动画执行。
加载数据库数据到datagrid,那看来动画的地方都最好后台操作都用异步了 样式放到窗口不可行,我这个样式是给所有窗口所有按钮用的,每个窗口都写注册完成事件太麻烦了
ilikeff8 2017-05-15
  • 打赏
  • 举报
回复
引用 3 楼 xuggzu 的回复:
。。。不知道怎么在xaml写事件?那你平时怎么写其它事件的? <Window.Resources> <Storyboard x:Key="OnButtonClickStoryboard" Completed="Storyboard_Completed"> 。。。。。。。。。。
你没明白我的意思,我带动画的样式是放在一个独立的资源文件里的,然后应用给所有界面的所有的按钮的, 所以这里很不好写

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Storyboard x:Key="OnButtonClickStoryboard" Completed="StoryboardCompleted(所有按钮?)">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
            <EasingDoubleKeyFrame KeyTime= "0:0:0.2" Value= "1.1" />
            <EasingDoubleKeyFrame KeyTime= "0:0:0.4" Value= "1" />
        </DoubleAnimationUsingKeyFrames>
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty= "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
            <EasingDoubleKeyFrame KeyTime= "0:0:0.2" Value= "1.1" />
            <EasingDoubleKeyFrame KeyTime= "0:0:0.4" Value= "1" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
</ResourceDictionary>
好像不允许这种写法,必须指定应用的class去找到对应的事件 ResourceDictionary”根元素需要 x:Class 特性来支持 XAML 文件中的事件处理程序。请移除 Completed 事件的事件处理程序,或将 x:Class 特性添加到根元素 但这样就太麻烦了
ilikeff8 2017-05-15
  • 打赏
  • 举报
回复
引用 8 楼 duanzi_peng 的回复:
[quote=引用 7 楼 ilikeff8 的回复:] 最好是资源字典里这个通用按钮动画能自动堵塞,执行完再执行对应的按钮的各种操作,如果不行就只能异步了
-》可以! 资源字典也支持后台code, 就像普通的window窗口一样,必须设定一个对应的x:Class 后台类,在后台类中 执行要执行的代码。[/quote] 搞定了,给数据字典建了个后台class

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    x:Class="分拣墙系统.Style.ButtonStyle">

    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="../Style/FontStyle.xaml"/>
        <ResourceDictionary Source="../Style/TextBlockStyle.xaml"/>
    </ResourceDictionary.MergedDictionaries>

    <Style TargetType="{x:Type Button}"  x:Key="BaseButton" BasedOn="{StaticResource BaseContentControl}">
        <Setter Property="Background" Value="White"/>
        <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <TransformGroup>
                    <ScaleTransform/>
                    <!--<SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>-->
                </TransformGroup>
            </Setter.Value>
        </Setter>
        <EventSetter Event="Click" Handler="OnButtonClick"/>
    </Style>

 public partial class ButtonStyle
    {
        static EventHandler OnButtonStoryboardCompleted = null;

        public void OnButtonClick(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;

            Storyboard storyboard = new Storyboard();
// 动画...
            Storyboard.SetTarget(doubleAnimationUsingKeyFrames1, button);
            Storyboard.SetTarget(doubleAnimationUsingKeyFrames2, button);

            storyboard.Begin();
        }
        private void Storyboard_Completed(object sender, EventArgs e)
        {
            Timeline timeline = ((sender as ClockGroup).Children[0]).Timeline;
            Button button = Storyboard.GetTarget(timeline) as Button;

            OnButtonStoryboardCompleted?.Invoke(button, e);
        }

        static public void RegisterStoryboardCompleted(EventHandler eventHandler)
        {
            var invocationList = OnButtonStoryboardCompleted?.GetInvocationList();

            if (invocationList==null||!invocationList.Contains(eventHandler))
            {
                ButtonStyle.OnButtonStoryboardCompleted += eventHandler;
            }
        }
    }
应用

<Button Style="{StaticResource BigButton}" Name="btnUSBCANConfig" >控制器设置</Button>
美中不足的是原本我想用下面这种方法去调用按钮的点击事件


            ButtonAutomationPeer buttonAutomationPeer = new ButtonAutomationPeer(button);
            IInvokeProvider iInvokeProvider = buttonAutomationPeer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;

                iInvokeProvider.Invoke()  // 调用按钮click实际后台逻辑
会动画和click死循环,因为等于一直触发click了,于是只能上面代码那样调用一个回调函数OnButtonStoryboardCompleted 然后某个窗口里

    ButtonStyle.RegisterStoryboardCompleted(OnButtonStoryboardCompleted);

 void OnButtonStoryboardCompleted(object sender, EventArgs e)
        {
            if (sender == btnUSBCANConfig)
            {
            }
            else if (sender==btnAddressConfig)
            {
            }
        }
然后再xaml里删除掉所欲按钮的click事件 显得有点繁琐了, 如果能在动画完成后,invoke按钮click的时候,暂时禁止动画,然后阻塞invoke,invoke click执行完后恢复按钮的动画,下次手动click按钮时正常动画就好了
exception92 2017-05-13
  • 打赏
  • 举报
回复
否则动画和click里的代码一起运行 ->click里的代码应该比较耗时,造成UI线程卡顿才出现的动画卡顿。都是些什么操作 或者把样式放到窗口中,在后台使用FindResource查询出动画执行。
xuggzu 2017-05-12
  • 打赏
  • 举报
回复
。。。不知道怎么在xaml写事件?那你平时怎么写其它事件的? <Window.Resources> <Storyboard x:Key="OnButtonClickStoryboard" Completed="Storyboard_Completed"> 。。。。。。。。。。
ilikeff8 2017-05-12
  • 打赏
  • 举报
回复
引用 1 楼 xuggzu 的回复:
把事件注册放到xaml不行吗? 如果非用后台代码注册,你的动画不是资源嘛,那就.findresource(xxx)
就是不明白xaml里的button里怎么注册其在style里定义的这个storyboard的完成动画事件并且告知完成后再调用click
xuggzu 2017-05-12
  • 打赏
  • 举报
回复
把事件注册放到xaml不行吗?
如果非用后台代码注册,你的动画不是资源嘛,那就.findresource(xxx)

110,566

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧