在Maui中使用Sqlite

本文介绍了如何在Maui项目中使用SQLite数据库,详细步骤包括安装必要的Nuget包,创建模型、常量类和数据库服务类。同时,文章提到了Maui的CommunityToolkit和依赖注入系统的便捷性,以及在不同页面间传递自定义值的方法,最终实现了预期的运行效果。

在maui项目中使用sqlite数据库,先在Nuget中搜索sqlite-net-pcl安装 ,再在搜索中输入sqlite空格green,搜索安装sqlitepclraw.bundle_green,如果不安装后者,将会报错。

在maui中体验一下sqlite,设计一个简单的笔记本simpleNotes,先建模型,在文件夹models中创建Note.cs。

using SQLite;

namespace SimpleNotes.Models
{
    public class Note
    {
        [PrimaryKey,AutoIncrement]
        public int NoteId { get; set; }

        public string Title { get; set; }
        public string Content { get; set; }

        public DateTime CreationTime { get; set; }

        public DateTime LastModifiedTime { get; set; }
    }
}

在models文件夹中再建一个常量类,方便使用,文件名constants.cs。

namespace SimpleNotes.Models
{
    public class Constants
    {
        private const string DBName = "notes.db3";
        public const SQLite.SQLiteOpenFlags Flags = SQLite.SQLiteOpenFlags.Create |
            SQLite.SQLiteOpenFlags.ReadWrite | SQLite.SQLiteOpenFlags.SharedCache;

        public static string DatabasePath => Path.Combine(FileSystem.AppDataDirectory, DBName);
    }
}

再在services文件夹建一个DatabaseService.cs,使用sqlite数据库的类。

using SimpleNotes.Models;
using SQLite;

namespace SimpleNotes.Services
{
    public class DatabaseService
    {
        SQLiteAsyncConnection conn;

        async Task Init()
        {
            if (conn is null)
            {
                conn = new SQLiteAsyncConnection(Constants.DatabasePath, Models.Constants.Flags);
                await conn.CreateTableAsync<Note>();
            }
        }

        public async Task<List<Models.Note>> GetAll()
        {
            await Init();
            return await conn.Table<Models.Note>().ToListAsync();
        }

        public async Task<Models.Note> GetNote(Note note)
        {
            await Init();
            var local = note;
            if (local is not null)
            {
                return await conn.Table<Models.Note>().Where(n => n.NoteId == local.NoteId).FirstOrDefaultAsync();
            }

            return null;
        }

        public async Task<int> AddNoteAsync(Note note)
        {
            await Init();
            var local = note;
            if (local is not null)
            {
                if (local.NoteId == 0)
                {
                    local.CreationTime = DateTime.Now;
                    local.LastModifiedTime = DateTime.Now;
                    return await conn.InsertAsync(local);
                }
                else
                {
                    local.LastModifiedTime = DateTime.Now;
                    return await conn.UpdateAsync(local);
                }
            }
            return -1;
        }

        public async Task<int> DeleteNoteAsync(Note note)
        {
            await Init();
            var local = note;
            if(local is not null)
            {
                var matchedNote = conn.Table<Note>().Where(n => n.NoteId == local.NoteId).FirstOrDefaultAsync();
                if(matchedNote is not null)
                {
                    return await conn.DeleteAsync(local);
                }
            }
            return 0;
        }        
    }
}

使用maui,不安装社区工具是不行的,真的是太方便了,提高效率,用nuget搜索安装communitytoolkit.maui和communitytoolkit.mvvm。

在viewmodels文件夹中创建AboutPageViewModel.cs。

namespace SimpleNotes.ViewModels
{
    public class AboutPageViewModel
    {
        public static string AppName => $"程序名称:{AppInfo.Name}";
        public static string Vertion => $"版本:{AppInfo.VersionString}";

        public static string MoreMessage => $"使用MAUI架构,C#语言,xaml设计界面,使用IOC容器技术。";
    }
}

在viewmodels文件夹中创建NotePageViewModel.cs。

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SimpleNotes.Models;
using SimpleNotes.Services;

namespace SimpleNotes.ViewModels
{
    public class NotePageViewModel : ObservableObject, IQueryAttributable
    {
        DatabaseService db;
        Note _note = new Note();
        public NotePageViewModel(DatabaseService databaseService) 
        {  
            db = databaseService;
            AddNoteCommand = new AsyncRelayCommand(AddNote);
            DeleteNoteCommand = new AsyncRelayCommand(DeleteNote);
        }       

        public void ApplyQueryAttributes(IDictionary<string, object> query)
        {
            if (query.ContainsKey("load"))
            {
                Note local = query["load"] as Note;
                _note = local;
                OnRefresh();
            }
            else if (query.ContainsKey("name"))
            {
                var name = query["name"] as string;
                if (name == "new")
                {
                    _note = new Note();
                    OnRefresh();
                }
            }
        }

        private void OnRefresh()
        {
            OnPropertyChanged(nameof(Title));
            OnPropertyChanged(nameof(Content));
            OnPropertyChanged(nameof(CreationTime));
            OnPropertyChanged(nameof(LastModifiedTime));
        }

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

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

        public DateTime CreationTime
        {
            get => _note.CreationTime;
            set => SetProperty(_note.CreationTime, value, _note, (n, v) => n.CreationTime = v);
        }

        public DateTime LastModifiedTime
        {
            get => _note.LastModifiedTime;
            set => SetProperty(_note.LastModifiedTime, value, _note, (n, v) => n.LastModifiedTime = v);
        }

        async Task AddNote()
        {
            await db.AddNoteAsync(_note);         
            await Shell.Current.GoToAsync("..");
        }

        public IAsyncRelayCommand AddNoteCommand { get; private set; }

        async Task DeleteNote()
        {
           await db.DeleteNoteAsync(_note);
            await Shell.Current.GoToAsync("..");
        }

        public IAsyncRelayCommand DeleteNoteCommand { get; private set; }
    }
}

再在viewmodels文件夹下创建主页面MainPageViewModels.cs。

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using SimpleNotes.Models;
using SimpleNotes.Services;
using SimpleNotes.Views;
using System.Collections.ObjectModel;

namespace SimpleNotes.ViewModels
{
    public class MainPageViewModel : ObservableObject
    {
        ObservableCollection<Note> notes;
        DatabaseService db;
        public ObservableCollection<Note> Notes
        {
            get => notes ??= new ObservableCollection<Note>();
            set => SetProperty(ref notes, value);
        }

        public MainPageViewModel(DatabaseService databaseService)
        {
            db = databaseService;
            InitializeCollectionCommand = new AsyncRelayCommand(InitializeCollection);
            SelectedNoteCommand = new AsyncRelayCommand<Note>(SelectedNote);
            NewNoteCommand = new AsyncRelayCommand(NewNote);
        }

        async Task InitializeCollection()
        {
            Notes.Clear();
            foreach (Note note in await db.GetAll())
            {
                Notes.Add(note);
            }
        }

        public IAsyncRelayCommand InitializeCollectionCommand { get; private set; }

        async Task SelectedNote(Note note)
        {
            if (note is not null)
            {
                var parameter = new Dictionary<string, object>()
                {
                    {"load",note }
                };
                await Shell.Current.GoToAsync($"{nameof(NotePage)}", parameter);
            }

        }

        public IAsyncRelayCommand SelectedNoteCommand { get; private set; }

        async Task NewNote()
        {
            string name = "new";
            await Shell.Current.GoToAsync($"{nameof(NotePage)}?name={name}");
        }  

        public IAsyncRelayCommand NewNoteCommand { get; private set; }
    }
}

再在views文件夹下创建AboutPage.xaml界面文件。

<?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:viewmodel="clr-namespace:SimpleNotes.ViewModels"
             x:Class="SimpleNotes.Views.AboutPage"
             Title="AboutPage">
    <VerticalStackLayout Margin="5">
        <HorizontalStackLayout Spacing="5">
            <Label Text="{x:Static viewmodel:AboutPageViewModel.AppName}" FontSize="20" FontAttributes="Bold" VerticalOptions="Center"/>
            <Label Text="{x:Static viewmodel:AboutPageViewModel.Vertion}" FontSize="18" VerticalOptions="Center"/>
        </HorizontalStackLayout>
        <Label Text="{x:Static viewmodel:AboutPageViewModel.MoreMessage}" FontSize="17"/>
    </VerticalStackLayout>
</ContentPage>

在views文件夹下创建NotePage.xaml界面文件。

<?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"
             x:Class="SimpleNotes.Views.NotePage"
             Title="NotePage">
    <Grid RowDefinitions="Auto,*,Auto" ColumnDefinitions="*,*" Margin="5" ColumnSpacing="5">
        <Entry Placeholder="键入标题" Text="{Binding Title}" FontAttributes="Bold" FontSize="18" Grid.ColumnSpan="2"/>
        <Editor Placeholder="键入内容" Text="{Binding Content}" IsSpellCheckEnabled="False"
                FontSize="16" IsTextPredictionEnabled="False" Grid.Row="1" Grid.ColumnSpan="2" AutoSize="TextChanges"/>
        <Button Text="删除" Command="{Binding DeleteNoteCommand}" Grid.Row="2" Grid.Column="0"/>
        <Button Text="保存" Command="{Binding AddNoteCommand}" Grid.Row="2" Grid.Column="1"/>
    </Grid>
</ContentPage>

在views文件夹下创建MainPage.xaml界面文件。

<?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"
             x:Class="SimpleNotes.Views.MainPage" Appearing="MainPage_Appearing" NavigatedTo="MainPage_NavigatedTo"
             Title="MainPage">
    <ContentPage.ToolbarItems>
        <ToolbarItem Text="添加新笔记" IconImageSource="{FontImage Glyph='+',Color=White,Size=22}" Command="{Binding NewNoteCommand}"/>
    </ContentPage.ToolbarItems>
    <Grid RowDefinitions="Auto,*" Margin="5" RowSpacing="5">
        <Label Text="{Binding Notes.Count,StringFormat='笔记总数:{0}'}"/>
        <CollectionView ItemsSource="{Binding Notes}" SelectionMode="Single" Grid.Row="1" SelectionChangedCommand="{Binding SelectedNoteCommand}"
                        SelectionChangedCommandParameter="{Binding Source={RelativeSource Self}, Path=SelectedItem}" x:Name="notesCollection">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid RowDefinitions="*,*,*" ColumnDefinitions="Auto,*" ColumnSpacing="5" RowSpacing="5">
                        <Image Source="documents.png" HeightRequest="32" Aspect="AspectFit"/>
                        <Label Text="{Binding Title}" Grid.Row="0" Grid.Column="1" FontAttributes="Bold" FontSize="18"/>
                        <Label Text="{Binding Content}" Grid.Row="1" Grid.ColumnSpan="2" MaxLines="1" FontSize="16"/>
                        <Label Text="{Binding LastModifiedTime,StringFormat='修改时间:{0:yyyy-MM-dd HH:mm:ss}'}" Grid.Row="2" Grid.ColumnSpan="2" TextColor="SlateGray"/>
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>

修改AppShell.xaml文件。

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="SimpleNotes.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:view="clr-namespace:SimpleNotes.Views" 
    Shell.FlyoutBehavior="Flyout" FlyoutBackgroundColor="Teal">
    <Shell.ItemTemplate>
        <DataTemplate>
            <Grid ColumnDefinitions="0.2*,0.8*" Margin="5">
                <Image Source="{Binding FlyoutIcon}" Margin="5" HeightRequest="32" VerticalOptions="Center"/>
                <Label Text="{Binding Title}" TextColor="White" FontSize="20" Grid.Column="1" VerticalOptions="Center"/>
            </Grid>
        </DataTemplate>
    </Shell.ItemTemplate>

    <ShellContent
        Title="主页"
        Icon="documents.png"
        ContentTemplate="{DataTemplate view:MainPage}"
        Route="MainPage" />
    <ShellContent
        Title="关于"
        Icon="about.png"
        ContentTemplate="{DataTemplate view:AboutPage}"
        Route="AboutPage" />

</Shell>

再修改mauiProgram.cs文件,由于maui自带容器,我们可以用用,最好用的是它的扩展builder.Services.AddSingleton<MainPage, MainPageViewModel>(),大家看看,把view和viewmodel一起注册,是不是非常非常方便?还有以下扩展builder.Services.AddSingletonWithShellRoute<NotePage, NotePageViewModel>($"{nameof(NotePage)}"),不仅注册了view和viewmodel,还顺带把shell的路由也注册了,真是方便,完整内容。

using CommunityToolkit.Maui;
using Microsoft.Extensions.Logging;
using SimpleNotes.Services;
using SimpleNotes.ViewModels;
using SimpleNotes.Views;

namespace SimpleNotes;

public static class MauiProgram
{
	public static MauiApp CreateMauiApp()
	{
		var builder = MauiApp.CreateBuilder();
		builder
			.UseMauiApp<App>()
			.UseMauiCommunityToolkit()
			.ConfigureFonts(fonts =>
			{
				fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
				fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
			});

		//注册service,viewmodels views;
		builder.Services.AddSingleton<DatabaseService>();
		builder.Services.AddSingleton<MainPage, MainPageViewModel>();
		builder.Services.AddSingletonWithShellRoute<NotePage, NotePageViewModel>($"{nameof(NotePage)}");

#if DEBUG
		builder.Logging.AddDebug();
#endif

		return builder.Build();
	}
}

修改NotePage.xaml.cs文件,由于我们在容器中注册了,所以可以在构造函数中直接引用注册的类型。

using SimpleNotes.ViewModels;
namespace SimpleNotes.Views;

public partial class NotePage : ContentPage
{
	public NotePage(NotePageViewModel viewmodel)
	{
		InitializeComponent();
		BindingContext = viewmodel;
	}
}

再修改MainPage.xaml.cs文件。

using SimpleNotes.ViewModels;

namespace SimpleNotes.Views;

public partial class MainPage : ContentPage
{
	public MainPage(MainPageViewModel viewmodel)
	{
		InitializeComponent();
		BindingContext = viewmodel;
	}

    private void MainPage_Appearing(object sender, EventArgs e)
    {
		((MainPageViewModel)BindingContext).InitializeCollectionCommand.Execute(null);
    }

    private void MainPage_NavigatedTo(object sender, NavigatedToEventArgs e)
    {
        notesCollection.SelectedItem = null;
    }
}

在maui页面间传递自定义的值是这样写,使用shell.current.GogoAsync的第二个签名。

​
 var parameter = new Dictionary<string, object>()
  {
    {"load",note }
  };
 await Shell.Current.GoToAsync($"{nameof(NotePage)}", parameter);

​

第一个签名是这样写,自定义的只能用第二个。

string name = "new";
await Shell.Current.GoToAsync($"{nameof(NotePage)}?name={name}");

看看运行效果,达到预期。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值