相关文章推荐
满身肌肉的冲锋衣  ·  Mockito ...·  1 年前    · 
奔跑的铁板烧  ·  javascript - ...·  1 年前    · 

在MVVM模式下,数据的显示都是通过绑定来实现的。当我们在ViewModel里修改数据时,View里面的界面会瞬间变化。但是如果我们希望这个变化有一个动画效果,应该怎么做呢?

可能一开始我们会想到DoubleAnimation、StoryBoard这些东西,但我们很快就会发现,它们只能操作View里面的元素,我们无法在ViewModel里使用它们。

我们在这里使用的方法是:创建一个类似DoubleAnimation的类,它的操作对象就是普通的double类型。在某一个时间段内,double类型的属性连续变化,View里的元素也会显示出一个动画的效果。

首先我们在View里放一个小正方形:

<Canvas>
    <Rectangle Width="10" Height="10" Fill="Red" Canvas.Left="{Binding RectLeft}"/>
</Canvas>

我们看到,正方形的Canvas.Left属性绑定了一个名为RectLeft的属性。而ViewModel也相当简单:

[ImplementPropertyChanged]
public class ViewModel
    public double RectLeft { get; set; }

我们这里用到了Fody.PropertyChanged,所以不用写RaisePropertyChanged那些代码。相关的资料可到百度上搜索。

好了,我们现在只要在某个时间段内,让RectLeft从一个值缓缓地变到另一个值,小正方形就会动起来了。

我们新建一个同样名叫DoubleAnimation的自定义类,然后我们这样来使用它:

DoubleAnimation ani = new DoubleAnimation(10, 700, 1000, (v) =>
    RectLeft = v;
ani.BeginAnimation();

第一个参数是From,第二个参数是To,第三个参数是时间,第四个参数是一个委托,用来改变RectLeft的值。由于RectLeft是一个属性,我们没办法用ref标记把它作为引用参数,只能用这种方法去改变它。

好了,我们现在就来看DoubleAnimation的实现,上代码:

public class DoubleAnimation
    /// <summary>
    /// 最小时间单元
    /// </summary>
    private const int MinTimeUnit = 40;
    private int Segments;
    private double[] MidValues;
    /// <summary>
    /// 构造DoubleAnimation
    /// </summary>
    /// <param name="from">起始点</param>
    /// <param name="to">结束点</param>
    /// <param name="interval">周期,单位毫秒</param>
    /// <param name="setvalue">设值函数</param>
    public DoubleAnimation(double from, double to, int interval, Action<double> setvalue)
        From = from;
        To = to;
        Interval = interval;
        SetValue = setvalue;
    /// <summary>
    /// 起始点
    /// </summary>
    private double From { get; set; }
    /// <summary>
    /// 结束点
    /// </summary>
    private double To { get; set; }
    /// <summary>
    /// 周期,单位毫秒
    /// </summary>
    private int Interval { get; set; }
    /// <summary>
    /// 设值函数
    /// </summary>
    private Action<double> SetValue;
    /// <summary>
    /// 完成函数
    /// </summary>
    public Action Completed;
    /// <summary>
    /// 缓动方法
    /// </summary>
    public EasingMethod EasingMethod { get; set; } = EasingMethod.Linear;
    /// <summary>
    /// 开始动画
    /// </summary>
    public void BeginAnimation()
        Segments = Interval / MinTimeUnit;
        if (Segments == 0)
            Segments = 1;
        MidValues = new double[Segments + 1];
        MidValues[0] = From;
        MidValues[Segments] = To;
        CalcMidValues();
        new Thread(() =>
            for (int i = 0; i < Segments; i++)
                SetValue(MidValues[i]);
                Thread.Sleep(MinTimeUnit);
            SetValue(MidValues[Segments]);
            Completed?.Invoke();
        }).Start();
    /// <summary>
    /// 计算中间值
    /// </summary>
    private void CalcMidValues()
        if (EasingMethod == EasingMethod.Linear)
            double gap = (To - From) / Segments;
            double current = From;
            for (int i = 1; i < Segments; i++)
                current += gap;
                MidValues[i] = current;

代码其实很简单,我们分步骤看:

(1)我们设置好起点From、终点To,时间Interval。

(2)我们知道,1/24秒是一般电影的帧率,也就是差不多40ms一帧,在这个频率下,人眼会觉得动画是连续的。

(3)我们把总时间进行分段,例如是1s,这里面应该有1000/40=25段,端点就是26个。我们计算出26个端点的值。

(4)最普遍也最简单的计算就是线性插值了。我们知道,.NET里面的Animation提供了大量的EasingFunction,它们的作用就是在这里插值用的。这个日后可以完善,慢慢加到类里面。

(5)好了,最重要的一步,就是不断地改变RectLeft的值。在这里,我们是40ms改变一次。可以考虑使用定时器或是线程来做,我们这里用线程去做。代码确实简单,就是一个for循环,改变一次值之后,“睡”40ms。完了之后如果有需要的,可以调用一个Completed的事件。

在MVVM模式下,数据的显示都是通过绑定来实现的。当我们在ViewModel里修改数据时,View里面的界面会瞬间变化。但是如果我们希望这个变化有一个动画效果,应该怎么做呢?可能一开始我们会想到DoubleAnimation、StoryBoard这些东西,但我们很快就会发现,它们只能操作View里面的元素,我们无法在ViewModel里使用它们。我们在这里使用的方法是:创建一个类似Doub...
MVVM模式WPF动态展示图片,界面选择图标,复制到项目中固定目录下面,保存到数据库的是相对路径,再次读取的时候是根据数据库的相对路径去获取项目中绝对路径的图片展示。 首先在ViewModel中 //属性定义 BitmapImage _ImageSource; /// <summary> /// 显示的图标
本示例适合初学者参考,是作者练习WPF的笔记,放上来与大家一起进步! 本资源是笔者学习过程中的笔记,目前包含了WPF中基本控件用法、数据绑定 、WPF动画效果、样式、模板定义、自定义控件、附加行为、多线程、串口模拟编写思路、导航页面、拖动效果、查看控件的默认模板,在集合中如果绑定命令等知识点,适中初级,中级开发者参考。 上图是一个listview的样式,主要用到DataTemplateSelector类 上图把常用控件的默认模板打印出来,方便更改样式 上图是一个模拟串口读写的通讯架构,主
在winform中,如果要执行一个耗时操作,通常会使用进度条ProgressBar来显示耗时操作的进度,在winform中耗时操作的同时更改进度条的值,在UI上面可以看到进度条动态增长。 但是在WPF中(Stylet框架+MVVM开发模式),如果用同样的方法去实现,则会造成UI阻塞,进度条卡死,当耗时操作执行完毕后UI才刷新(参考下图)。 为什么会这样? 先看一下ViewModel ViewModel定义了用于表示耗时操作进度的两个属性以及耗时操作,这些属性或者方法会在View中被绑定。 <Canvas Width="100" Height="100"> 圆的半径是25,设计其基础的样式。因为剩余的圆是通过该圆旋转得到的,旋转的中心是上图中几条红色直线相交的那个点,不难算出RenderTransformOrigin为0.5,2,这个很关键。 <Style x:K
MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中的实现(三)命令绑定 MVVM模式解析和在WPF中的实现(四)事件绑定 MVVM模式解析和在WPF中的实现(五)View和ViewModel的通信 MVVM模式解析和在WPF...
WPF(Windows Presentation Foundation)是一种用于创建Windows应用程序的用户界面框架,它提供了丰富的图形、动画和多媒体功能,非常适合实现图片浏览器功能。 首先,我们可以使用WPF的布局控件,如Grid、StackPanel、WrapPanel等来创建图片浏览器的布局。可以将图片以网格状、列表状或者平铺方式显示出来,通过设置布局控件的属性来达到不同显示效果。 然后,我们可以使用WPF的Image控件来显示图片。通过绑定图片路径,将图片加载到Image控件上,并设置合适的布局和尺寸,使得图片在浏览器中呈现出较好的显示效果。同时可以利用WPF的特性,如绑定、命令等来实现图片的放大、缩小、旋转、拖拽等交互操作。 另外,为了实现图片浏览器的导航功能,我们可以使用WPF的按钮、菜单和导航控件,如ToolBar、Menu、TabControl等来增加上一页、下一页、首页、尾页、放大、缩小等功能按钮,并通过事件绑定和命令来实现相关操作。 此外,WPF还提供了强大的动画和过渡效果功能,我们可以利用这些功能,为图片浏览器增加一些华丽的过渡效果,如渐变、旋转、淡入淡出等,提升用户体验。 最后,在WPF中,我们可以采用MVVM(Model-View-ViewModel)架构来实现图片浏览器的功能。通过创建ViewModel类,将图片数据和操作逻辑与界面分离,实现数据绑定和命令绑定,提高代码的可维护性和重用性。 总的来说,WPF提供了许多强大的功能和灵活的设计模式实现图片浏览器功能,开发者可以根据自己的需求和技术实力,选择最适合的方案来完成项目。
//配置Token builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(opt => opt.TokenValidationParameters = new TokenValidationParameters() ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ClockSkew = TimeSpan.FromSeconds(30), ValidateIssuerSigningKey = false