Avalonia ReactiveUI MVVM 模式之命令绑定(一)

内容分享4小时前发布
0 0 0

本章通过自学分享一些Avalonia ReactiveUI MVVM 模式之命令绑定经验,有不对之处,欢迎各位大佬给予纠正。

一、MVVM介绍

关于MVVM介绍,以下来自Avalonia文档

Avalonia ReactiveUI MVVM 模式之命令绑定(一)

Model-View-View Model(MVVM)模式是一种常见的UI应用程序结构方式。它使用数据绑定系统来帮助在视图和视图模型之间传递数据。这意味着它实现了应用程序逻辑(视图模型)与UI显示(视图)的分离。

应用程序逻辑与业务服务(模型)之间的分离通常通过依赖注入(DI)系统来实现。

对于简单的应用程序来说,MVVM可能有些过度设计;但随着应用程序的发展,往往会出现在同一UI组件模块中保持显示定义和应用程序逻辑的问题:

UI组件之间的交互变得复杂且容易出错。由于依赖于目标UI平台,对UI组件进行单元测试变得困难。

MVVM通过将应用程序逻辑抽象为仅包含代码的类来解决这个问题,这些类不依赖于目标UI平台,因此可以独立进行单元测试。

二、现在开始,我们用VS创建一个Avalonia .NET MVVM App (AvaloniaUl)项目,MVVM Toolkit选择ReactiveUI  (关键)

Avalonia ReactiveUI MVVM 模式之命令绑定(一)

三、基本按钮功能实现

1.修改ViewsMainWindow.axaml文件,在视图中添加一个按钮控件,代码如下:

<Window xmlns=”https://github.com/avaloniaui”
        xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
        xmlns:vm=”using:AvaloniaApplication2.ViewModels”
        xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″
        xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″
        mc:Ignorable=”d” d:DesignWidth=”800″ d:DesignHeight=”450″
        x:Class=”AvaloniaApplication2.Views.MainWindow”
        x:DataType=”vm:MainWindowViewModel”
        Icon=”/Assets/avalonia-logo.ico”
        Title=”AvaloniaApplication2″>

    <Design.DataContext>
        <!– This only sets the DataContext for the previewer in an IDE,
        to set the actual DataContext for runtime, set the DataContext property in code (look at App.axaml.cs) –>
        <vm:MainWindowViewModel/>
    </Design.DataContext>
    <StackPanel>
        <TextBlock Text=”{Binding Greeting, Mode=TwoWay}” HorizontalAlignment=”Center” VerticalAlignment=”Center”/>

        <!–执行ViewModelsMainWindowViewModel.cs文件中Execute函数–>
        <Button  Command=”{Binding Execute}”>Execute</Button>
    </StackPanel>
    </StackPanel>
</Window>

2.修改ViewModelsMainWindowViewModel.cs文件,代码如下:

using ReactiveUI;

namespace AvaloniaApplication2.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string _greeting = “欢迎使用Avalonia!”;
        public string Greeting
        {
            get => _greeting;
            set => this.RaiseAndSetIfChanged(ref _greeting, value);
        }

        public void Execute()
        {
            Greeting = System.DateTime.Now.ToString();
        }
    }
}
 

3.以上已经实现了简单命令绑定,程序运行后,每次点击文本框会更新当前时间。

Avalonia ReactiveUI MVVM 模式之命令绑定(一)

四、ReactiveCommand方法

第三部分绑定能够满足大部分功能需求。但在特定情况下,我们使用ReactiveCommand方式,例如基于任务(异步)、按钮状态(判断是否可用)、观察者模式、组合模式等,下面开始介绍这几种方式的实现。

 官方文档参考:https://www.reactiveui.net/docs/handbook/commands/index.html

CreateFromObservable() 观察都模式         
CreateFromTask() 通过任务,使用async/await 支持异步   
Create() 同步模式
CreateCombined() 执行一个或多个命令

4.1 Create() 同步模式

MainWindow.axaml文件无需改动,第一步修改ViewModelsMainWindowViewModel.cs文件,代码如下:

1.创建Execute函数

public ReactiveCommand<Unit, Unit> Execute { get; }

2.给Execute函数指定动作ExecuteAction

Execute = ReactiveCommand.Create(ExecuteAction);

3.创建ExecuteAction函数

public void ExecuteAction()
        {
            Greeting = System.DateTime.Now.ToString();
        }

ViewModelsMainWindowViewModel.cs

using ReactiveUI;
using System.Reactive;

namespace AvaloniaApplication2.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string _greeting = “欢迎使用Avalonia!”;

        public ReactiveCommand<Unit, Unit> Execute { get; }
        public MainWindowViewModel()
        {
            Execute = ReactiveCommand.Create(ExecuteAction);
        }
        public string Greeting
        {
            get => _greeting;
            set => this.RaiseAndSetIfChanged(ref _greeting, value);
        }

        public void ExecuteAction()
        {
            Greeting = System.DateTime.Now.ToString();
        }
    }
}
 

我们已经实现ReactiveCommand方法绑定命令,程序运行后,每次点击后,文本框更新当前时间。是不是感觉多了好多行代码,还是和上面功能一样,不过确实是,如果你只是这样ReactiveCommand方法,真还不如不改,因为我们还是同步执行。

4.2 CreateFromTask() 基于任务(同步)

我们对1.1代码做下简单修改,以实现异步执行(关于同步和异步区别这里不介绍)

将ReactiveCommand.Create() 替换为ReactiveCommand.CreateFromTask()

将ExecuteAction函数声明为异步方式: public async Task ExecuteAction(Unit msg)

ViewModelsMainWindowViewModel.cs

using ReactiveUI;
using System.Reactive;
using System.Threading.Tasks;

namespace AvaloniaApplication2.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string _greeting = “欢迎使用Avalonia!”;

        public ReactiveCommand<Unit, Unit> Execute { get; }
        public MainWindowViewModel()
        {
            Execute = ReactiveCommand.CreateFromTask<Unit>(ExecuteAction);
        }
        public string Greeting
        {
            get => _greeting;
            set => this.RaiseAndSetIfChanged(ref _greeting, value);
        }

        public async Task ExecuteAction(Unit msg)
        {

            await Task.Delay(5000); // 等待5秒
            Greeting = System.DateTime.Now.ToString();
        }
    }
}

程序运行后,点击

程序运行后,点击Execute按钮,5秒后文本框更新当前时间。在这5秒内不会影响你鼠标和键盘和键盘操作,窗口也会随意移动,状态不会出现卡死状态,这就是异步程序最大好处,在这个程序里感觉用处不大,但频繁web请求和数据库操作时非常有用。

4.3 CreateFromObservable() 观察都模式

说实话,观察者模式我也不是完全理解。

下面我列举几个观察者模式代码(最基本功能):

定时执行任务

using ReactiveUI;
using System;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;

namespace AvaloniaApplication2.ViewModels
{
    public class MainWindowViewModel : ViewModelBase
    {
        private string _greeting = “欢迎使用Avalonia!”;

        public ReactiveCommand<string, DateTime> Execute { get; }
        public MainWindowViewModel()
        {
            Execute = ReactiveCommand.CreateFromObservable<string, DateTime>(ExecuteAction);
            Execute.Subscribe(v => ShowObservableResult(v));
        }
        public string Greeting
        {
            get => _greeting;
            set => this.RaiseAndSetIfChanged(ref _greeting, value);
        }

        private IObservable<DateTime> ExecuteAction(string arg)
        {
            return Observable.Interval(TimeSpan.FromSeconds(1)).Select(_ => System.DateTime.Now);

        }

        private void ShowObservableResult(DateTime v)
        {
            Greeting = v.ToString();
        }
    }
}
 

程序运行后,文本框变成了一个时钟,每秒都会更新时间。

© 版权声明

相关文章

暂无评论

none
暂无评论...