Maui学习笔记- SQLite简单使用案例
在本案例中我们将使用EFCore对象关系映射器,对SQLite数据库进行添加删除操作。我们将从数据库读取数据并显示在CollectionView中。并使用RefreshView实现下拉刷新数据。
IOS下运行程序
创建项目
首先需要安装NuGet包
-
Microsoft.EntityFrameworkCore.Sqlite
-
CommunityToolkit.Mvvm
-
CommunityToolkit.Maui(需要在MauiProgram内引入)
-
EFCore使用DbContext连接数据库并使用DbSet<>表示数据中的每个表。
创建用户表和数据模型
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class UserContext:DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string daPath = Path.Combine(FileSystem.AppDataDirectory, "localdatabase.db");
//EFCore支持不同的数据库,这里我们使用SQLite
optionsBuilder.UseSqlite($"Filename={daPath}");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//为数据库设置初始数据
modelBuilder.Entity<User>().HasData(new User
{
Id = 1,
Name = "张三",
Email = "张三@163.com",
Phone = "123456789"
});
base.OnModelCreating(modelBuilder);
}
}
-
在APP.xaml.cs中初始化数据库
public partial class App : Application
{
public App()
{
SQLitePCL.Batteries_V2.Init();
using (var context = new UserContext())
{
context.Database.EnsureCreated();
}
InitializeComponent();
MainPage = new AppShell();
}
}
-
创建ViewModels目录并创建MainViewModel
-
使用User类绑定到CollectionView,并使用Refreshing绑定到RefreshView元素。
-
LoadUserAsync用来刷新视图,加载数据。
public partial class MainViewModel:ObservableObject
{
[ObservableProperty]
ObservableCollection<User> users;
[ObservableProperty] private bool refreshing;
[RelayCommand]
private async Task LoadUserAsync()
{
await Task.Run(() =>
{
using var context = new UserContext();
Users = new ObservableCollection<User>(context.Users);
});
Refreshing = false;
}
[RelayCommand]
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 Dictionary<string, object>
{
{"ParentRefreshAction",(Func<User,Task>)RefreshAddedAsync},
{"Item",new User()}
});
}
}
-
创建UserEditPage视图页面和UserEditViewModel
-
在UserEditViewModel中我们要实现IQueryAttributable接口
-
ApplyQueryAttributes从查询参数中加载用户对象和刷新回调函数。 SaveAsync保存用户信息到数据库,并调用父页面的刷新操作,最后返回上一页。
public partial class UserEditViewModel:ObservableObject,IQueryAttributable
{
//接受当前编辑的用户信息
[ObservableProperty] private User itemUser;
//用于在保存后刷新主页
protected Func<User, Task> ParentRefreshAction { get;set; }
[RelayCommand]
private async Task SaveAsync()
{
await using var context = new UserContext();
context.Users.Add(ItemUser);
context.SaveChangesAsync();
await ParentRefreshAction(ItemUser);
await Shell.Current.GoToAsync("..");
}
public void ApplyQueryAttributes(IDictionary<string, object> query) {
if (query.TryGetValue("Item", out object currentItem)) {
ItemUser = (User)currentItem;
}
if (query.TryGetValue("ParentRefreshAction", out object parentRefreshAction)) {
ParentRefreshAction = (Func<User, Task>)parentRefreshAction;
}
query.Clear();
}
}
-
UserEditPage页面上的Entry用来接收用户信息。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MauiApp3.ViewModels;assembly=MauiApp3"
x:Class="MauiApp3.Views.UserEditPage"
Title="新用户">
<ContentPage.BindingContext>
<vm:UserEditViewModel/>
</ContentPage.BindingContext>
<Grid>
<VerticalStackLayout VerticalOptions="Start">
<Entry Placeholder="用户名"
Text="{Binding ItemUser.Name}"/>
<Entry Placeholder="电话"
Text="{Binding ItemUser.Phone}"/>
<Entry Placeholder="Email"
Text="{Binding ItemUser.Email}"
ReturnCommand="{Binding SaveCommand}"/>
<Button Text="保存"
Command="{Binding SaveCommand}"/>
</VerticalStackLayout>
<ActivityIndicator
VerticalOptions="Center"
HorizontalOptions="Center"
IsRunning="{Binding SaveCommand.IsRunning}"/>
</Grid>
</ContentPage>
-
注册路由页面
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(UserEditPage),typeof(UserEditPage));
}
}
-
主页代码
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MauiApp3.ViewModels"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:models="clr-namespace:MauiApp3.Models"
x:DataType="{x:Type vm:MainViewModel}"
x:Class="MauiApp3.MainPage">
<ContentPage.BindingContext>
<vm:MainViewModel/>
</ContentPage.BindingContext>
<ContentPage.Behaviors>
<toolkit:EventToCommandBehavior
EventName="Appearing"
Command="{Binding ShowingCommand}"/>
</ContentPage.Behaviors>
<ContentPage.Resources>
<DataTemplate
x:Key="UserTemplate"
x:DataType="models:User">
<SwipeView>
<SwipeView.RightItems>
<SwipeItem
Text="Delete"
BackgroundColor="IndianRed"
Command="{Binding Path=BindingContext.DeleteUserCommand,Source={RelativeSource Mode=FindAncestor,AncestorType={x:Type ContentPage}}}"
CommandParameter="{Binding}"/>
</SwipeView.RightItems>
<Grid RowDefinitions="40,40"
ColumnDefinitions="*,*"
Padding="10">
<Label
Text="{Binding Name}"/>
<Label
Text="{Binding Phone}"
Grid.Column="1"/>
<Label
Text="{Binding Email}"
TextColor="DarkGrey"
Grid.Row="1"
Grid.ColumnSpan="2"/>
</Grid>
</SwipeView>
</DataTemplate>
</ContentPage.Resources>
<Grid>
<RefreshView IsRefreshing="{Binding Refreshing}"
Command="{Binding LoadUsersCommand}">
<CollectionView ItemsSource="{Binding Users}"
ItemTemplate="{StaticResource UserTemplate}"/>
</RefreshView>
<Button
Text="+"
Command="{Binding ShowNewFormCommand }"
WidthRequest="56"
HeightRequest="56"
FontSize="24"
HorizontalOptions="End"
VerticalOptions="End"
Margin="16"/>
</Grid>
</ContentPage>
后续会对该案例添加一个用户详情页面,并改进优化一下代码。