Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Pada langkah ini, minta asisten untuk menjelaskan bagian nonvisual aplikasi. Memisahkan perubahan ini dari XAML membuat kesalahan pengkompilasi dan masalah desain lebih mudah diisolasi.
Meminta model dan layanan penyimpanan
Gunakan perintah ini:
Add the data layer for TaskTally.
- Create a TaskItem model with an ID, title, and completion state.
- Use MVVM Toolkit observable properties.
- Create a TaskStorage service that serializes the task list to JSON.
- Store tasks in ApplicationData.Current.LocalFolder because this is
a packaged WinUI 3 app.
- Return an empty list when the file doesn't exist.
- Serialize save operations so rapid changes don't write the file concurrently.
- Surface real read and write errors to the caller.
- Build the project after the change.
Bandingkan model yang dihasilkan dengan implementasi ini:
using CommunityToolkit.Mvvm.ComponentModel;
namespace TaskTally.Models;
public partial class TaskItem : ObservableObject
{
public Guid Id { get; init; } = Guid.NewGuid();
[ObservableProperty]
public partial string Title { get; set; } = string.Empty;
[ObservableProperty]
public partial bool IsComplete { get; set; }
}
Atribut [ObservableProperty] menghasilkan properti publik dan mengubah pemberitahuan. Kelas harus partial sehingga generator sumber Toolkit MVVM dapat menambahkan kode tersebut.
Layanan penyimpanan akan terlihat seperti ini:
using System.Text.Json;
using System.Threading;
using TaskTally.Models;
using Windows.Storage;
namespace TaskTally.Services;
internal static class TaskStorage
{
private const string FileName = "tasks.json";
private static readonly SemaphoreSlim SaveLock = new(1, 1);
public static async Task<IReadOnlyList<TaskItem>> LoadAsync()
{
StorageFile? file =
await ApplicationData.Current.LocalFolder.TryGetItemAsync(FileName) as StorageFile;
if (file is null)
{
return [];
}
string json = await FileIO.ReadTextAsync(file);
return JsonSerializer.Deserialize<List<TaskItem>>(json) ?? [];
}
public static async Task SaveAsync(IEnumerable<TaskItem> tasks)
{
await SaveLock.WaitAsync();
try
{
string json = JsonSerializer.Serialize(tasks, new JsonSerializerOptions
{
WriteIndented = true
});
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(
FileName,
CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, json);
}
finally
{
SaveLock.Release();
}
}
}
ApplicationData.Current.LocalFolder sesuai di sini karena aplikasi memiliki identitas paket.
SaveLock mencegah operasi penambahan, penghapusan, dan penyelesaian menulis file yang sama secara bersamaan. Jika nanti Anda mengubah model distribusi, verifikasi asumsi identitas paket lagi alih-alih menyalin pilihan penyimpanan ini secara otomatis.
Pelajari lebih lanjut: Menyimpan dan mengambil pengaturan dan data aplikasi lainnya dan ApplicationData.LocalFolder.
Meminta model tampilan
Selanjutnya, gunakan perintah ini:
Add MainPageViewModel.
- Expose an ObservableCollection<TaskItem>.
- Add observable properties for the new-task text and status message.
- Add asynchronous commands to add and delete tasks.
- Disable AddTaskCommand when the title is blank.
- Load tasks once when the page starts.
- Save after add, delete, or completion changes.
- Expose a summary and empty-state property for x:Bind.
- Catch storage exceptions only where the UI can report them.
- Build and fix all warnings.
Pola utama untuk diperiksa dalam respons adalah:
public ObservableCollection<TaskItem> Tasks { get; } = [];
[ObservableProperty]
public partial string NewTaskTitle { get; set; } = string.Empty;
public string Summary =>
Tasks.Count == 0
? "No tasks yet"
: $"{Tasks.Count(task => !task.IsComplete)} of {Tasks.Count} remaining";
[RelayCommand(CanExecute = nameof(CanAddTask))]
private async Task AddTaskAsync()
{
string title = NewTaskTitle.Trim();
Tasks.Add(new TaskItem { Title = title });
NewTaskTitle = string.Empty;
RefreshTaskState();
await SaveAsync($"Added \"{title}\".");
}
[RelayCommand]
private async Task DeleteTaskAsync(TaskItem task)
{
Tasks.Remove(task);
RefreshTaskState();
await SaveAsync($"Deleted \"{task.Title}\".");
}
private bool CanAddTask() => !string.IsNullOrWhiteSpace(NewTaskTitle);
partial void OnNewTaskTitleChanged(string value)
{
AddTaskCommand.NotifyCanExecuteChanged();
}
Periksa apakah asisten tidak memblokir pekerjaan asinkron dengan .Wait() atau .Result. Operasi penyimpanan harus ditunggu hingga selesai.
Model tampilan dapat menangkap pengecualian penyimpanan saat mengonversinya menjadi pesan untuk halaman:
private async Task SaveAsync(string successMessage)
{
try
{
await TaskStorage.SaveAsync(Tasks);
ShowStatus(successMessage);
}
catch (Exception ex)
{
ShowStatus($"Changes couldn't be saved: {ex.Message}");
}
}
Ini bukan mekanisme cadangan diam-diam: pengguna menerima pesan kesalahan, dan view model tidak menyatakan bahwa penyimpanan berhasil.
Membangun dan memeriksa
Buat untuk x64. Perlakukan peringatan sebagai item kerja, terutama peringatan binding dan referensi nullabel:
dotnet build -p:Platform=x64
Minta asisten untuk menjelaskan setiap paket yang ditambahkan. Untuk aplikasi ini, tidak ada paket baru yang harus diperlukan di luar referensi toolkit SDK Aplikasi Windows dan MVVM dalam templat.
Windows developer