按钮动画、定时响应刷新

按钮动画

效果图如下:

新建用户控件UC_AutoRefreshButton

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="auto"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Button Grid.Row="0" Width="auto" Height="auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Click="Button_Click" x:Name="btnReFresh">
        <Button.Background>
            <ImageBrush ImageSource="{Binding ImgBackgroudPath, RelativeSource={RelativeSource AncestorType=local:UC_AutoRefreshButton}}"/>
        </Button.Background>
    </Button>

    <Rectangle Grid.Row="2" Height="5" Width="{Binding Path=ActualWidth,RelativeSource={RelativeSource AncestorType=local:UC_AutoRefreshButton}}">
        <Rectangle.Fill>
            <SolidColorBrush Color="{DynamicResource PrimaryColor}"/>
        </Rectangle.Fill>
    </Rectangle>
    <Rectangle Grid.Row="2" Height="5" Width="{Binding Path=ActualWidth,RelativeSource={RelativeSource AncestorType=local:UC_AutoRefreshButton}}">
        <Rectangle.Fill>
            <SolidColorBrush Color="{DynamicResource BackgroundColor}"/>
        </Rectangle.Fill>
        <Rectangle.OpacityMask>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                <GradientStop Offset="0" Color="Transparent" x:Name="transparentStop"/>
                <GradientStop Offset="0" Color="Black" x:Name="visibleStop"/>
            </LinearGradientBrush>
        </Rectangle.OpacityMask>
    </Rectangle>
</Grid>

<UserControl.Resources>
    <Storyboard x:Key="LinearTimeline" FillBehavior="Stop">
        <DoubleAnimation Storyboard.TargetName="transparentStop"
                         Storyboard.TargetProperty="Offset"
                        From="0" To="1"
                         Duration="{Binding AminationDuration, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Converter={StaticResource Int2DurationConverter}}" />
        <DoubleAnimation Storyboard.TargetName="visibleStop"
                         Storyboard.TargetProperty="Offset"
                        From="0" To="1"
                         Duration="{Binding AminationDuration, RelativeSource={RelativeSource AncestorType=UserControl}, Converter={StaticResource Int2DurationConverter}}" />
    </Storyboard>
</UserControl.Resources>

后台实现

public partial class UC_AutoRefreshButton : UserControl
{
    /// <summary>
    /// 背景图相对路径
    /// </summary>
    public string ImgBackgroudPath
    {
        get { return (string)GetValue(ImgBackgroudPathProperty); }
        set { SetValue(ImgBackgroudPathProperty, value); }
    }
    public static readonly DependencyProperty ImgBackgroudPathProperty =
        DependencyProperty.Register("ImgBackgroudPath", typeof(string), typeof(UC_AutoRefreshButton), new PropertyMetadata(ValueBoxes.StringEmptyBox));


    /// <summary>
    /// 动画持续时间(s)
    /// </summary>
    public int AminationDuration
    {
        get { return (int)GetValue(AminationDurationProperty); }
        set { SetValue(AminationDurationProperty, value); }
    }

    public static readonly DependencyProperty AminationDurationProperty =
        DependencyProperty.Register("AminationDuration", typeof(int), typeof(UC_AutoRefreshButton), new PropertyMetadata(1));

    /// <summary>
    /// 声明路由事件
    /// 参数:要注册的路由事件名称,路由事件的路由策略,事件处理程序的委托类型(可自定义),路由事件的所有者类型
    /// </summary>
    public static readonly RoutedEvent ClickedEvent = EventManager.RegisterRoutedEvent("Clicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UC_AutoRefreshButton));

    /// <summary>
    /// 处理各种路由事件的方法
    /// </summary>
    public event RoutedEventHandler Clicked
    {
        // 将路由事件添加路由事件处理程序
        add { AddHandler(ClickedEvent, value); }
        // 从路由事件处理程序中移除路由事件
        remove { RemoveHandler(ClickedEvent, value); }
    }

    Storyboard _storyboard;

    public UC_AutoRefreshButton()
    {
        InitializeComponent();
    }

    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        StoryboardStart();
    }
    void StoryboardStart()
    {
        _storyboard = this.FindResource("LinearTimeline") as Storyboard;
        if (_storyboard != null)
        {
            _storyboard.Completed -= _storyboard_Completed;
            _storyboard.Completed += _storyboard_Completed;
            _storyboard.Begin(this, true);
        }

    }

    private void _storyboard_Completed(object sender, EventArgs e)
    {
        StoryboardStart();           

        // 定义传递参数
        RoutedPropertyChangedEventArgs<object> args = new RoutedPropertyChangedEventArgs<object>(0, "Storyboard_Completed", ClickedEvent);
        // 引用自定义路由事件
        btnReFresh.RaiseEvent(args);
    }

    private void UserControl_Unloaded(object sender, RoutedEventArgs e)
    {
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        _storyboard.Stop(this);
        _storyboard_Completed(null, null);
    }

}

应用:
<local:UC_AutoRefreshButton x:Name="ucReFresh" Width="200" Height="50" ImgBackgroudPath="/WpfDemo;component/Image/autorefresh.png" AminationDuration="{Binding ElementName=slider,Path=Value}" Clicked="UcReFresh_Clicked" />
<Slider x:Name="slider" Minimum="0" Maximum="10" Value="1" TickPlacement="Both" TickFrequency="1" AutoToolTipPlacement="BottomRight"/>

private void UcReFresh_Clicked(object sender, RoutedEventArgs e)
{
    var args = (RoutedPropertyChangedEventArgs<object>)e;
    MessageBox.Show("Manual Refresh"); 
}

扩展

Button添加图片

<Button HorizontalAlignment="Stretch" Command="{Binding PrevCommand}">
    <Button.Template>
        <ControlTemplate>
            <Grid Cursor="Hand">
                <Image Source="{Binding ImagePrev, Mode=TwoWay}" Stretch="Fill"
                       Width="{Binding ElementName=Grid_p, Path=ActualWidth}" Height="{Binding ElementName=Grid_p, Path=ActualHeight}"/>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>

Button添加Path

<Geometry x:Key="UpGeometry" PresentationOptions:Freeze="True">M......</Geometry>
<Style x:Key="PathBaseStyle" TargetType="{x:Type Path}">
    <Setter Property="Stretch" Value="Uniform" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="FlowDirection" Value="LeftToRight" />
</Style>

<Style x:Key="UpPathStyle" BasedOn="{StaticResource PathBaseStyle}" TargetType="{x:Type Path}">
    <Setter Property="Data" Value="{StaticResource UpGeometry}" />
</Style>

<Button HorizontalAlignment="Stretch" Command="{Binding PrevCommand}">
    <Button.Template>
        <ControlTemplate>
            <Grid Cursor="Hand">
                <Border CornerRadius="4">
                    <Path Margin="2" Fill="White" Style="{StaticResource UpPathStyle}"/>
                </Border>
            </Grid>
    </Button.Template>
</Button>

Button与鼠标移动

<Button HorizontalAlignment="Stretch" Command="{Binding PrevCommand}">
    <Button.Template>
        <ControlTemplate>
            <Grid x:Name="Grid_p" Opacity="0.5" Cursor="Hand">
                <Border Width="100" Height="50" Background="{DynamicResource DarkOpacityBrush}" CornerRadius="4">
                    <Path Margin="2" Fill="White" Style="{StaticResource UpPathStyle}"/>
                </Border>
            </Grid>
            <ControlTemplate.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Grid_p" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:.1"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="FrameworkElement.MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="Grid_p" Storyboard.TargetProperty="Opacity" To="0.5" Duration="0:0:.1"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>


原文地址:https://www.cnblogs.com/wesson2019-blog/p/13498064.html