当前位置: 首页 > news >正文

珠宝首饰商城网站建设莱芜人才网招聘网

珠宝首饰商城网站建设,莱芜人才网招聘网,国产免费crm系统有哪些在线,邯郸网站建设渠道前言写在.NET MAUI官宣正式发布之际#xff0c;热烈庆祝MAUI正式发布#xff01;去年12月份做了MAUI混合开发框架的调研#xff0c;想起来文章里给自己挖了个坑#xff0c;要教大家如何把Abp移植进Maui项目。熟悉Abp的同学都知道#xff0c;Abp 是一套强大的应用程序设计时… 前言写在.NET MAUI官宣正式发布之际热烈庆祝MAUI正式发布去年12月份做了MAUI混合开发框架的调研想起来文章里给自己挖了个坑要教大家如何把Abp移植进Maui项目。熟悉Abp的同学都知道Abp 是一套强大的应用程序设计时框架俗称脚手架新版本的Abp vNext为微服务和网络优化的更多然而本地开发经典Abp已经够用而且官方没有停止维护因此使用这个框架MAUI则是跨平台的应用程序抽象层强大的运行时框架 强大的设计时框架 我说这是宇宙最强大跨平台开发框架不为过吧计划整个程序我们还是利用Mvvm设计模式但是将利用Abp的Ioc容器而不使用mvvmlight或者xamarinToolkit这些库自行编写一个ViewModelBase使用Abp.EntityFrameworkCore库中的EF相关功能使用sqlite作为数据持久化方案。目标编写一个歌单App对歌曲信息进行增、删、查、改。下面来看看如何搭建搭建MAUI项目请注意本文发布时MAUI处于RC3版本仍没有正式发布需要安装Visual Studio 2022 17.3 (Preview)首先按照官方教程搭建一个MAUI项目 命名为MauiBoilerplateBuild your first .NET MAUI app - .NET MAUI | Microsoft Docs再前往Abp官网生成一个项目 Startup Templates - Create a Demo | AspNet Boilerplate选择最新版本 v7.x 和.Net 6版本取消勾选“Include login, register, user, role and tenant management pages”项目名称中填入MauiBoilerplate与Maui项目保持一致点击“Create My Project”生成abp项目文件等待下载完成下载解压好后打开src目录可以发现4个项目目录我们仅需要Core和EntityFrameworkCore项目将这两个目录移至项目根目录并且添加至解决方案。配置应用入口点在MauiBoilerplate.Core项目中改写默认配置文件{ConnectionStrings: {Default: Data Sourcefile:{0};},Logging: {IncludeScopes: false,LogLevel: {Default: Debug,System: Information,Microsoft: Information}} }在MauiBoilerplate.Core.csproj中的ItemGroup节点下添加EmbeddedResource Includeappsettings.jsonCopyToOutputDirectoryAlways/CopyToOutputDirectory/EmbeddedResource在MauiBoilerplate.Core项目中新建MauiBoilerplateBuilderExtensions.cs 作为程序入口添加一个静态方法InitConfig用于读取项目的配置文件appsettings.json若第一次运行或者该文件不存在则读取默认的配置文件private static void InitConfig(string logCfgName, string documentsPath){var assembly IntrospectionExtensions.GetTypeInfo(typeof(MauiBoilerplateBuilderExtensions)).Assembly;Stream stream assembly.GetManifestResourceStream($MauiBoilerplate.Core.{logCfgName});string text ;using (var reader new System.IO.StreamReader(stream)){text reader.ReadToEnd();}if (DirFileHelper.IsExistFile(documentsPath)){var currentFileContent DirFileHelper.ReadFile(documentsPath);var isSameContent currentFileContent.ToMd5() text.ToMd5();if (isSameContent){return;}DirFileHelper.CreateFile(documentsPath, text);}else{DirFileHelper.CreateFile(documentsPath, text);}}添加一个静态方法InitDataBase用于初始化sqlite数据库文件mato.dbprivate static void InitDataBase(string dbName, string documentsPath){var assembly IntrospectionExtensions.GetTypeInfo(typeof(MauiBoilerplateBuilderExtensions)).Assembly;Stream stream assembly.GetManifestResourceStream($MauiBoilerplate.Core.{dbName});StreamHelper.WriteStream(stream, documentsPath);var path Path.GetDirectoryName(documentsPath);DirFileHelper.CreateDir(path);}添加一个 静态方法UseMauiBoilerplate用于初始化配置文件初始化db文件和向管道服务中注册AbpBootstrapper实例。public static MauiAppBuilder UseMauiBoilerplateTStartupModule(this MauiAppBuilder builder) where TStartupModule : AbpModule{var logCfgName log4net.config;var appCfgName appsettings.json;var dbName mato.db;string documentsPath Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), MauiBoilerplateConsts.LocalizationSourceName, logCfgName);string documentsPath2 Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), MauiBoilerplateConsts.LocalizationSourceName, appCfgName);string dbPath Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), MauiBoilerplateConsts.LocalizationSourceName, dbName);InitConfig(logCfgName, documentsPath);InitConfig(appCfgName, documentsPath2);InitDataBase(dbName, dbPath);var _bootstrapper AbpBootstrapper.CreateTStartupModule(options {options.IocManager new IocManager();});_bootstrapper.IocManager.IocContainer.AddFacilityLoggingFacility(f f.UseAbpLog4Net().WithConfig(documentsPath));builder.Services.AddSingleton(_bootstrapper);WindsorRegistrationHelper.CreateServiceProvider(_bootstrapper.IocManager.IocContainer, builder.Services);return builder;}在MauiBoilerplate项目中新建MauiBoilerplateModule.cs 并编写代码如下这是App起始模块[DependsOn(typeof(MauiBoilerplateEntityFrameworkCoreModule))]public class MauiBoilerplateModule : AbpModule{public override void Initialize(){IocManager.RegisterAssemblyByConvention(typeof(MauiBoilerplateModule).GetAssembly());}}打开MauiProgram.cs文件将UseMauiBoilerplate添加到MauiAppBuilder这里提一下, MAUI 应用跟其他.Net6应用一样采用泛型主机启动应用在项目中有一个静态MauiProgram类这是应用的入口点。这提供了从单个位置配置应用、服务和第三方库的功能。更多泛型主机的信息请参阅微软文档.NET 通用主机 | Microsoft Docs 至此在主机管道中已经配置了MauiBoilerplate服务配置AbpApp.xaml是应用的声明起始点将从这里初始化Abp打开App.xaml.cs添加如下代码public partial class App : Application{private readonly AbpBootstrapper _abpBootstrapper;public App(AbpBootstrapper abpBootstrapper){_abpBootstrapper abpBootstrapper;InitializeComponent();_abpBootstrapper.Initialize();this.MainPage abpBootstrapper.IocManager.Resolve(typeof(MainPage)) as MainPage;}}注意我们还没有创建初始页面MainPage你可以先创建这个文件将在第三章讲UI层时介绍至此就完成了MAUI项目的搭建与Abp脚手架的集成现在你可以在这个项目中使用Abp的IocManagerConfigurationManager工作单元特性模组化特性等等任何的Abp提供的功能了。但是距离目标制作一个具有数据访问层的App还需要两段路要走配置数据库以及编写界面。因为我们要做一个数据持久化型的小应用所以在完成Abp功能的集成后我们需要做数据库相关的配置工作配置数据库在MauiBoilerplate.Core项目中添加两个实体类我们简单的写一个歌曲song的实体类其中包含了歌曲标题MusicTitle艺术家Artist专辑Album时长Duration以及发售日期ReleaseDatepublic class Song : FullAuditedEntitylong{[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]public override long Id { get; set; }public string MusicTitle { get; set; }public string Artist { get; set; }public string Album { get; set; }public TimeSpan Duration { get; set; }public DateTime ReleaseDate { get; set; }}在MauiBoilerplate.EntityFrameworkCore项目中将这个类添加至MauiBoilerplateDbContext中public class MauiBoilerplateDbContext : AbpDbContext {//Add DbSet properties for your entities...public DbSetSong Song { get; set; } } 新建WithDbContextHelper.cs创建一个静态类WithDbContext利用Abp的工作单元模式对dbcontext执行操作public class WithDbContextHelper{public static void WithDbContextTDbContext(IIocResolver iocResolver, ActionTDbContext contextAction)where TDbContext : DbContext{using (var uowManager iocResolver.ResolveAsDisposableIUnitOfWorkManager()){using (var uow uowManager.Object.Begin(TransactionScopeOption.Suppress)){var context uowManager.Object.Current.GetDbContextTDbContext();contextAction(context);uow.Complete();}}}}[可选]种子数据相关类编写编写种子数据帮助类SeedHelper.cs与数据库初始化类InitialDbBuilder这里将在程序启动时向数据库插入一些种子数据public static class SeedHelper{public static void SeedHostDb(IIocResolver iocResolver){Helper.WithDbContextHelper.WithDbContextMauiBoilerplateDbContext(iocResolver, SeedHostDb);}public static void SeedHostDb(MauiBoilerplateDbContext context){context.SuppressAutoSetTenantId true;// Host seednew InitialDbBuilder(context).Create();}}编写MauiBoilerplateEntityFrameworkCoreModule.cs[DependsOn(typeof(MauiBoilerplateCoreModule), typeof(AbpEntityFrameworkCoreModule))]public class MauiBoilerplateEntityFrameworkCoreModule : AbpModule{public bool SkipDbContextRegistration { get; set; }public bool SkipDbSeed { get; set; }public override void PreInitialize(){if (!SkipDbContextRegistration){Configuration.Modules.AbpEfCore().AddDbContextMauiBoilerplateDbContext(options {if (options.ExistingConnection ! null){DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ExistingConnection);}else{DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ConnectionString);}});}}public override void Initialize(){IocManager.RegisterAssemblyByConvention(typeof(MauiBoilerplateEntityFrameworkCoreModule).GetAssembly());}public override void PostInitialize(){Helper.WithDbContextHelper.WithDbContextMauiBoilerplateDbContext(IocManager, RunMigrate);if (!SkipDbSeed){SeedHelper.SeedHostDb(IocManager);}}public static void RunMigrate(MauiBoilerplateDbContext dbContext){dbContext.Database.Migrate();}}将MauiBoilerplate.EntityFrameworkCore设置为启动项目选择框架为.net6.0打开程序包管理器控制台选择默认项目MauiBoilerplate.EntityFrameworkCore编辑 运行Add-Migration命令将生成迁移脚本运行MauiBoilerplate.EntityFrameworkCore将生成mato.db等三个文件编辑编写基类可选我们在使用相关的父类时某某ContentPage或者某某UserControl时需要像使用AbpServiceBase一样使用一些常用的功能比如字符串的本地化配置AutoMapper对象等就像AbpServiceBase的注释里描述的那样    /// summary    /// This class can be used as a base class for services.    /// It has some useful objects property-injected and has some basic methods    /// most of services may need to.    /// /summary此时需要编写一个基类奈何.net本身没有Mixin模式C#语言也不支持多继承这些基类仅是注入了一些常用的Manager方便代码编写者使用因此基类的创建不是必须的。比如可以增加一个ContentPageBase类作为ContentPage实例控件的基类新建ContentPageBase.cs文件创建类ContentPageBase继承于ContentPagepublic class ContentPageBase : ContentPage{public IObjectMapper ObjectMapper { get; set; }/// summary/// Reference to the setting manager./// /summarypublic ISettingManager SettingManager { get; set; }/// summary/// Reference to the localization manager./// /summarypublic ILocalizationManager LocalizationManager { get; set; }/// summary/// Gets/sets name of the localization source that is used in this application service./// It must be set in order to use see crefL(string)/ and see crefL(string,CultureInfo)/ methods./// /summaryprotected string LocalizationSourceName { get; set; }/// summary/// Gets localization source./// Its valid if see crefLocalizationSourceName/ is set./// /summaryprotected ILocalizationSource LocalizationSource{get{if (LocalizationSourceName null){throw new AbpException(Must set LocalizationSourceName before, in order to get LocalizationSource);}if (_localizationSource null || _localizationSource.Name ! LocalizationSourceName){_localizationSource LocalizationManager.GetSource(LocalizationSourceName);}return _localizationSource;}}private ILocalizationSource _localizationSource;/// summary/// Constructor./// /summaryprotected ContentPageBase(){LocalizationSourceName MauiBoilerplateConsts.LocalizationSourceName;ObjectMapper NullObjectMapper.Instance;LocalizationManager NullLocalizationManager.Instance;}/// summary/// Gets localized string for given key name and current language./// /summary/// param namenameKey name/param/// returnsLocalized string/returnsprotected virtual string L(string name){return LocalizationSource.GetString(name);}/// summary/// Gets localized string for given key name and current language with formatting strings./// /summary/// param namenameKey name/param/// param nameargsFormat arguments/param/// returnsLocalized string/returnsprotected virtual string L(string name, params object[] args){return LocalizationSource.GetString(name, args);}/// summary/// Gets localized string for given key name and specified culture information./// /summary/// param namenameKey name/param/// param namecultureculture information/param/// returnsLocalized string/returnsprotected virtual string L(string name, CultureInfo culture){return LocalizationSource.GetString(name, culture);}/// summary/// Gets localized string for given key name and current language with formatting strings./// /summary/// param namenameKey name/param/// param namecultureculture information/param/// param nameargsFormat arguments/param/// returnsLocalized string/returnsprotected virtual string L(string name, CultureInfo culture, params object[] args){return LocalizationSource.GetString(name, culture, args);}}同理若我们使用了其他控件类时可以增加一个Base类作为实例控件的基类的比如Popup控件就编写一个PopupBase基类。在这里我们编写了两个基类编辑 本地化配置新建一个TranslateExtension.cs作为Xaml标签的本地化处理类[ContentProperty(Text)]public class TranslateExtension : DomainService, IMarkupExtension{public TranslateExtension(){LocalizationSourceName MauiBoilerplateConsts.LocalizationSourceName;}public string Text { get; set; }public object ProvideValue(IServiceProvider serviceProvider){if (Text null)return ;var translation L(Text); return translation;}}在MauiBoilerplateLocalization.cs配置好SourceFiles public static void Configure(ILocalizationConfiguration localizationConfiguration){localizationConfiguration.Sources.Add(new DictionaryBasedLocalizationSource(MauiBoilerplateConsts.LocalizationSourceName,new XmlEmbeddedFileLocalizationDictionaryProvider(typeof(LocalizationConfigurer).GetAssembly(),MauiBoilerplate.Core.Localization.SourceFiles)));}编写ViewModelBase为实现Mvvm设计模式页面需要绑定一个继承于ViewModelBase的类型在ViewModelBase中需要实现INotifyPropertyChanged以处理绑定成员变化时候的通知消息ViewModelBase集成于AbpServiceBase以方便ViewModel代码编写者使用常用的功能比如字符串的本地化配置AutoMapper对象等。public abstract class ViewModelBase : AbpServiceBase, ISingletonDependency, INotifyPropertyChanged{public ViewModelBase(){LocalizationSourceName MauiBoilerplateConsts.LocalizationSourceName;}public event PropertyChangedEventHandler PropertyChanged;protected PropertyChangedEventHandler PropertyChangedHandler { get; }public void VerifyPropertyName(string propertyName){Type type GetType();if (!string.IsNullOrEmpty(propertyName) type.GetTypeInfo().GetDeclaredProperty(propertyName) null)throw new ArgumentException(找不到属性, propertyName);}public virtual void RaisePropertyChanged([CallerMemberName] string propertyName null){PropertyChangedEventHandler propertyChanged PropertyChanged;if (propertyChanged null)return;propertyChanged(this, new PropertyChangedEventArgs(propertyName));}public virtual void RaisePropertyChangedT(ExpressionFuncT propertyExpression){if (PropertyChanged null)return;string propertyName GetPropertyName(propertyExpression);if (string.IsNullOrEmpty(propertyName))return;RaisePropertyChanged(propertyName);}protected static string GetPropertyNameT(ExpressionFuncT propertyExpression){if (propertyExpression null)throw new ArgumentNullException(nameof(propertyExpression));MemberExpression body propertyExpression.Body as MemberExpression;if (body null)throw new ArgumentException(参数不合法, nameof(propertyExpression));PropertyInfo member body.Member as PropertyInfo;if (member null)throw new ArgumentException(找不到属性, nameof(propertyExpression));return member.Name;}}至此我们完成了数据库的配置内容页基类与 ViewModel基类的编写接下来可以制作我们的页面了。 很开心终于到了创建页面的时候了我们需要两个页面MainPage 主页面MusicItemPage 条目编辑页面编写主页面 新建一个MainPageViewModel.cs作为MainPage的ViewModel层public class MainPageViewModel : ViewModelBase{private readonly IRepositorySong, long songRepository;public MainPageViewModel(IRepositorySong, long songRepository){this.RefreshCommandnew Command(Refresh, (o) true);this.DeleteCommandnew Command(Delete, (o) true);this.songRepositorysongRepository;}private void Delete(object obj){songRepository.Delete(obj as Song);}private async void Refresh(object obj){this.IsRefreshingtrue;var getSongs this.songRepository.GetAllListAsync();await getSongs.ContinueWith(r IsRefreshingfalse);var songs await getSongs;this.Songsnew ObservableCollectionSong(songs);}private ObservableCollectionSong songs;public ObservableCollectionSong Songs{get { return songs; }set{songs value;RaisePropertyChanged();}}private Song currentSong;public Song CurrentSong{get { return currentSong; }set{currentSong value;RaisePropertyChanged();}}private bool _isRefreshing;public bool IsRefreshing{get { return _isRefreshing; }set{_isRefreshing value;RaisePropertyChanged();}}public Command RefreshCommand { get; set; }public Command DeleteCommand { get; private set; }}新建一个MainPage页面编写Xaml为注意这个页面将继承MauiBoilerplate.ContentPageBase?xml version1.0 encodingutf-8 ? mato:ContentPageBase xmlnshttp://schemas.microsoft.com/dotnet/2021/mauixmlns:xhttp://schemas.microsoft.com/winfx/2009/xamlxmlns:matoclr-namespace:MauiBoilerplate;assemblyMauiBoilerplate.Corex:ClassMauiBoilerplate.MainPageGridGrid.RowDefinitionsRowDefinition Height155/RowDefinitionRowDefinition/RowDefinition/Grid.RowDefinitionsLabel TextMy Music FontSize65/LabelListView Grid.Row1ItemsSource{Binding Songs,ModeTwoWay}x:NameMainListViewRowHeight74 IsPullToRefreshEnabledTrueIsRefreshing{Binding IsRefreshing}RefreshCommand{Binding RefreshCommand}SelectedItem{Binding CurrentSong,ModeTwoWay}ListView.HeaderGrid HeightRequest96Grid.RowDefinitionsRowDefinition/RowDefinitionRowDefinition/RowDefinition/Grid.RowDefinitionsButton ClickedAddButton_ClickedCornerRadius100TextHeightRequest44WidthRequest200FontFamilyFontAwesome/ButtonStackLayout VerticalOptionsEndMargin0,0,0,8Grid.Row1HorizontalOptionsCenterOrientationHorizontalLabel HorizontalTextAlignmentCenterFontSizeSmall Text{Binding Songs.Count}/LabelLabel HorizontalTextAlignmentCenterFontSizeSmall Text首歌/Label/StackLayout/Grid/ListView.HeaderListView.ItemTemplateDataTemplateViewCellGrid x:NameModeControlLayout VerticalOptionsCenterAndExpandGrid.ColumnDefinitionsColumnDefinition Width* /ColumnDefinition WidthAuto //Grid.ColumnDefinitionsStackLayout Grid.Column0 HorizontalOptionsCenter VerticalOptionsCenterAndExpandLabel Text{Binding MusicTitle} HorizontalOptionsFillAndExpand HorizontalTextAlignmentCenter FontSizeBody /LabelText{Binding Artist} HorizontalOptionsFillAndExpand HorizontalTextAlignmentCenter FontSizeBody //StackLayoutButton x:NameMoreButtonHeightRequest44 WidthRequest44 Margin10TextClickedSongMoreButton_OnClickedFontFamilyFontAwesomeGrid.Column1 CornerRadius100HorizontalOptionsCenter //Grid/ViewCell/DataTemplate/ListView.ItemTemplate/ListView/Grid /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;public MainPage(MainPageViewModel mainPageViewModel, MusicItemPageViewModel musicItemPageViewModel, MusicItemPage musicItemPage){InitializeComponent();this.mainPageViewModelmainPageViewModel;this.musicItemPageViewModelmusicItemPageViewModel;this.musicItemPagemusicItemPage;BindingContextthis.mainPageViewModel;}protected override void OnAppearing(){base.OnAppearing();mainPageViewModel.RefreshCommand.Execute(null);}private async void SongMoreButton_OnClicked(object sender, EventArgs e){var currentsong (sender as BindableObject).BindingContext as Song;string action await DisplayActionSheet(currentsong.MusicTitle, 取消, null, 修改, 删除);if (action修改){musicItemPageViewModel.CurrentSong currentsong;await Navigation.PushModalAsync(musicItemPage);}else if (action删除){mainPageViewModel.DeleteCommand.Execute(currentsong);mainPageViewModel.RefreshCommand.Execute(null);}}private async void AddButton_Clicked(object sender, EventArgs e){musicItemPageViewModel.CurrentSong new Song();await Navigation.PushModalAsync(musicItemPage);} }此页面将显示一个列表并在列表条目下可以弹出一个菜单 编写条目编辑页面 新建一个MusicItemPageViewModel.cs作为MusicItemPage的ViewModel层public class MusicItemPageViewModel : ViewModelBase{private readonly IIocResolver iocResolver;private readonly IRepositorySong, long songRepository;public event EventHandler OnFinished;public MusicItemPageViewModel(IIocResolver iocResolver,IRepositorySong, long songRepository){this.CommitCommandnew Command(Commit, (o) CurrentSong!null);this.iocResolveriocResolver;this.songRepositorysongRepository;this.PropertyChangedMusicItemPageViewModel_PropertyChanged;}private void MusicItemPageViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e){if (e.PropertyNamenameof(CurrentSong)){CommitCommand.ChangeCanExecute();}}private void Commit(object obj){songRepository.InsertOrUpdate(currentSong); }private Song currentSong;public Song CurrentSong{get { return currentSong; }set{currentSong value;RaisePropertyChanged();}}}新建一个MusicItemPage 页面编写Xaml为注意这个页面将继承MauiBoilerplate.ContentPageBase?xml version1.0 encodingutf-8 ? mato:ContentPageBase xmlnshttp://schemas.microsoft.com/dotnet/2021/mauixmlns:xhttp://schemas.microsoft.com/winfx/2009/xamlxmlns:matoclr-namespace:MauiBoilerplate;assemblyMauiBoilerplate.Corex:ClassMauiBoilerplate.MusicItemPageGridGrid.RowDefinitionsRowDefinition/RowDefinitionRowDefinition Height155/RowDefinition/Grid.RowDefinitionsTableView IntentFormTableRootTableSection Title基础EntryCell Label标题 Text{Binding CurrentSong.MusicTitle, ModeTwoWay}/EntryCell Label艺术家 Text{Binding CurrentSong.Artist, ModeTwoWay}/EntryCell Label专辑 Text{Binding CurrentSong.Album, ModeTwoWay}//TableSectionTableSection Title其他EntryCell Label时长 Text{Binding CurrentSong.Duration}/EntryCell Label发布日期 Text{Binding CurrentSong.ReleaseDate}//TableSection/TableRoot/TableViewButton x:NameCommitButtonGrid.Row1CornerRadius100HeightRequest44WidthRequest200TextCommand{Binding CommitCommand}FontFamilyFontAwesome HorizontalOptionsCenter //Grid /mato:ContentPageBase 编写CodeBehind为注意将它继承ITransientDependency接口public partial class MusicItemPage : ContentPageBase, ITransientDependency {private readonly MusicItemPageViewModel musicItemPageViewModel;public MusicItemPage(MusicItemPageViewModel musicItemPageViewModel){InitializeComponent();this.musicItemPageViewModelmusicItemPageViewModel;this.musicItemPageViewModel.OnValidateErrorsMusicItemPageViewModel_OnValidateErrors;this.musicItemPageViewModel.OnFinishedMusicItemPageViewModel_OnFinished;BindingContextthis.musicItemPageViewModel;UnloadedMusicItemPage_Unloaded;}private async void MusicItemPageViewModel_OnFinished(object sender, EventArgs e){await this.Navigation.PopModalAsync();}private void MusicItemPage_Unloaded(object sender, EventArgs e){musicItemPageViewModel.CurrentSong null;}private async void MusicItemPageViewModel_OnValidateErrors(object sender, ListSystem.ComponentModel.DataAnnotations.ValidationResult e){var content string.Join(,, e);await DisplayAlert(请注意, content, 好的);} }这个页面提供歌曲条目新增和编辑的交互功能[可选]使用Abp校验数据功能这个部分使用Abp的ValidationConfiguration功能校验表单数据以展示Abp功能的使用首先在MusicItemPageViewModel 构造函数中添加对IValidationConfiguration对象的注入编辑 添加OnValidateErrors事件并且在Page中订阅这个事件。此事件将在校验未通过时触发MusicItemPageViewModel.cs中public event EventHandlerListValidationResult OnValidateErrors; MusicItemPage.xaml.cs中this.musicItemPageViewModel.OnValidateErrorsMusicItemPageViewModel_OnValidateErrors;private async void MusicItemPageViewModel_OnValidateErrors(object sender, ListSystem.ComponentModel.DataAnnotations.ValidationResult e){var content string.Join(,, e);await DisplayAlert(请注意, content, 好的);}编写校验逻辑代码MusicItemPageViewModel.cs中protected ListValidationResult GetValidationErrors(Song validatingObject){ListValidationResult validationErrors new ListValidationResult();foreach (var validatorType in _configuration.Validators){using (var validator iocResolver.ResolveAsDisposableIMethodParameterValidator(validatorType)){var validationResults validator.Object.Validate(validatingObject);validationErrors.AddRange(validationResults);}}return validationErrors;}Commit提交方法改造如下当GetValidationErrors返回的校验错误列表中有内容时将OnValidateErrors事件Invokeprivate void Commit(object obj){var validateErrors GetValidationErrors(this.CurrentSong);if (validateErrors.Count0){songRepository.InsertOrUpdate(currentSong);this.OnFinished?.Invoke(this, EventArgs.Empty);}else{OnValidateErrors?.Invoke(this, validateErrors);}}接下来在实体中定义校验规则校验器将按照这些规则返回校验结果public class Song : FullAuditedEntitylong, IValidatableObject{[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]public override long Id { get; set; }[Required][StringLength(6, ErrorMessage 歌曲名称要在6个字以内)]public string MusicTitle { get; set; }[Required][StringLength(10, ErrorMessage 歌曲名称要在10个字以内)]public string Artist { get; set; }[Required][StringLength(10, ErrorMessage 歌曲名称要在10个字以内)]public string Album { get; set; }public TimeSpan Duration { get; set; }public DateTime ReleaseDate { get; set; }public IEnumerableValidationResult Validate(ValidationContext validationContext){if (ReleaseDate ! default ReleaseDateDateTime.Now){yield return new ValidationResult(ReleaseDate不能大于当天,new[] { nameof(ReleaseDate) });}}}运行新建条目。当我们如下填写的时候将会弹出提示框iOS平台也测试通过 至此我们完成了所有的工作。结束语Abp是一个很好用的.Net开发框架Abp库帮助我们抽象了整个项目以及更多的设计模式应用虽然有一个Asp在其中但其功能不仅仅可以构建AspNet Core应用经过我们的探索用Abp构建了跨平台应用同样它还可以用于XamarinWpf甚至是WinForms这些基于桌面的应用。欢迎参与讨论和转发。 项目地址jevonsflash/maui-abp-sample (github.com)
http://www.sadfv.cn/news/359525/

相关文章:

  • 用python语言做网站discuz轻社区模板
  • html做网站步骤手机网站怎么写
  • 自己做内部网站网络品牌营销方案
  • 太原百度seo网站建设宁波seo优化报价多少
  • 常熟做网站的社交网站怎么制作
  • 怎么做网站记者网站网站代理怎么做的
  • 网站建设项目功能需求分析报告开发公司成本管控
  • 做网站的 书籍营销型网站建设的好处
  • 定西市小企业网站建设建设推荐广州微信网站建设
  • 微网站怎么用明年做那个网站致富
  • 教育培训网站建设ppt心理咨询网站
  • 衡水市网站建设嘉兴网站建设全包
  • 广州哪家网站建设服务好长沙县工程建设质监站网站
  • iapp网站做软件教程动漫制作专业一个月多少钱
  • 网站建设哪家合适网站集群建设解决方案
  • o2o商城分销网站开发广东室内设计学校
  • 企业网站的制作原则圣象分销系统
  • 泉州网页模板建站微信应用小程序
  • 网站建设seo推广网站建设基础与实践
  • 用视频做网站背景wordpress阅读数 显示k
  • 美团网站制作的特色wordpress大前端破解
  • 中山营销型网站设计网站风格下载
  • 网站建设英语网页设计与制作精品课程网站
  • 如何验证网站所有权搜索引擎查重
  • 网站建设 教学视频上海网站建设品牌
  • 上市公司网站建设评价建设一个网站平台的费用吗
  • 工信部个人备案网站可信吗宝安网站建设公司
  • 这个网站做海外推广wordpress简单论坛
  • 建设一个跟京东一样的网站肇庆关键词网站排名
  • 制作软件网站中国企业报集团简介