Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In deze stap vraagt u de assistent om de niet-visuele onderdelen van de app. Door deze wijziging gescheiden te houden van de XAML, kunnen compilerfouten en ontwerpproblemen gemakkelijker worden geïsoleerd.
Een model- en opslagservice vragen
Gebruik deze prompt:
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.
Vergelijk het gegenereerde model met deze implementatie:
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; }
}
Het [ObservableProperty] kenmerk genereert openbare eigenschappen en wijzigt meldingen. De klasse moet zo zijn partial dat de MVVM Toolkit-brongenerator die code kan toevoegen.
De opslagservice moet er als volgt uitzien:
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 is hier geschikt omdat de app pakketidentiteit heeft.
SaveLock voorkomt dat toevoeg-, verwijder- en voltooiingsbewerkingen tegelijkertijd naar hetzelfde bestand schrijven. Als u het distributiemodel later wijzigt, controleert u de aanname van de pakketidentiteit opnieuw in plaats van deze opslagkeuze automatisch te kopiëren.
Meer informatie: Instellingen en andere app-gegevens opslaan en ophalen en ApplicationData.LocalFolder.
Vraag om het weergavemodel
Gebruik vervolgens deze prompt:
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.
De belangrijkste patronen die in het antwoord moeten worden geïnspecteerd, zijn:
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();
}
Controleer of de assistent asynchroon werken met .Wait() of .Resultniet blokkeert. Opslagbewerkingen moeten worden afgewacht.
Het weergavemodel kan opslag-uitzonderingen ondervangen wanneer deze worden geconverteerd naar een bericht voor de pagina:
private async Task SaveAsync(string successMessage)
{
try
{
await TaskStorage.SaveAsync(Tasks);
ShowStatus(successMessage);
}
catch (Exception ex)
{
ShowStatus($"Changes couldn't be saved: {ex.Message}", hasError: true);
}
}
Dit is geen stille terugval: de gebruiker ontvangt een foutmelding en het weergavemodel claimt niet dat het opslaan is geslaagd.
De opdrachten en SaveAsync roepen twee kleine helpers aan.
RefreshTaskState genereert een wijzigingsmelding voor de berekende Summary eigenschap, zodat de gebruikersinterface wordt bijgewerkt nadat de takenlijst is gewijzigd en ShowStatus stelt de waarneembare statuseigenschappen in waaraan de pagina wordt gekoppeld:
[ObservableProperty]
public partial string StatusMessage { get; set; } = string.Empty;
[ObservableProperty]
public partial bool IsStatusOpen { get; set; }
[ObservableProperty]
public partial bool HasError { get; set; }
private void RefreshTaskState()
{
OnPropertyChanged(nameof(Summary));
OnPropertyChanged(nameof(HasNoTasks));
}
private void ShowStatus(string message, bool hasError = false)
{
StatusMessage = message;
HasError = hasError;
IsStatusOpen = true;
}
Omdat Summary een berekende eigenschap is en niet een [ObservableProperty], activeert u de wijzigingsmelding handmatig wanneer Tasks verandert.
Bouwen en inspecteren
Compileren voor x64. Waarschuwingen behandelen als werkitems, met name bindings- en nullable-verwijzingswaarschuwingen:
dotnet build -p:Platform=x64
Vraag de assistent om elk pakket dat is toegevoegd toe te lichten. Voor deze app moet er geen nieuw pakket nodig zijn buiten de Windows App SDK- en MVVM Toolkit-verwijzingen in de sjabloon.
Windows developer