WPF中自定义GridLengthAnimation

需求

我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧。

可以通过将一个Grid,分成两个Cloumn,动态调整两个Cloumn的Width,就可以实现这个需求。

我们知道,Clomun的Width是个,而默认的动画没有这样子的。我们就需要自己实现这样一人动画。

设计
我们从Animation的类图上看到

我们可以从需求

我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧。

可以通过将一个Grid,分成两个Cloumn,动态调整两个Cloumn的Width,就可以实现这个需求。

我们知道,Clomun的Width是个GridLength,而默认的动画没有这样子的。我们就需要自己实现这样一人动画。

设计

我们从Animation的类图上看到AnimationTimeline继承,重写其GetCurrentValue

public class GridLengthAnimation : AnimationTimeline
  {
    /// <summary>
    /// Returns the type of object to animate
    /// </summary>
    public override Type TargetPropertyType => typeof(GridLength);

    /// <summary>
    /// Creates an instance of the animation object
    /// </summary>
    /// <returns>Returns the instance of the GridLengthAnimation</returns>
    protected override System.Windows.Freezable CreateInstanceCore()
    {
      return new GridLengthAnimation();
    }

    /// <summary>
    /// Dependency property for the From property
    /// </summary>
    public static readonly DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(GridLength),
      typeof(GridLengthAnimation));

    /// <summary>
    /// CLR Wrapper for the From depenendency property
    /// </summary>
    public GridLength From
    {
      get
      {
        return (GridLength)GetValue(GridLengthAnimation.FromProperty);
      }
      set
      {
        SetValue(GridLengthAnimation.FromProperty, value);
      }
    }

    /// <summary>
    /// Dependency property for the To property
    /// </summary>
    public static readonly DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(GridLength),
      typeof(GridLengthAnimation));

    /// <summary>
    /// CLR Wrapper for the To property
    /// </summary>
    public GridLength To
    {
      get
      {
        return (GridLength)GetValue(GridLengthAnimation.ToProperty);
      }
      set
      {
        SetValue(GridLengthAnimation.ToProperty, value);
      }
    }

    /// <summary>
    /// Animates the grid let set
    /// </summary>
    /// <param name="defaultOriginValue">The original value to animate</param>
    /// <param name="defaultDestinationValue">The final value</param>
    /// <param name="animationClock">The animation clock (timer)</param>
    /// <returns>Returns the new grid length to set</returns>
    public override object GetCurrentValue(object defaultOriginValue,
      object defaultDestinationValue, AnimationClock animationClock)
    {
      double fromVal = ((GridLength)GetValue(GridLengthAnimation.FromProperty)).Value;

      double toVal = ((GridLength)GetValue(GridLengthAnimation.ToProperty)).Value;

      if (fromVal > toVal)
        return new GridLength((1 - animationClock.CurrentProgress.Value) * (fromVal - toVal) + toVal, GridUnitType.Star);
      else
        return new GridLength(animationClock.CurrentProgress.Value * (toVal - fromVal) + fromVal, GridUnitType.Star);
    }

如上所示,我们仿着默认动画实现了From,To,同时将其属性定义为GridLength,当动画执行时,我们重写了GetCurrentValue,使其根据From/To属性相关联。

优化

通过以上代码,我们实现了在GridLength变化时,实现动画。但是,试用后我们发现,动画,有点太线性。这个时候,怎么办?

可以通过引入EasingFunction来实现。我们知道EasingFunction其实就是一个与时间t有关的时间函数f(t).通过时间函数的处理,我们使动画过渡不要那么线性。

 /// <summary>
    /// The <see cref="EasingFunction" /> dependency property's name.
    /// </summary>
    public const string EasingFunctionPropertyName = "EasingFunction";

    /// <summary>
    /// Gets or sets the value of the <see cref="EasingFunction" />
    /// property. This is a dependency property.
    /// </summary>
    public IEasingFunction EasingFunction
    {
      get
      {
        return (IEasingFunction)GetValue(EasingFunctionProperty);
      }
      set
      {
        SetValue(EasingFunctionProperty, value);
      }
    }

    /// <summary>
    /// Identifies the <see cref="EasingFunction" /> dependency property.
    /// </summary>
    public static readonly DependencyProperty EasingFunctionProperty = DependencyProperty.Register(
      EasingFunctionPropertyName,
      typeof(IEasingFunction),
      typeof(GridLengthAnimation),
      new UIPropertyMetadata(null));

对应的,还要重写GetCurrentValue函数。

public override object GetCurrentValue(object defaultOriginValue,
      object defaultDestinationValue, AnimationClock animationClock)
    {
      double fromVal = ((GridLength)GetValue(FromProperty)).Value;

      double toVal = ((GridLength)GetValue(ToProperty)).Value;

      //check that from was set from the caller
      //if (fromVal == 1)
      //  //set the from as the actual value
      //  fromVal = ((GridLength)defaultDestinationValue).Value;

      double progress = animationClock.CurrentProgress.Value;

      IEasingFunction easingFunction = EasingFunction;
      if (easingFunction != null)
      {
        progress = easingFunction.Ease(progress);
      }

      if (fromVal > toVal)
        return new GridLength((1 - progress) * (fromVal - toVal) + toVal, GridUnitType.Star);

        return new GridLength(progress * (toVal - fromVal) + fromVal, GridUnitType.Star);
    }

使用

 <anim:GridLengthAnimation Storyboard.TargetProperty="Width" From="0" To="*" Duration="0:0:0.5"/>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • wpf将表中数据显示到datagrid示例

    a.在.xaml文件中拖入一个datagrid,然后添加列名,使用Binding="{Binding 数据库中的列名称}",如下:  复制代码 代码如下: <DataGrid AutoGenerateColumns="False" Height="438"HorizontalAlignment="Left" Margin="23,278,0,0" Name="dataGrid1" 

  • WPF拖动DataGrid滚动条时内容混乱的解决方法

    在WPF中,如果DataGrid里使用了模板列,当拖动滚动条时,往往会出现列表内容显示混乱的情况.解决方法就是在Binding的时候给UpdateSourceTrigger赋值. <Grid> <Grid.RowDefinitions> <RowDefinition Height="25"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowD

  • WPF中自定义GridLengthAnimation

    需求 我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧. 可以通过将一个Grid,分成两个Cloumn,动态调整两个Cloumn的Width,就可以实现这个需求. 我们知道,Clomun的Width是个,而默认的动画没有这样子的.我们就需要自己实现这样一人动画. 设计 我们从Animation的类图上看到 我们可以从需求 我们想在编辑一个列表中某一个条目时,将编辑的详情内容也放置当前面,比如右侧. 可以通过将一个Grid,分成两个Cloumn,动态调整两个Cloumn的

  • c# WPF中自定义加载时实现带动画效果的Form和FormItem

    背景 今天我们来谈一下我们自定义的一组WPF控件Form和FormItem,然后看一下如何自定义一组完整地组合WPF控件,在我们很多界面显示的时候我们需要同时显示文本.图片并且我们需要将这些按照特定的顺序整齐的排列在一起,这样的操作当然通过定义Grid和StackPanel然后组合在一起当然也是可以的,我们的这一组控件就是将这个过程组合到一个Form和FormItem中间去,从而达到这样的效果,我们首先来看看这组控件实现的效果. 一 动画效果 看了这个效果之后我们来看看怎么来使用Form和For

  • c# WPF中如何自定义MarkupExtension

    在介绍这一篇文章之前,我们首先来回顾一下WPF中的一些基础的概念,首先当然是XAML了,XAML全称是Extensible Application Markup Language (可扩展应用程序标记语言),是专门用于WPF技术中的UI设计语言,通过使用XAML语言,我们能够快速设计软件界面,同时能够通过绑定这种机制能够很好地实现界面和实现逻辑之间的解耦,这个就是MVVM模式的核心了,那么今天我们介绍的MarkupExtension和XAML之间又有哪些的关系呢? Markup Extensio

  • WPF在自定义文本框中实现输入法跟随光标

    本文告诉大家在 WPF 写一个自定义的文本框,如何实现让输入法跟随光标 本文非小白向,本文适合想开发自定义的文本框,从底层开始开发的文本库的伙伴.在开始之前,期望了解了文本库开发的基础知识 本文实现的效果如下 实现 本文的方法参考了 WPF 官方仓库的逻辑,可以在WPF仓库的wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\System\Windows\Documents\ImmComposition.cs文件看到官方是如何让TextB

  • 在WinForm和WPF中使用GMap.Net地图插件简单教程

    如何在WinForm中使用GMap.Net 项目主页:https://greatmaps.codeplex.com/ 下载GMap.Net,我下载的版本:greatmaps_81b71bf30091,编译三个核心项目: GMap.Net.Core:核心DLL GMap.Net.WindowsForms:WinForm中使用的DLL GMap.NET.WindowsPresentation:WPF中使用的DLL 在WinForm项目中使用GMap: 1.新建一个Visual C# 的Windows

  • 在Winform和WPF中注册全局快捷键实现思路及代码

    快捷键辅助类 复制代码 代码如下: class HotKey { /// <summary> /// 如果函数执行成功,返回值不为0. /// 如果函数执行失败,返回值为0.要得到扩展错误信息,调用GetLastError..NET方法:Marshal.GetLastWin32Error() /// </summary> /// <param name="hWnd">要定义热键的窗口的句柄</param> /// <param na

  • c# WPF中System.Windows.Interactivity的使用

    背景 在我们进行WPF开发应用程序的时候不可避免的要使用到事件,很多时候没有严格按照MVVM模式进行开发的时候习惯直接在xaml中定义事件,然后再在对应的.cs文件中直接写事件的处理过程,这种处理方式写起来非常简单而且不用过多地处理考虑代码之间是否符合规范,但是我们在写代码的时候如果完全按照WPF规范的MVVM模式进行开发的时候就应该将相应的事件处理写在ViewModel层,这样整个代码才更加符合规范而且层次也更加清楚,更加符合MVVM规范. 常规用法 1 引入命名空间 通过在代码中引入Syst

  • c# WPF中通过双击编辑DataGrid中Cell的示例(附源码)

    背景 在很多的时候我们需要编辑DataGrid中每一个Cell,编辑后保存数据,原生的WPF中的DataGrid并没有提供这样的功能,今天通过一个具体的例子来实现这一个功能,在这个例子中DataGrid中的数据类型可能是多种多样的,有枚举.浮点类型.布尔类型.DateTime类型,每一种不同的类型需要双击以后呈现不同的效果,本文通过使用Xceed.Wpf.DataGrid这个动态控件库来实现这个功能,当前使用的Dll版本是2.5.0.0,不同的版本可能实现上面有差别,这个在使用的时候需要特别注意

  • WPF中的数据模板用法介绍

    数据模板常用在3种类型的控件, 下图形式: 1.Grid这种列表表格中修改Cell的数据格式, CellTemplate可以修改单元格的展示数据的方式. 2.针对列表类型的控件, 例如树形控件,下拉列表,列表控件, 可以修改其中的ItemTemplate. 3.修改ContentTemplate, 例UserControl控件的数据展现形式. CellTemplate 模板 下面用一个例子, 来演示CellTemplate使用.例子实现一个DataGrid 展示一个普通的数据标, 同时新增一列C

  • WPF中button按钮同时点击多次触发click解决方法

    解决WPF中button按钮同时点击多次触发click的方法,供大家参考,具体内容如下 DateTime lastClick = DateTime.Now; object obj = new object(); int i = 0; private void Button_Click(object sender, RoutedEventArgs e) { this.IsEnabled = false; var t = (DateTime.Now - lastClick).TotalMillise

随机推荐