app converted to mvvm

This commit is contained in:
iTob 2024-09-05 17:58:38 +02:00
parent 3b291e4fba
commit 60ec37b2c7
7 changed files with 144 additions and 105 deletions

View File

@ -1,12 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows.Input;
namespace MauiApp2.ViewModels
{
class NoteViewModel
internal class NoteViewModel : ObservableObject, IQueryAttributable
{
private Models.Note _note;
public NoteViewModel()
{
_note = new Models.Note();
SaveCommand = new AsyncRelayCommand(Save);
DeleteCommand = new AsyncRelayCommand(Delete);
}
public NoteViewModel(Models.Note note)
{
_note = note;
SaveCommand = new AsyncRelayCommand(Save);
DeleteCommand = new AsyncRelayCommand(Delete);
}
public string Text
{
get => _note.Text;
set
{
if (_note.Text != value)
{
_note.Text = value;
OnPropertyChanged();
}
}
}
public DateTime Date => _note.Date;
public string Identifier => _note.Filename;
public ICommand SaveCommand { get; private set; }
public ICommand DeleteCommand { get; private set; }
private async Task Save()
{
_note.Date = DateTime.Now;
_note.Save();
await Shell.Current.GoToAsync($"..?saved={_note.Filename}");
}
private async Task Delete()
{
_note.Delete();
await Shell.Current.GoToAsync($"..?deleted={_note.Filename}");
}
void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query)
{
if (query.ContainsKey("load"))
{
_note = Models.Note.Load(query["load"].ToString());
RefreshProperties();
}
}
public void Reload()
{
_note = Models.Note.Load(_note.Filename);
RefreshProperties();
}
private void RefreshProperties()
{
OnPropertyChanged(nameof(Text));
OnPropertyChanged(nameof(Date));
}
}
}

View File

@ -1,12 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using MauiApp2.Models;
using System.Collections.ObjectModel;
using System.Windows.Input;
namespace MauiApp2.ViewModels
{
class NotesViewModel
internal class NotesViewModel : IQueryAttributable
{
public ObservableCollection<ViewModels.NoteViewModel> AllNotes { get; }
public ICommand NewCommand { get; }
public ICommand SelectNoteCommand { get; }
public NotesViewModel()
{
AllNotes = new ObservableCollection<ViewModels.NoteViewModel>(Models.Note.LoadAll().Select(n => new NoteViewModel(n)));
NewCommand = new AsyncRelayCommand(NewNoteAsync);
SelectNoteCommand = new AsyncRelayCommand<ViewModels.NoteViewModel>(SelectNoteAsync);
}
private async Task NewNoteAsync()
{
await Shell.Current.GoToAsync(nameof(Views.NotePage));
}
private async Task SelectNoteAsync(NoteViewModel note)
{
if (note != null)
await Shell.Current.GoToAsync($"{nameof(Views.NotePage)}?load={note.Identifier}");
}
void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query)
{
if (query.ContainsKey("deleted"))
{
string noteId = query["deleted"].ToString();
NoteViewModel matchedNote = AllNotes.Where((n) => n.Identifier == noteId).FirstOrDefault();
// If note exists, delete it
if (matchedNote != null)
AllNotes.Remove(matchedNote);
}
else if (query.ContainsKey("saved"))
{
string noteId = query["saved"].ToString();
NoteViewModel matchedNote = AllNotes.Where((n) => n.Identifier == noteId).FirstOrDefault();
// If note is found, update it
if (matchedNote != null)
matchedNote.Reload();
// If note isn't found, it's new; add it.
else
AllNotes.Add(new NoteViewModel(Note.Load(noteId)));
}
}
}
}

View File

@ -6,12 +6,4 @@ public partial class AboutPage : ContentPage
{
InitializeComponent();
}
private async void LearnMore_Clicked(object sender, EventArgs e)
{
if (BindingContext is Models.About about)
{
// Navigate to the specified URL in the system browser.
await Launcher.Default.OpenAsync(about.MoreInfoUrl);
}
}
}

View File

@ -2,19 +2,24 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp2.Views.AllNotesPage"
xmlns:viewModels="clr-namespace:MauiApp2.ViewModels"
Title="Your Notes">
<ContentPage.BindingContext>
<viewModels:NotesViewModel />
</ContentPage.BindingContext>
<!-- Add an item to the toolbar -->
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Clicked="Add_Clicked" IconImageSource="{FontImage Glyph='+', Color=Black, Size=22}" />
<ToolbarItem Text="Add" Command="{Binding NewCommand}" IconImageSource="{FontImage Glyph='+', Color=Black, Size=22}" />
</ContentPage.ToolbarItems>
<!-- Display notes in a list -->
<CollectionView x:Name="notesCollection"
ItemsSource="{Binding Notes}"
<CollectionView x:Name="notesCollection"
ItemsSource="{Binding AllNotes}"
Margin="20"
SelectionMode="Single"
SelectionChanged="notesCollection_SelectionChanged">
SelectionChangedCommand="{Binding SelectNoteCommand}"
SelectionChangedCommandParameter="{Binding Source={RelativeSource Self}, Path=SelectedItem}">
<!-- Designate how the collection of items are laid out -->
<CollectionView.ItemsLayout>

View File

@ -1,38 +1,9 @@
using MauiApp2.Models;
namespace MauiApp2.Views;
public partial class AllNotesPage : ContentPage
{
public AllNotesPage()
{
InitializeComponent();
BindingContext = new AllNotes();
}
protected override void OnAppearing()
public AllNotesPage()
{
((AllNotes)BindingContext).LoadNotes();
}
private async void Add_Clicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync(nameof(NotePage));
}
private async void notesCollection_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.CurrentSelection.Count != 0)
{
// Get the note model
var note = (Note)e.CurrentSelection[0];
// Should navigate to "NotePage?ItemId=path\on\device\XYZ.notes.txt"
await Shell.Current.GoToAsync($"{nameof(NotePage)}?{nameof(NotePage.ItemId)}={note.Filename}");
// Unselect the UI
notesCollection.SelectedItem = null;
}
InitializeComponent();
}
}

View File

@ -2,7 +2,11 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp2.Views.NotePage"
xmlns:viewModels="clr-namespace:MauiApp2.ViewModels"
Title="NotePage">
<ContentPage.BindingContext>
<viewModels:NoteViewModel />
</ContentPage.BindingContext>
<VerticalStackLayout Spacing="10" Margin="5">
<Editor x:Name="TextEditor"
Text="{Binding Text}"
@ -11,11 +15,13 @@
<Grid ColumnDefinitions="*,*" ColumnSpacing="4">
<Button Text="Save"
Clicked="SaveButton_Clicked" />
Command="{Binding SaveCommand}"/>
<Button Grid.Column="1"
Text="Delete"
Clicked="DeleteButton_Clicked" />
Command="{Binding DeleteCommand}"/>
</Grid>
</VerticalStackLayout>
</ContentPage>

View File

@ -1,55 +1,9 @@
using MauiApp2.Models;
namespace MauiApp2.Views;
[QueryProperty(nameof(ItemId), nameof(ItemId))]
public partial class NotePage : ContentPage
{
public string ItemId
{
set => LoadNote(value);
}
public NotePage()
{
InitializeComponent();
string appDataPath = FileSystem.AppDataDirectory;
string randomFileName = $"{Path.GetRandomFileName()}.notes.txt";
LoadNote(Path.Combine(appDataPath, randomFileName));
}
private async void SaveButton_Clicked(object sender, EventArgs e)
{
if (BindingContext is Note note)
File.WriteAllText(note.Filename, TextEditor.Text);
await Shell.Current.GoToAsync("..");
}
private async void DeleteButton_Clicked(object sender, EventArgs e)
{
if (BindingContext is Note note)
{
if (File.Exists(note.Filename))
File.Delete(note.Filename);
}
await Shell.Current.GoToAsync("..");
}
private void LoadNote(string fileName)
{
Note noteModel = new Note();
noteModel.Filename = fileName;
if (File.Exists(fileName))
{
noteModel.Date = File.GetCreationTime(fileName);
noteModel.Text = File.ReadAllText(fileName);
}
BindingContext = noteModel;
InitializeComponent();
}
}