将Abp移植进.NET MAUI项目(三):构建UI层

 很开心,终于到了创建页面的时候了!

我们需要两个页面

  • MainPage 主页面
  • MusicItemPage 条目编辑页面

编写主页面

 新建一个MainPageViewModel.cs,作为MainPage的ViewModel层

    public class MainPageViewModel : ViewModelBase
    {
        private readonly IRepository<Song, long> songRepository;

    <span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">MainPageViewModel(<span class="hljs-params">IRepository&lt;Song, <span class="hljs-built_in">long&gt; songRepository)
    {
        <span class="hljs-keyword">this.RefreshCommand=<span class="hljs-keyword">new Command(Refresh, (o) =&gt; <span class="hljs-literal">true);
        <span class="hljs-keyword">this.DeleteCommand=<span class="hljs-keyword">new Command(Delete, (o) =&gt; <span class="hljs-literal">true);
        <span class="hljs-keyword">this.songRepository=songRepository;

    }
    <span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">void <span class="hljs-title">Delete(<span class="hljs-params"><span class="hljs-built_in">object obj)
    {
        songRepository.Delete(obj <span class="hljs-keyword">as Song);
    }
    <span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">async <span class="hljs-keyword">void <span class="hljs-title">Refresh(<span class="hljs-params"><span class="hljs-built_in">object obj)
    {
        <span class="hljs-keyword">this.IsRefreshing=<span class="hljs-literal">true;
        <span class="hljs-keyword">var getSongs = <span class="hljs-keyword">this.songRepository.GetAllListAsync();
        <span class="hljs-keyword">await getSongs.ContinueWith(r =&gt; IsRefreshing=<span class="hljs-literal">false);
        <span class="hljs-keyword">var songs = <span class="hljs-keyword">await getSongs;
        <span class="hljs-keyword">this.Songs=<span class="hljs-keyword">new ObservableCollection&lt;Song&gt;(songs);
    }

    <span class="hljs-keyword">private ObservableCollection&lt;Song&gt; songs;

    <span class="hljs-keyword">public ObservableCollection&lt;Song&gt; Songs
    {
        <span class="hljs-keyword">get { <span class="hljs-keyword">return songs; }
        <span class="hljs-keyword">set
        {
            songs = <span class="hljs-keyword">value;
            RaisePropertyChanged();
        }
    }

    <span class="hljs-keyword">private Song currentSong;

    <span class="hljs-keyword">public Song CurrentSong
    {
        <span class="hljs-keyword">get { <span class="hljs-keyword">return currentSong; }
        <span class="hljs-keyword">set
        {
            currentSong = <span class="hljs-keyword">value;
            RaisePropertyChanged();
        }
    }

    <span class="hljs-keyword">private <span class="hljs-built_in">bool _isRefreshing;

    <span class="hljs-keyword">public <span class="hljs-built_in">bool IsRefreshing
    {
        <span class="hljs-keyword">get { <span class="hljs-keyword">return _isRefreshing; }
        <span class="hljs-keyword">set
        {
            _isRefreshing = <span class="hljs-keyword">value;
            RaisePropertyChanged();

        }
    }
    <span class="hljs-keyword">public Command RefreshCommand { <span class="hljs-keyword">get; <span class="hljs-keyword">set; }
    <span class="hljs-keyword">public Command DeleteCommand { <span class="hljs-keyword">get; <span class="hljs-keyword">private <span class="hljs-keyword">set; }
}

新建一个MainPage页面

编写Xaml为:

注意这个页面将继承MauiBoilerplate.ContentPageBase

<?xml version="1.0" encoding="utf-8" ?>
<mato:ContentPageBase xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mato="clr-namespace:MauiBoilerplate;assembly=MauiBoilerplate.Core"
             x:Class="MauiBoilerplate.MainPage">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="155"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

    <span class="hljs-tag">&lt;<span class="hljs-name">Label <span class="hljs-attr">Text=<span class="hljs-string">"My Music" <span class="hljs-attr">FontSize=<span class="hljs-string">"65"&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">Label&gt;
    <span class="hljs-tag">&lt;<span class="hljs-name">ListView 
            <span class="hljs-attr">Grid.Row=<span class="hljs-string">"1"
            <span class="hljs-attr">ItemsSource=<span class="hljs-string">"{Binding Songs,Mode=TwoWay}"
            <span class="hljs-attr">x:Name=<span class="hljs-string">"MainListView"
            <span class="hljs-attr">RowHeight=<span class="hljs-string">"74" 
            <span class="hljs-attr">IsPullToRefreshEnabled=<span class="hljs-string">"True"
            <span class="hljs-attr">IsRefreshing=<span class="hljs-string">"{Binding IsRefreshing}"
            <span class="hljs-attr">RefreshCommand=<span class="hljs-string">"{Binding RefreshCommand}"
            <span class="hljs-attr">SelectedItem=<span class="hljs-string">"{Binding CurrentSong,Mode=TwoWay}"&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">ListView.Header&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">Grid <span class="hljs-attr">HeightRequest=<span class="hljs-string">"96"&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">Grid.RowDefinitions&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">RowDefinition&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">RowDefinition&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">RowDefinition&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">RowDefinition&gt;
                <span class="hljs-tag">&lt;/<span class="hljs-name">Grid.RowDefinitions&gt;


                <span class="hljs-tag">&lt;<span class="hljs-name">Button <span class="hljs-attr">Clicked=<span class="hljs-string">"AddButton_Clicked"
                        <span class="hljs-attr">CornerRadius=<span class="hljs-string">"100"
                        <span class="hljs-attr">Text=<span class="hljs-string">""
                        <span class="hljs-attr">HeightRequest=<span class="hljs-string">"44"
                        <span class="hljs-attr">WidthRequest=<span class="hljs-string">"200"
                        <span class="hljs-attr">FontFamily=<span class="hljs-string">"FontAwesome"
                            &gt;<span class="hljs-tag">&lt;/<span class="hljs-name">Button&gt;


                <span class="hljs-tag">&lt;<span class="hljs-name">StackLayout <span class="hljs-attr">VerticalOptions=<span class="hljs-string">"End"
                             <span class="hljs-attr">Margin=<span class="hljs-string">"0,0,0,8"
                             <span class="hljs-attr">Grid.Row=<span class="hljs-string">"1"
                             <span class="hljs-attr">HorizontalOptions=<span class="hljs-string">"Center"
                             <span class="hljs-attr">Orientation=<span class="hljs-string">"Horizontal"&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Label <span class="hljs-attr">HorizontalTextAlignment=<span class="hljs-string">"Center"
                        <span class="hljs-attr">FontSize=<span class="hljs-string">"Small" 
                        <span class="hljs-attr">Text=<span class="hljs-string">"{Binding Songs.Count}"&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">Label&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Label  <span class="hljs-attr">HorizontalTextAlignment=<span class="hljs-string">"Center"
                        <span class="hljs-attr">FontSize=<span class="hljs-string">"Small" 
                        <span class="hljs-attr">Text=<span class="hljs-string">"首歌"&gt;<span class="hljs-tag">&lt;/<span class="hljs-name">Label&gt;

                <span class="hljs-tag">&lt;/<span class="hljs-name">StackLayout&gt;
            <span class="hljs-tag">&lt;/<span class="hljs-name">Grid&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">ListView.Header&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">ListView.ItemTemplate&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">DataTemplate&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">ViewCell&gt;
                    <span class="hljs-tag">&lt;<span class="hljs-name">Grid <span class="hljs-attr">x:Name=<span class="hljs-string">"ModeControlLayout" 
                          <span class="hljs-attr">VerticalOptions=<span class="hljs-string">"CenterAndExpand"&gt;
                        <span class="hljs-tag">&lt;<span class="hljs-name">Grid.ColumnDefinitions&gt;
                            <span class="hljs-tag">&lt;<span class="hljs-name">ColumnDefinition <span class="hljs-attr">Width=<span class="hljs-string">"*" /&gt;
                            <span class="hljs-tag">&lt;<span class="hljs-name">ColumnDefinition <span class="hljs-attr">Width=<span class="hljs-string">"Auto" /&gt;
                        <span class="hljs-tag">&lt;/<span class="hljs-name">Grid.ColumnDefinitions&gt;


                        <span class="hljs-tag">&lt;<span class="hljs-name">StackLayout <span class="hljs-attr">Grid.Column=<span class="hljs-string">"0" 
                                         <span class="hljs-attr">HorizontalOptions=<span class="hljs-string">"Center" 
                                         <span class="hljs-attr">VerticalOptions=<span class="hljs-string">"CenterAndExpand"&gt;
                            <span class="hljs-tag">&lt;<span class="hljs-name">Label 
                                <span class="hljs-attr">Text=<span class="hljs-string">"{Binding MusicTitle}"                                    
                                <span class="hljs-attr">HorizontalOptions=<span class="hljs-string">"FillAndExpand" 
                                <span class="hljs-attr">HorizontalTextAlignment=<span class="hljs-string">"Center" 
                                <span class="hljs-attr">FontSize=<span class="hljs-string">"Body" 
                                /&gt;
                            <span class="hljs-tag">&lt;<span class="hljs-name">Label
                                <span class="hljs-attr">Text=<span class="hljs-string">"{Binding Artist}" 
                                <span class="hljs-attr">HorizontalOptions=<span class="hljs-string">"FillAndExpand" 
                                <span class="hljs-attr">HorizontalTextAlignment=<span class="hljs-string">"Center" 
                                <span class="hljs-attr">FontSize=<span class="hljs-string">"Body" 
                                /&gt;
                        <span class="hljs-tag">&lt;/<span class="hljs-name">StackLayout&gt;
                        <span class="hljs-tag">&lt;<span class="hljs-name">Button 
                            <span class="hljs-attr">x:Name=<span class="hljs-string">"MoreButton"
                            <span class="hljs-attr">HeightRequest=<span class="hljs-string">"44" 
                            <span class="hljs-attr">WidthRequest=<span class="hljs-string">"44" 
                            <span class="hljs-attr">Margin=<span class="hljs-string">"10"
                            <span class="hljs-attr">Text=<span class="hljs-string">""
                            <span class="hljs-attr">Clicked=<span class="hljs-string">"SongMoreButton_OnClicked"
                            <span class="hljs-attr">FontFamily=<span class="hljs-string">"FontAwesome"
                            <span class="hljs-attr">Grid.Column=<span class="hljs-string">"1" 
                            <span class="hljs-attr">CornerRadius=<span class="hljs-string">"100"
                            <span class="hljs-attr">HorizontalOptions=<span class="hljs-string">"Center" /&gt;

                    <span class="hljs-tag">&lt;/<span class="hljs-name">Grid&gt;

                <span class="hljs-tag">&lt;/<span class="hljs-name">ViewCell&gt;
            <span class="hljs-tag">&lt;/<span class="hljs-name">DataTemplate&gt;
        <span class="hljs-tag">&lt;/<span class="hljs-name">ListView.ItemTemplate&gt;
    <span class="hljs-tag">&lt;/<span class="hljs-name">ListView&gt;
<span class="hljs-tag">&lt;/<span class="hljs-name">Grid&gt;

</mato:ContentPageBase>

 编写CodeBehind为:

注意将它继承ITransientDependency接口

这个页面之前提到过,已经通过IocManager.Resolve(typeof(MainPage))解析出实例并赋值给App.MainPage了。

public partial class MainPage : ContentPageBase, ITransientDependency
{
    private readonly MainPageViewModel mainPageViewModel;
    private readonly MusicItemPageViewModel musicItemPageViewModel;
    private readonly MusicItemPage musicItemPage;

<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">MainPage(<span class="hljs-params">MainPageViewModel mainPageViewModel, MusicItemPageViewModel musicItemPageViewModel, MusicItemPage musicItemPage)
{
    InitializeComponent();
    <span class="hljs-keyword">this.mainPageViewModel=mainPageViewModel;
    <span class="hljs-keyword">this.musicItemPageViewModel=musicItemPageViewModel;
    <span class="hljs-keyword">this.musicItemPage=musicItemPage;
    BindingContext=<span class="hljs-keyword">this.mainPageViewModel;
   
}

<span class="hljs-function"><span class="hljs-keyword">protected <span class="hljs-keyword">override <span class="hljs-keyword">void <span class="hljs-title">OnAppearing()
{
    <span class="hljs-keyword">base.OnAppearing();
    mainPageViewModel.RefreshCommand.Execute(<span class="hljs-literal">null);

}

<span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">async <span class="hljs-keyword">void <span class="hljs-title">SongMoreButton_OnClicked(<span class="hljs-params"><span class="hljs-built_in">object sender, EventArgs e)
{
    <span class="hljs-keyword">var currentsong = (sender <span class="hljs-keyword">as BindableObject).BindingContext <span class="hljs-keyword">as Song;
    <span class="hljs-built_in">string action = <span class="hljs-keyword">await DisplayActionSheet(currentsong.MusicTitle, <span class="hljs-string">"取消", <span class="hljs-literal">null, <span class="hljs-string">"修改", <span class="hljs-string">"删除");
    <span class="hljs-keyword">if (action==<span class="hljs-string">"修改")
    {
        musicItemPageViewModel.CurrentSong  = currentsong;
        <span class="hljs-keyword">await Navigation.PushModalAsync(musicItemPage);
    }
    <span class="hljs-keyword">else <span class="hljs-keyword">if (action==<span class="hljs-string">"删除")
    {
        mainPageViewModel.DeleteCommand.Execute(currentsong);
        mainPageViewModel.RefreshCommand.Execute(<span class="hljs-literal">null);
    }
}

<span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">async <span class="hljs-keyword">void <span class="hljs-title">AddButton_Clicked(<span class="hljs-params"><span class="hljs-built_in">object sender, EventArgs e)
{
    musicItemPageViewModel.CurrentSong  = <span class="hljs-keyword">new Song();
    <span class="hljs-keyword">await Navigation.PushModalAsync(musicItemPage);
}

}

此页面将显示一个列表,并在列表条目下可以弹出一个菜单

 

 编写条目编辑页面

 新建一个MusicItemPageViewModel.cs,作为MusicItemPage的ViewModel层

 public class MusicItemPageViewModel : ViewModelBase
 {
        private readonly IIocResolver iocResolver;
        private readonly IRepository<Song, long> songRepository;

    <span class="hljs-keyword">public <span class="hljs-keyword">event EventHandler OnFinished;

    <span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">MusicItemPageViewModel(<span class="hljs-params">
        IIocResolver iocResolver,
        IRepository&lt;Song, <span class="hljs-built_in">long&gt; songRepository)
    {
        <span class="hljs-keyword">this.CommitCommand=<span class="hljs-keyword">new Command(Commit, (o) =&gt; CurrentSong!=<span class="hljs-literal">null);
        <span class="hljs-keyword">this.iocResolver=iocResolver;
        <span class="hljs-keyword">this.songRepository=songRepository;
        <span class="hljs-keyword">this.PropertyChanged+=MusicItemPageViewModel_PropertyChanged;
    }

    <span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">void <span class="hljs-title">MusicItemPageViewModel_PropertyChanged(<span class="hljs-params"><span class="hljs-built_in">object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        <span class="hljs-keyword">if (e.PropertyName==<span class="hljs-keyword">nameof(CurrentSong))
        {
            CommitCommand.ChangeCanExecute();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">void <span class="hljs-title">Commit(<span class="hljs-params"><span class="hljs-built_in">object obj)
    {
        songRepository.InsertOrUpdate(currentSong);       
    }

    <span class="hljs-keyword">private Song currentSong;

    <span class="hljs-keyword">public Song CurrentSong
    {
        <span class="hljs-keyword">get { <span class="hljs-keyword">return currentSong; }
        <span class="hljs-keyword">set
        {
            currentSong = <span class="hljs-keyword">value;
            RaisePropertyChanged();
        }
    }

}

新建一个MusicItemPage 页面

编写Xaml为:

注意这个页面将继承MauiBoilerplate.ContentPageBase

<?xml version="1.0" encoding="utf-8" ?>
<mato:ContentPageBase xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mato="clr-namespace:MauiBoilerplate;assembly=MauiBoilerplate.Core"
             x:Class="MauiBoilerplate.MusicItemPage">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="155"></RowDefinition>
        </Grid.RowDefinitions>
        <TableView Intent="Form">
            <TableRoot>
                <TableSection Title="基础">
                    <EntryCell Label="标题"   Text="{Binding CurrentSong.MusicTitle, Mode=TwoWay}"/>
                    <EntryCell  Label="艺术家"  Text="{Binding CurrentSong.Artist, Mode=TwoWay}"/>
                    <EntryCell  Label="专辑"  Text="{Binding CurrentSong.Album, Mode=TwoWay}"/>

            <span class="hljs-tag">&lt;/<span class="hljs-name">TableSection&gt;
            <span class="hljs-tag">&lt;<span class="hljs-name">TableSection <span class="hljs-attr">Title=<span class="hljs-string">"其他"&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">EntryCell  <span class="hljs-attr">Label=<span class="hljs-string">"时长"  <span class="hljs-attr">Text=<span class="hljs-string">"{Binding CurrentSong.Duration}"/&gt;
                <span class="hljs-tag">&lt;<span class="hljs-name">EntryCell  <span class="hljs-attr">Label=<span class="hljs-string">"发布日期"  <span class="hljs-attr">Text=<span class="hljs-string">"{Binding CurrentSong.ReleaseDate}"/&gt;
            <span class="hljs-tag">&lt;/<span class="hljs-name">TableSection&gt;

        <span class="hljs-tag">&lt;/<span class="hljs-name">TableRoot&gt;
    <span class="hljs-tag">&lt;/<span class="hljs-name">TableView&gt;
    <span class="hljs-tag">&lt;<span class="hljs-name">Button <span class="hljs-attr">x:Name=<span class="hljs-string">"CommitButton"
            <span class="hljs-attr">Grid.Row=<span class="hljs-string">"1"
            <span class="hljs-attr">CornerRadius=<span class="hljs-string">"100"
            <span class="hljs-attr">HeightRequest=<span class="hljs-string">"44"
            <span class="hljs-attr">WidthRequest=<span class="hljs-string">"200"
            <span class="hljs-attr">Text=<span class="hljs-string">""
            <span class="hljs-attr">Command=<span class="hljs-string">"{Binding CommitCommand}"
            <span class="hljs-attr">FontFamily=<span class="hljs-string">"FontAwesome"             
            <span class="hljs-attr">HorizontalOptions=<span class="hljs-string">"Center" /&gt;
<span class="hljs-tag">&lt;/<span class="hljs-name">Grid&gt;

</mato:ContentPageBase>

 编写CodeBehind为:

注意将它继承ITransientDependency接口

public partial class MusicItemPage : ContentPageBase, ITransientDependency
{
    private readonly MusicItemPageViewModel musicItemPageViewModel;

<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">MusicItemPage(<span class="hljs-params">MusicItemPageViewModel musicItemPageViewModel)
{
    InitializeComponent();
    <span class="hljs-keyword">this.musicItemPageViewModel=musicItemPageViewModel;
    <span class="hljs-keyword">this.musicItemPageViewModel.OnValidateErrors+=MusicItemPageViewModel_OnValidateErrors;
    <span class="hljs-keyword">this.musicItemPageViewModel.OnFinished+=MusicItemPageViewModel_OnFinished;
    BindingContext=<span class="hljs-keyword">this.musicItemPageViewModel;
    Unloaded+=MusicItemPage_Unloaded;
}

<span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">async <span class="hljs-keyword">void <span class="hljs-title">MusicItemPageViewModel_OnFinished(<span class="hljs-params"><span class="hljs-built_in">object sender, EventArgs e)
{
   <span class="hljs-keyword">await <span class="hljs-keyword">this.Navigation.PopModalAsync();
}

<span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">void <span class="hljs-title">MusicItemPage_Unloaded(<span class="hljs-params"><span class="hljs-built_in">object sender, EventArgs e)
{
    musicItemPageViewModel.CurrentSong = <span class="hljs-literal">null;
}

<span class="hljs-function"><span class="hljs-keyword">private <span class="hljs-keyword">async <span class="hljs-keyword">void <span class="hljs-title">MusicItemPageViewModel_OnValidateErrors(<span class="hljs-params"><span class="hljs-built_in">object sender, List&lt;System.ComponentModel.DataAnnotations.ValidationResult&gt; e)
{
    <span class="hljs-keyword">var content = <span class="hljs-built_in">string.Join(<span class="hljs-string">',', e);
    <span class="hljs-keyword">await DisplayAlert(<span class="hljs-string">"请注意", content, <span class="hljs-string">"好的");
}

}

这个页面提供歌曲条目新增和编辑的交互功能

 

[可选]使用Abp校验数据功能

这个部分使用Abp的ValidationConfiguration功能校验表单数据,以展示Abp功能的使用

首先在MusicItemPageViewModel 构造函数中添加对IValidationConfiguration对象的注入

 添加OnValidateErrors事件,并且在Page中订阅这个事件。此事件将在校验未通过时触发

MusicItemPageViewModel.cs中:

public event EventHandler<List<ValidationResult>> OnValidateErrors;

 MusicItemPage.xaml.cs中:

        this.musicItemPageViewModel.OnValidateErrors+=MusicItemPageViewModel_OnValidateErrors;
    private async void MusicItemPageViewModel_OnValidateErrors(object sender, List<System.ComponentModel.DataAnnotations.ValidationResult> e)
    {
        var content = string.Join(',', e);
        await DisplayAlert("请注意", content, "好的");
    }

编写校验逻辑代码

MusicItemPageViewModel.cs中:

        protected List<ValidationResult> GetValidationErrors(Song validatingObject)
        {
            List<ValidationResult> validationErrors = new List<ValidationResult>();

        <span class="hljs-keyword">foreach (<span class="hljs-keyword">var validatorType <span class="hljs-keyword">in _configuration.Validators)
        {
            <span class="hljs-keyword">using (<span class="hljs-keyword">var validator = iocResolver.ResolveAsDisposable&lt;IMethodParameterValidator&gt;(validatorType))
            {
                <span class="hljs-keyword">var validationResults = validator.Object.Validate(validatingObject);
                validationErrors.AddRange(validationResults);
            }

        }
        <span class="hljs-keyword">return validationErrors;
    }

Commit提交方法,改造如下:

当GetValidationErrors返回的校验错误列表中有内容时,将OnValidateErrors事件Invoke

        private void Commit(object obj)
        {
            var validateErrors = GetValidationErrors(this.CurrentSong);
            if (validateErrors.Count==0)
            {
                songRepository.InsertOrUpdate(currentSong);
                this.OnFinished?.Invoke(this, EventArgs.Empty);

        }
        <span class="hljs-keyword">else
        {
            OnValidateErrors?.Invoke(<span class="hljs-keyword">this, validateErrors);
        }
    }</span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>

接下来在实体中定义校验规则,校验器将按照这些规则返回校验结果

    public class Song : FullAuditedEntity<long>, IValidatableObject
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public override long Id { get; set; }

    [<span class="hljs-meta">Required]
    [<span class="hljs-meta">StringLength(6, ErrorMessage = <span class="hljs-string">"歌曲名称要在6个字以内")]
    <span class="hljs-keyword">public <span class="hljs-built_in">string MusicTitle { <span class="hljs-keyword">get; <span class="hljs-keyword">set; }

    [<span class="hljs-meta">Required]
    [<span class="hljs-meta">StringLength(10, ErrorMessage = <span class="hljs-string">"歌曲名称要在10个字以内")]
    <span class="hljs-keyword">public <span class="hljs-built_in">string Artist { <span class="hljs-keyword">get; <span class="hljs-keyword">set; }

    [<span class="hljs-meta">Required]
    [<span class="hljs-meta">StringLength(10, ErrorMessage = <span class="hljs-string">"歌曲名称要在10个字以内")]
    <span class="hljs-keyword">public <span class="hljs-built_in">string Album { <span class="hljs-keyword">get; <span class="hljs-keyword">set; }

    <span class="hljs-keyword">public TimeSpan Duration { <span class="hljs-keyword">get; <span class="hljs-keyword">set; }
    <span class="hljs-keyword">public DateTime ReleaseDate { <span class="hljs-keyword">get; <span class="hljs-keyword">set; }

    <span class="hljs-function"><span class="hljs-keyword">public IEnumerable&lt;ValidationResult&gt; <span class="hljs-title">Validate(<span class="hljs-params">ValidationContext validationContext)
    {
        <span class="hljs-keyword">if (ReleaseDate != <span class="hljs-literal">default &amp;&amp; ReleaseDate&gt;DateTime.Now)
        {
            <span class="hljs-function"><span class="hljs-keyword">yield <span class="hljs-keyword">return <span class="hljs-keyword">new <span class="hljs-title">ValidationResult(<span class="hljs-params"><span class="hljs-string">"ReleaseDate不能大于当天",
                              <span class="hljs-keyword">new[] { <span class="hljs-keyword">nameof(ReleaseDate) });
        }

    }
}

运行,新建条目。当我们如下填写的时候,将会弹出提示框

iOS平台也测试通过 

 

 

至此我们完成了所有的工作。

结束语

Abp是一个很好用的.Net开发框架,Abp库帮助我们抽象了整个项目以及更多的设计模式应用,其名称Asp Boilerplate,虽然有一个Asp在其中,但其功能不仅仅可以构建AspNet Core应用,

经过我们的探索用Abp构建了跨平台应用,同样它还可以用于Xamarin,Wpf甚至是WinForms这些基于桌面的应用。

欢迎参与讨论和转发。

项目地址

jevonsflash/maui-abp-sample (github.com)

将Abp移植进.NET MAUI项目(三):构建UI层

https://blog.matoapp.net/posts/ab7a5062/

作者

林晓lx

发布于

2022-05-25

更新于

2024-09-11

许可协议

评论