制作微信网站模板,网站建设公司如何规避风险,建筑招聘网站有哪些,单位做网站的目的我们继续上一个案例#xff0c;实现一个可以修改当前用户信息功能。 当用户点击某个信息时#xff0c;跳转到信息详情页#xff0c;然后可以点击编辑按钮导航到编辑页面。 创建项目 我们首先在ViewModels目录下创建UserDetailViewModel。 实现从详情信息页面导航到编辑页面… 我们继续上一个案例实现一个可以修改当前用户信息功能。 当用户点击某个信息时跳转到信息详情页然后可以点击编辑按钮导航到编辑页面。
创建项目 我们首先在ViewModels目录下创建UserDetailViewModel。 实现从详情信息页面导航到编辑页面。 这里要使用一个字典来传输对象。
public partial class UserDetailViewModel:ObservableObject,IQueryAttributable
{[ObservableProperty] private User itemUser;public FuncUser, Task ParentRefreshAction { get;set; }[RelayCommand]async Task ShowEditFormAsync(){var context new UserContext();var editedItem context.Users.FirstOrDefault(u u.Id ItemUser.Id);await Shell.Current.GoToAsync(nameof(UserEditPage),parameters: new Dictionarystring, object{{ ParentRefreshAction, (FuncUser, Task)ItemEditedAsync },{ Item, editedItem }});}async Task ItemEditedAsync(User user) {ItemUser user;await ParentRefreshAction(user);}public virtual void ApplyQueryAttributes(IDictionarystring, object query){if (query.TryGetValue(Item,out object currentItem)){ItemUser (User)currentItem;}if (query.TryGetValue(ParentRefreshAction,out object parentRefreshAction)){ParentRefreshAction (FuncUser, Task)parentRefreshAction;}query.Clear();}
} 创建用户详情页面用来显示用户的全部信息。 在ToolbarItem中添加一个命令导航到编辑页面。
ContentPage xmlnshttp://schemas.microsoft.com/dotnet/2021/mauixmlns:xhttp://schemas.microsoft.com/winfx/2009/xamlxmlns:vmclr-namespace:MauiApp3.ViewModelsTitle用户详情x:ClassMauiApp3.Views.UserDetailPageContentPage.BindingContextvm:UserDetailViewModel//ContentPage.BindingContextContentPage.ToolbarItemsToolbarItem Text编辑 Command{Binding ShowEditFormCommand}//ContentPage.ToolbarItemsVerticalStackLayoutLabel Text{Binding ItemUser.Id} FontSizeLarge/Label Text{Binding ItemUser.Name} FontSizeLarge/Label Text{Binding ItemUser.Phone} FontSizeLarge/Label Text{Binding ItemUser.Email} FontSizeLarge//VerticalStackLayout
/ContentPage 更新UserEditViewModel我们让他直接继承自UserDetailViewModel.
public partial class UserEditViewModel:UserDetailViewModel
{[ObservableProperty] private bool isNewItem;[RelayCommand]private async Task SaveAsync(){await using var context new UserContext();if (IsNewItem){context.Users.Add(ItemUser);}else{context.Users.Attach(ItemUser);context.Entry(ItemUser).State Microsoft.EntityFrameworkCore.EntityState.Modified;}context.SaveChangesAsync();await ParentRefreshAction(ItemUser);await Shell.Current.GoToAsync(..);}public override void ApplyQueryAttributes(IDictionarystring, object query) {if (query.TryGetValue(IsNewItem, out object isNew)) {IsNewItem (bool)isNew;}base.ApplyQueryAttributes(query);}
} 修改MainViewModel。
public partial class MainViewModel:ObservableObject
{[ObservableProperty]ObservableCollectionUser users;[ObservableProperty] private bool refreshing;[RelayCommand]private async Task LoadUsersAsync(){await Task.Run(() {using var context new UserContext();Users new ObservableCollectionUser(context.Users);});Refreshing false;}[RelayCommand]private void Showing(){Refreshing true;}[RelayCommand]private void DeleteUser(User user){var context new UserContext();context.Users.Remove(user);context.SaveChanges();Users.Remove(user);}[RelayCommand]private async Task ShowNewFormAsync(){await Shell.Current.GoToAsync(nameof(UserEditPage),parameters:new Dictionarystring, object{{ParentRefreshAction,(FuncUser,Task)RefreshAddedAsync},{Item,new User()},{IsNewItem,true}});}Task RefreshAddedAsync(User addedUser){Users.Add(addedUser);return Task.CompletedTask;}[RelayCommand]async Task ShowDetailFormAsync(User user){await Shell.Current.GoToAsync(nameof(UserDetailPage),parameters:new Dictionarystring, object{{ParentRefreshAction,(FuncUser,Task)RefreshEditedAsync},{Item,user},});}async Task RefreshEditedAsync(User updataUser){int editedItemIndex -1;await Task.Run(() {editedItemIndex Users.Select((user, index) new { user, index }).First(x x.user.Id updataUser.Id).index;});if (editedItemIndex-1){return;}Users[editedItemIndex] updataUser;}
} 注册路由
public partial class AppShell : Shell
{public AppShell(){InitializeComponent();Routing.RegisterRoute(nameof(UserEditPage),typeof(UserEditPage));Routing.RegisterRoute(nameof(UserDetailPage),typeof(UserDetailPage));}
} 在主页添加GestureRecognizers对详情页面的跳转
Grid RowDefinitions40,40ColumnDefinitions*,*Padding10Grid.GestureRecognizersTapGestureRecognizerCommand{Binding PathBindingContext.ShowDetailFormCommand,Source{RelativeSource ModeFindAncestor,AncestorType{x:Type ContentPage}}}CommandParameter{Binding}//Grid.GestureRecognizers IOS下运行程序 我们实现了查看用户详情并且可以修改
优化代码 我们要在数据库和视图模型之间提供一个抽象层它能使项目有不同的模块区分更明确的分离开。 在项目中往往需要对多张表进行操作我们创建一个泛型接口来抽象对数据库中CURD。 在Models中添加一个IRepository.cs文件
public interface IRepositoryT where T:class
{TaskT GetByIdAsync(int id);TaskIEnumerableT GetAllAsync();Task AddAsync(T item);Task UpdateAsync(T item);Task DeleteAsync(T item);} 实现接口
public class UserRepository: IRepositoryUser
{private readonly DbSetUser DbSet;private readonly UserContext Context;public UserRepository(UserContext context){Context context;DbSet Context.SetUser();}public async TaskUser GetByIdAsync(int id){return await Task.Run(() DbSet.Find(id));}public async TaskIEnumerableUser GetAllAsync(){return await Task.Run(() DbSet.ToList());}public async Task AddAsync(User item){DbSet.Add(item);await Task.CompletedTask;}public async Task UpdateAsync(User item){DbSet.Attach(item);Context.Entry(item).State EntityState.Modified;await Task.CompletedTask;}public async Task DeleteAsync(User item){DbSet.Remove(item);await Task.CompletedTask;} 创建工作单元它的作用主要是作用于不同的数据表。
public class DbUnitOfWork:IDisposable,IUnitOfWorkUser
{readonly UserContext Contextnew UserContext();private IRepositoryUser userRepository;public IRepositoryUser Items userRepository ?? new UserRepository(Context);public void Dispose(){Context.Dispose();}public async Task SaveAsync(){await Task.Run(() Context.SaveChangesAsync());}
}public interface IUnitOfWorkT where T : class {IRepositoryT Items { get; } Task SaveAsync();
}
修改MainViewModel LoadUserAsync
[RelayCommand]
private async Task LoadUsersAsync()
{using var uniOfWork new DbUnitOfWork();Users new ObservableCollectionUser(await uniOfWork.Items.GetAllAsync());Refreshing false;
} DeleteUserAsync
[RelayCommand]
private async Task DeleteUser(User user)
{using var uniOfWork new DbUnitOfWork();await uniOfWork.Items.DeleteAsync(user);await uniOfWork.SaveAsync();Users.Remove(user);
}
修改CustomerEditViewModel SaveAsync
[RelayCommand]
private async Task SaveAsync()
{using var unitOfWork new DbUnitOfWork();if (IsNewItem)await unitOfWork.Items.AddAsync(ItemUser);elseawait unitOfWork.Items.UpdateAsync(ItemUser);await unitOfWork.SaveAsync();await ParentRefreshAction(ItemUser);await Shell.Current.GoToAsync(..);
}
修改UserDetailViewModel ShowEditFormAsync
[RelayCommand]
async Task ShowEditFormAsync()
{using var unitOfWork new DbUnitOfWork();var editedItem await unitOfWork.Items.GetByIdAsync(ItemUser.Id);await Shell.Current.GoToAsync(nameof(UserEditPage),parameters: new Dictionarystring, object{{ ParentRefreshAction, (FuncUser, Task)ItemEditedAsync },{ Item, editedItem }});
} 数据库验证错误 很多时候我们需要对用户输入的数据进行验证有很多方法和形式我们来看看在数据库层面如何做错误验证处理。并反馈在页面给用户。 我们在UserContext中进行简单的数据约束 使用try catch来捕获异常
protected override void OnModelCreating(ModelBuilder modelBuilder)
{//用户邮箱唯一modelBuilder.EntityUser().HasIndex(u u.Email).IsUnique();//用户名不能为空modelBuilder.EntityUser().Property(u u.Name).IsRequired();//初始化数据modelBuilder.EntityUser().HasData(new User{Id 1,Name 张三,Email 张三163.com,Phone 123456789});base.OnModelCreating(modelBuilder);
}
修改MainViewModel DeleteCustomerAsync
[RelayCommand]
private async Task DeleteUserAsync(User user)
{using var uniOfWork new DbUnitOfWork();try{await uniOfWork.Items.DeleteAsync(user);await uniOfWork.SaveAsync();}catch (Exception ex){await Shell.Current.DisplayAlert(Error, ex.Message, OK);return;}Users.Remove(user);
}
修改UserEditViewModel SaveAsync
[RelayCommand]
private async Task SaveAsync()
{using var unitOfWork new DbUnitOfWork();try{if (IsNewItem)await unitOfWork.Items.AddAsync(ItemUser);elseawait unitOfWork.Items.UpdateAsync(ItemUser);await unitOfWork.SaveAsync();}catch (Exception ex){await Shell.Current.DisplayAlert(Error, ex.Message, OK);return;}await ParentRefreshAction(ItemUser);await Shell.Current.GoToAsync(..);
}
IOS下运行程序 这里如果用户没有添加用户名程序会提出错误信息。 在UI中验证数据 程序中在将数据提交到数据库之前可以在UI层执行某些验证规则可以在用户保存某些修改时告知用户从而改善用户体验。
修改UserEditViewModel 在编辑用户页面我们添加对用户名和邮箱的验证并关联到保存命令上。
[NotifyCanExecuteChangedFor(nameof(SaveCommand))] [ObservableProperty]
private bool isEmailValid;[NotifyCanExecuteChangedFor(nameof(SaveCommand))] [ObservableProperty]
private bool isNameValid;bool CanSave() IsEmailValid IsNameValid;[RelayCommand(CanExecute nameof(CanSave))]
private async Task SaveAsync()
{using var unitOfWork new DbUnitOfWork();try{if (IsNewItem)await unitOfWork.Items.AddAsync(ItemUser);elseawait unitOfWork.Items.UpdateAsync(ItemUser);await unitOfWork.SaveAsync();}catch (Exception ex){await Shell.Current.DisplayAlert(Error, ex.Message, OK);return;}await ParentRefreshAction(ItemUser);await Shell.Current.GoToAsync(..);
} 在UserEditPage文件中我们添加一个样式来反馈给用户并使用工具包中的ValidationBehavior来进行验证和绑定命令。 这个验证很简单当用户输入的内容不满足条件时会使用我们设置的样式颜色来显示保存按钮无法点击当满足条件时颜色变为正常并可以保存内容。 ContentPage xmlnshttp://schemas.microsoft.com/dotnet/2021/mauixmlns:xhttp://schemas.microsoft.com/winfx/2009/xamlxmlns:vmclr-namespace:MauiApp3.ViewModels;assemblyMauiApp3xmlns:toolkit http://schemas.microsoft.com/dotnet/2022/maui/toolkitx:ClassMauiApp3.Views.UserEditPageTitle新用户ContentPage.BindingContextvm:UserEditViewModel//ContentPage.BindingContextContentPage.ResourcesStyle TargetTypeEntry x:KeyinvalidEntryStyleSetter PropertyTextColor ValueRed/Setter/Style/ContentPage.ResourcesGridVerticalStackLayout VerticalOptionsStartEntry Placeholder用户名Text{Binding ItemUser.Name}Entry.Behaviorstoolkit:TextValidationBehavior InvalidStyle{StaticResource invalidEntryStyle}IsValid{Binding IsNameValid}FlagsValidateOnValueChanged,ValidateOnAttaching//内容长度不能小于5MinimumLength5//Entry.Behaviors/EntryEntry Placeholder电话Text{Binding ItemUser.Phone}/Entry PlaceholderEmailText{Binding ItemUser.Email}ReturnCommand{Binding SaveCommand}Entry.Behaviors//验证是否时正常的邮箱格式toolkit:EmailValidationBehaviorInvalidStyle{StaticResource invalidEntryStyle}IsValid{Binding IsEmailValid}FlagsValidateOnValueChanged,ValidateOnAttaching//Entry.Behaviors/EntryButton Text保存 Command{Binding SaveCommand}//VerticalStackLayoutActivityIndicator VerticalOptionsCenterHorizontalOptionsCenterIsRunning{Binding SaveCommand.IsRunning}//Grid
/ContentPage
IOS下运行程序