CommunityToolkit.Mvvm
TodoListViewModel
和AddUpdateTodoViewModel
TodoListViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Todo.ViewModels
{
public class TodoListViewModel
{
}
}
AddUpdateTodoViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Todo.ViewModels
{
public class AddUpdateTodoViewModel
{
}
}
回到我們的MauiProgram.cs把他們給加入
MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
...
// Add ViewModel
builder.Services.AddSingleton<TodoListViewModel>();
builder.Services.AddSingleton<AddUpdateTodoViewModel>();
return builder.Build();
}
}
打開我們的Todo\Pages\TodoPage.xaml.cs
並加入ViewModel
using Todo.ViewModels;
namespace Todo;
public partial class TodoPage : ContentPage
{
public TodoPage(TodoListViewModel vm)
{
InitializeComponent();
this.BindingContext = vm;
}
private void ButtonClicked(object sender, EventArgs e)
{
Navigation.PushAsync(new AddTodoPage());
}
}
Todo\Pages\AddTodoPage.xaml.cs也加入ViewModel
namespace Todo;
using Todo.Models;
using Todo.Services;
using Todo.ViewModels;
public partial class AddTodoPage : ContentPage
{
public AddTodoPage(AddUpdateTodoViewModel vm)
{
InitializeComponent();
this.BindingContext = vm;
}
}
修改我們的Todo\Pages\TodoPage.xaml.cs
using AndroidX.Lifecycle;
using Todo.ViewModels;
namespace Todo;
public partial class TodoPage : ContentPage
{
private TodoListViewModel _vm;
public TodoPage(TodoListViewModel vm)
{
InitializeComponent();
_vm = vm;
this.BindingContext = vm;
}
private async void ButtonClicked(object sender, EventArgs e)
{
await AppShell.Current.GoToAsync(nameof(AddTodoPage));
}
}
並在MauiProgram.cs註冊views
using Todo.Services;
using Todo.ViewModels;
namespace Todo;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
// Add TodoItem Service
builder.Services.AddSingleton<ITodoService, TodoService>();
// Add Views
builder.Services.AddSingleton<AddTodoPage>();
builder.Services.AddSingleton<TodoPage>();
// Add ViewModel
builder.Services.AddSingleton<TodoListViewModel>();
builder.Services.AddSingleton<AddUpdateTodoViewModel>();
return builder.Build();
}
}
並且到Todo\AppShell.xaml.cs
加入路徑
namespace Todo;
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(AddTodoPage), typeof(AddTodoPage));
}
}
並刪除TestTabbedPage
並且修改Todo\AppShell.xaml
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="Todo.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Todo"
Shell.FlyoutBehavior="Disabled">
<TabBar x:Name="Tabs">
<Tab Title="Home">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage"
/>
</Tab>
<Tab Title="Todo">
<ShellContent ContentTemplate="{DataTemplate local:TodoPage}" Route="TodoPage" />
</Tab>
<Tab Title="User">
<ShellContent ContentTemplate="{DataTemplate local:UserPage}" Route="UserPage" />
</Tab>
</TabBar>
</Shell>
AddUpdateTodoViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Todo.Models;
using Todo.Services;
namespace Todo.ViewModels
{
[QueryProperty(nameof(TodoItem), "TodoItem")]
public partial class AddUpdateTodoViewModel : ObservableObject
{
[ObservableProperty]
private TodoItemModel _todoItem = new TodoItemModel();
private readonly ITodoService _todoService;
public AddUpdateTodoViewModel(ITodoService todoService)
{
_todoService = todoService;
}
[RelayCommand]
public async void AddUpdateTodo()
{
int res = -1;
if(TodoItem.TodoId > 0) {
res = await _todoService.UpdateTodo(TodoItem);
} else {
res = await _todoService.AddTodo(new Models.TodoItemModel
{
Title = TodoItem.Title,
IsDone = false,
});
}
if(res > 0) {
await Shell.Current.DisplayAlert("Status: Todo Saved", "The Todo Items Saved", "Ok");
} else {
await Shell.Current.DisplayAlert("Status: Wrong", "Something is wrong", "Ok");
}
}
}
}
TodoListViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Todo.Models;
using Todo.Services;
namespace Todo.ViewModels
{
public partial class TodoListViewModel : ObservableObject
{
public ObservableCollection<TodoItemModel> Todos { get; set; } = new ObservableCollection<TodoItemModel>();
private readonly ITodoService _todoService;
public TodoListViewModel(ITodoService todoService)
{
_todoService = todoService;
}
[RelayCommand]
public async void GetTodoList()
{
Todos.Clear();
var todoList = await _todoService.GetTodos();
if (todoList?.Count > 0) {
foreach (var todo in todoList) {
Todos.Add(todo);
}
}
}
}
}
首先修改我們的Todo\Pages\TodoPage.xaml.cs
,加入OnAppearing
當畫面切過去實會執行GetTodo
using AndroidX.Lifecycle;
using Todo.ViewModels;
namespace Todo;
public partial class TodoPage : ContentPage
{
private TodoListViewModel _vm;
public TodoPage(TodoListViewModel vm)
{
InitializeComponent();
_vm = vm;
this.BindingContext = vm;
}
private async void ButtonClicked(object sender, EventArgs e)
{
await AppShell.Current.GoToAsync(nameof(AddTodoPage));
}
protected override void OnAppearing()
{
base.OnAppearing();
_vm.GetTodoList();
}
}
Todo\Pages\AddTodoPage.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="Todo.AddTodoPage"
Title="AddTodoPage">
<VerticalStackLayout Padding="10">
<Label
Text="Add Todo"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Entry Placeholder="Add Todo" Text="{Binding TodoItem.Title}"/>
<Button Text="Add Todo Item" Command="{Binding AddUpdateTodoCommand}" />
</VerticalStackLayout>
</ContentPage>
Todo\Pages\TodoPage.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:models="clr-namespace:Todo.Models"
x:Class="Todo.TodoPage"
Title="TodoPage">
<VerticalStackLayout Margin="10">
<Label
Text="Welcome to .NET MAUI!"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button Text="Go to Add Page" Clicked="ButtonClicked"/>
<CollectionView ItemsSource="{Binding Todos}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:TodoItemModel">
<HorizontalStackLayout>
<Label Text="{Binding Title}" />
<CheckBox IsChecked="{Binding IsDone}"/>
</HorizontalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
Test
大致上新增和列出todo簡易的完成,明天再來繼續完善我們的todo
您好,
我在NuGet安裝這套件communitytoolkit.mvvm後出現以下錯誤,請問有解決辦法嗎?
警告 CS8032 不可從 C:\Users\hans.huang.nuget\packages\communitytoolkit.mvvm\8.2.2\analyzers\dotnet\roslyn4.3\cs\CommunityToolkit.Mvvm.SourceGenerators.dll 建立分析器 CommunityToolkit.Mvvm.SourceGenerators.AsyncVoidReturningRelayCommandMethodAnalyzer 的執行個體: 無法載入檔案或組件 'System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 或其相依性的其中之一。 系統找不到指定的檔案。。 TestCommunityToolkit (net6.0-android) D:\MAUI\TestCommunityToolkit\CSC 1 作用中
不確定問題,可能是communitytoolkit.mvvm的版本與System.Collections.Immutable不符合或是缺少System.Collections.Immutable。可能要看一下你的communitytoolkit.mvvm版本,你目前的版本應該是8.2.2。
阿甫您好,
是8.2.2沒錯,後來改安裝8.0.0版就沒有出現這錯誤了。
剛檢查發現我的確缺少System.Collections.Immutable,這部分我會再做測試,感謝回覆!