Maui之CommunityToolkit社区工具的魔法

Communitytoolkit社区工具给我们开发带来了极大的方便,堪称魔法,非常好用,可以极大的提升企业和个人的开发效率,标注方法[ObservableProperty]、[RelayCommand]和一个方法SetProperty,下面举个例子演示一下。

写一个枚举 Microsoft.Maui.Graphics空间下类Colors的命名颜色,共148个公共静态字段,建一个maui程序名为NamedColorsDemoApp,先在文件夹/Models下建一个模型,NamedColor.cs,文件内容:

namespace NamedColorsDemoApp.Models
{
    internal class NamedColor
    {
        public string Name { get; set; }

        public Color Color { get; set; }
    }
}

在程序内Nuget二个包

然后在文件夹/ViewModels 下创建NamedColorsViewModel.cs文件,文件头内容:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NamedColorsDemoApp.Models;
using System.Collections.ObjectModel;
using System.Reflection;

这个类要派生自ObservableObject,且要设成分部类。

 partial class NamedColorsViewModel : ObservableObject
{
}

创建一个私有的字段 private NamedColor namedColor,再创建一个列表字段allColors,这个带标注方法[ObservableProperty]

    private NamedColor namedColor;

    [ObservableProperty]
    private static ObservableCollection<NamedColorsViewModel> allColors; 

再创建二个可绑定的属性,使用SetProperty,这个太方便了。

        public string Name
        {
            get => namedColor.Name;
            set => SetProperty(namedColor.Name, value, namedColor, (n, v) => n.Name = v);
        }

        public Color Color
        {
            get => namedColor.Color;
            set => SetProperty(namedColor.Color, value, namedColor, (n, v) => n.Color = v);
        }

SetProperty第一个参数是要更新的值,第二个参数是新值,第三个参数是模型,传一个实例,第四个参数是回调动作,用lambda表达式很方便,注意lambda表达式不能捕获外部变量,像我这样起名应该是不会了,外部变量用单词,lambda用字母。

建一个IAsyncEnumerable<NamedColor> AsyncEnumerableAllColors()方法反射命名颜色

       private static async IAsyncEnumerable<NamedColor> AsyncEnumerableAllColors()
        {
            foreach (FieldInfo fieldInfo in typeof(Colors).GetRuntimeFields())
            {
                if ((fieldInfo.FieldType == typeof(Color)) && fieldInfo.IsPublic && 
                   fieldInfo.IsStatic)
                {
                    yield return new NamedColor { Color = (Color)fieldInfo.GetValue(null), 
                      Name = fieldInfo.Name };
                    await Task.Delay(10);
                }
            }
        }

再建一个带标注方法 [RelayCommand]
                                 private async Task InitCollection()

        [RelayCommand]
        private async Task InitCollection()
        {
            AllColors.Clear();
            await foreach (NamedColor named in AsyncEnumerableAllColors())
            {
                AllColors.Add(new NamedColorsViewModel() { Name = named.Name, Color = 
                named.Color });
            }
        }

完整代码内容

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using NamedColorsDemoApp.Models;
using System.Collections.ObjectModel;
using System.Reflection;

namespace NamedColorsDemoApp.ViewModels
{
    partial class NamedColorsViewModel : ObservableObject
    {
        private NamedColor namedColor;

        [ObservableProperty]
        private static ObservableCollection<NamedColorsViewModel> allColors;       

        public string Name
        {
            get => namedColor.Name;
            set => SetProperty(namedColor.Name, value, namedColor, (n, v) => n.Name = v);
        }

        public Color Color
        {
            get => namedColor.Color;
            set => SetProperty(namedColor.Color, value, namedColor, (n, v) => n.Color = 
                   v);
        }
        

        public NamedColorsViewModel()
        {            
            namedColor = new NamedColor();            
        }

        static NamedColorsViewModel()
        {
            allColors = new ObservableCollection<NamedColorsViewModel>();            
        }

        private static async IAsyncEnumerable<NamedColor> AsyncEnumerableAllColors()
        {
            foreach (FieldInfo fieldInfo in typeof(Colors).GetRuntimeFields())
            {
                if ((fieldInfo.FieldType == typeof(Color)) && fieldInfo.IsPublic && 
                   fieldInfo.IsStatic)
                {
                    yield return new NamedColor { Color = 
                    (Color)fieldInfo.GetValue(null), Name = fieldInfo.Name };
                    await Task.Delay(10);
                }
            }
        }

        [RelayCommand]
        private async Task InitCollection()
        {
            AllColors.Clear();
            await foreach (NamedColor named in AsyncEnumerableAllColors())
            {
                AllColors.Add(new NamedColorsViewModel() { Name = named.Name, Color = 
                named.Color });
            }
        }
    }
}

在文件夹Views下视图文件NamedColorsPage.xaml,在这个文件内引用这些

xmlns:viewmodels="clr-namespace:NamedColorsDemoApp.ViewModels"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"

在这个页面上添加行为,目的是把Appearing事件绑定到InitCollectionCommand上,注意这个命令在viewmodel里是没有的,标注方法自动加上的,非常有意思,省力。

<ContentPage.Behaviors>
        <toolkit:EventToCommandBehavior EventName="Appearing" Command="{Binding 
         InitCollectionCommand}"/>
</ContentPage.Behaviors>

完整的页面内容,CollectionView.ItemsSource绑定的AllColors也是标注方法自动生成的。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewmodels="clr-namespace:NamedColorsDemoApp.ViewModels"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="NamedColorsDemoApp.Views.NamedColorsPage"
             Title="命名颜色">
    <ContentPage.Behaviors>
        <toolkit:EventToCommandBehavior EventName="Appearing" Command="{Binding 
         InitCollectionCommand}"/>
    </ContentPage.Behaviors>
    <ContentPage.Resources>
        <toolkit:ColorToHexRgbStringConverter x:Key="colorToRgbConverter"/>
        <toolkit:ColorToCmykStringConverter x:Key="colorToCMYKConverter"/>
    </ContentPage.Resources>
    <ContentPage.BindingContext>
        <viewmodels:NamedColorsViewModel/>
    </ContentPage.BindingContext>
    <Grid RowDefinitions="Auto,*" Margin="5" RowSpacing="5">
        <Label Text="{Binding AllColors.Count,StringFormat='命名颜色数:{0}'}" Padding="5" 
               BackgroundColor="DarkCyan" TextColor="White"/>
        <Border StrokeThickness="8" StrokeShape="RoundRectangle 20,20,0,40" Stroke=" 
               {Binding Color}" Padding="12" Grid.Row="1" BindingContext="{Binding 
               Source={x:Reference colorsCollection},Path=SelectedItem}">
            <CollectionView Grid.Row="1" ItemsSource="{Binding AllColors}" 
              SelectionMode="Single" x:Name="colorsCollection" BindingContext="{Binding 
              Source={RelativeSource AncestorLevel=1,AncestorType={x:Type ContentPage}
              },Path=BindingContext}">                
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Grid RowDefinitions="*,*,*" ColumnDefinitions="Auto,*" 
                         RowSpacing="5" ColumnSpacing="5">
                            <BoxView Color="{Binding Color}" WidthRequest="50" 
                              HeightRequest="50" Grid.RowSpan="3"/>
                            <Label Text="{Binding Name}" FontAttributes="Bold" 
                             VerticalOptions="Center" Grid.Column="1"/>
                            <Label Text="{Binding Color,Converter={x:StaticResource 
                             colorToRgbConverter},StringFormat='RGB={0}'}" 
                             VerticalOptions="Center" Grid.Row="1" Grid.Column="1"/>
                            <Label Text="{Binding Color,Converter={x:StaticResource 
                            colorToCMYKConverter}}" VerticalOptions="End" Grid.Row="2" 
                            Grid.Column="1"/>
                        </Grid>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </Border>
    </Grid>
</ContentPage>

Android下运行

Windows下运行 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值