Maui学习笔记-CommunityToolkit.Mvvm简单使用

  • MVVM模式主要目的是将UI(View)与数据和业务逻辑分开(Model)。这种分离是通过视图模型(ViewModel)实现的。该类充当视图和模型之间的中介。

MVVM模式几个优势 

  • 可重复使用,业务逻辑可以在不同的模块之间重用。

  • 可测试,在MVVM模式种,可以轻松的隔离和测试视图、模型和视图模型代码。

  • 更容易理解的代码结构,UI代码在视图中,业务逻辑和数据结构位于模型中,视图模型充当它们的连接器,项目会变得更容易理解。

一个简单视图模型案例

  • 创建一个项目添加MyViewModel,声明一个TextValue用来存储一个按钮中的文本并对其修改。

  • 添加一个按钮命令来显示按钮文本中显示的点击次数。

public class MyViewModel:INotifyPropertyChanged
{
    private int count = 0;

    private string textValue = "按钮";

    public string TextValue
    {
        get => textValue;
        set
        {
            textValue = value;
            OnPropertyChanged();
        }
    }

    public ICommand UpdateTextCommand { get; set; }

    public MyViewModel()
    {
        UpdateTextCommand = new Command(UpdateText);
    }

    public void UpdateText()
    {
        count++;
        if (count == 1)

            TextValue = $"点击了{count}次";
        else
            TextValue = $"点击了{count}次";


    }

    public event PropertyChangedEventHandler? PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    
}

 

  • 删除MainPage.cs代码中的count变量和按钮事件

  • 在MainPage.xaml中使用BindingContext添加对MyViewModel的引用并修改button中的代码

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MauiApp1"
             x:Class="MauiApp1.MainPage">
   
    <ContentPage.BindingContext>
        <vm:MyViewModel/>
    </ContentPage.BindingContext>
    <ScrollView>
        <VerticalStackLayout
            Padding="30,0"
            Spacing="25">
            <Image
                Source="dotnet_bot.png"
                HeightRequest="185"
                Aspect="AspectFit"
                SemanticProperties.Description="dot net bot in a race car number eight" />

            <Label
                Text="Hello, World!"
                Style="{StaticResource Headline}"
                SemanticProperties.HeadingLevel="Level1" />

            <Label
                Text="Welcome to &#10;.NET Multi-platform App UI"
                Style="{StaticResource SubHeadline}"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I" />

            <Button
                x:Name="CounterBtn"
                Text="{Binding TextValue}" 
                SemanticProperties.Hint="Counts the number of times you click"
                Command="{Binding UpdateTextCommand}"
                HorizontalOptions="Fill" />

        </VerticalStackLayout>
    </ScrollView>
</ContentPage>

CommunityToolkit.Mvvm

  • 在MVVM模式中通常涉及到INotifyPropertyChanged接口的支持和命令属性会编写大量的样板代码,会让代码变得很繁琐容易导致错误。

  • 在.NET社区提供了CommunityToolkit.Mvvm代码生成器,会让我们在实现MVVM是方便很多。

  • 我们在项目中添加CommunityToolkit.Mvvm工具包,并修改MyViewModel中的代码

public partial class MyViewModel:ObservableObject
{
    private int count = 0;

    [ObservableProperty]
    private string textValue = "按钮";

    [RelayCommand]
    private void UpdateText()
    {
        count++;
        TextValue = count==1 ? $"点击了{count}次" : $"点击了{count}次";
    }

}

 

  • 我们可以对比一下前后在MyViewModel中的代码量

  • 使用CommunityToolkit.Mvvm代码生成器简洁了很多。

  • 这里要注意需要在类中添加partial关键字。

  • 还有一点如果该类继承了其他类,可以是使用[INotifyPropertyChanged]特性来标记该类同样可以实现ObservableObject的功能

[INotifyPropertyChanged]
public partial class MyViewModel : SomeOtherBase
{
	......
}
  • 当一个属性依赖于另一个属性时可以使用[NotifyPropertyChangedFor(nameof(被通知属性))]来通知当前属性已更改。

  • 在[RelayCommand]中可以使用CanExecute来控制该命令是否可执行。

下面是使用CommunityToolkit.Mvvm工具包的一个案例

  • 我们在视图模型中使用ObservableCollection创建一个用户集合并绑定到CollectionView中.

  • [RelayCommand]特性会对Initialize生成一个InitializeCommand。

  • [NotifyCanExecuteChangedFor(nameof(InitializeCommand))]指示当IsInitialized属性更改时,通知InitializeCommand的CanExecute 方法重新检查其可执行性。

using System.Collections.ObjectModel;

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace MauiApp1;

public partial class MyViewModel : ObservableObject
{
    [ObservableProperty] private ObservableCollection<User> users;
    
    [ObservableProperty]
    [NotifyCanExecuteChangedFor(nameof(InitializeCommand))]
    private bool isInitialized;
    
    [RelayCommand(CanExecute = nameof(CanInitialize))]
    private async Task InitializeAsync()
    {
        Users = new ObservableCollection<User>(await DummyService.GetUsersAsync());
        IsInitialized = true;
    }
    
    public bool CanInitialize() => !IsInitialized;
}
/// <summary>
/// 模拟远程获取用户数据服务,模拟耗时5秒操作
/// </summary>
public static class DummyService
{
    public static async Task<IEnumerable<User>> GetUsersAsync()
    {
        await Task.Delay(5000);
        return new List<User>()
        {
            new User
            {
                Id = 1,
                Name = "张飞",
            },
            new User
            {
                Id = 2,
                Name = "刘备",
            },
            new User
            {
                Id = 3,
                Name = "赵云",
            },
            new User
            {
                Id = 4,
                Name = "关羽",
            },
        };
    }
}

public class User
{
    public int Id { get; set; }
    
    public string Name { get; set; }
}

引入CommunityToolkit.Maui工具包 

  • 是一组用于.NET MAUI开发的动画、行为、转换器和自定义视图的工具包。

  • 安装后,需要在MauiProgram.cs文件中对它进行引用。

public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder
        .UseMauiApp<App>()
        .UseMauiCommunityToolkit()
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });
  • 来到主页我们使用该工具包中的EventToCommandBehavior来绑定Viewmodel中的初始化命令。

  • 注意需要对toolkit命名空间添加引用。

  • 定义CollectionView并绑定到user,添加ActivityIndicator模拟数据加载。

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:vm="clr-namespace:MauiApp1"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="MauiApp1.MainPage">
    <ContentPage.Behaviors>
        <toolkit:EventToCommandBehavior 
            EventName="Loaded"
            Command="{Binding InitializeCommand}"/>
    </ContentPage.Behaviors>
   
    <ContentPage.BindingContext>
        <vm:MyViewModel/>
    </ContentPage.BindingContext>
    
    <Grid>
        <CollectionView ItemsSource="{Binding Users}">
            <CollectionView.ItemTemplate>
                <DataTemplate
                    x:DataType="vm:User">
                    <HorizontalStackLayout>
                        <Label Text="{Binding Name}"/>
                        <Label Text="{Binding Id}"/>
                    </HorizontalStackLayout>
                    
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
        <ActivityIndicator IsRunning="{Binding InitializeCommand.IsRunning}"/>
    </Grid>
</ContentPage>

 

 运行程序

  • 启动项目模拟加载5秒,然后显示集合.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值