Skip to content

Commit

Permalink
Improve data bindings and view model composition
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-lerch committed Dec 4, 2022
1 parent 7300f94 commit be6d689
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 9 deletions.
21 changes: 21 additions & 0 deletions src/Vocup.Core/ViewModels/BookViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ReactiveUI;
using Vocup.IO;
using Vocup.Models;
using Vocup.Settings;

namespace Vocup.ViewModels;

/// <summary>
/// Represents an opened vocabulary book. Multiple instances can be used simultaneously to implement tabs for books.
/// </summary>
public class BookViewModel : ReactiveObject
{
public BookViewModel(BookContext bookContext, IVocupSettings settings)
{
Book = bookContext.Book;
BookContext = bookContext;
}

public Book Book { get; }
public BookContext BookContext { get; }
}
6 changes: 4 additions & 2 deletions src/Vocup.Core/ViewModels/MainFormViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ public MainFormViewModel(IVocupSettings settings)

OpenCommand = ReactiveCommand.CreateFromTask(OpenCommandAction);
SaveCommand = ReactiveCommand.CreateFromTask(SaveCommandAction,
this.WhenAnyValue(x => x.BookContext, x => x.BookContext.UnsavedChanges, (_, _) => BookContext?.UnsavedChanges ?? false));
this.WhenAnyValue(x => x.BookContext, x => x.BookContext!.UnsavedChanges, (_, _) => BookContext?.UnsavedChanges ?? false));
SaveAsCommand = ReactiveCommand.CreateFromTask(SaveAsCommandAction, this.WhenAnyValue(x => x.BookContext).Select(x => x != null));
CloseCommand = ReactiveCommand.CreateFromTask(CloseCommandAction, this.WhenAnyValue(x => x.BookContext).Select(x => x != null));
PracticeCommand = ReactiveCommand.CreateFromTask(PracticeCommandAction, this.WhenAnyValue(x => x.BookContext.Book.Unpracticed).Select(x => x > 0));
CreateBookCommand = ReactiveCommand.CreateFromTask(CreateBookCommandAction);
BookSettingsCommand = ReactiveCommand.CreateFromTask(BookSettingsCommandAction, this.WhenAnyValue(x => x.BookContext).Select(x => x != null));
PrintCommand = ReactiveCommand.CreateFromTask(PrintCommandAction, this.WhenAnyValue(x => x.BookContext.Book.Words.Count).Select(x => x > 0));
OpenInExplorerCommand = ReactiveCommand.CreateFromTask(OpenInExplorerCommandAction,
this.WhenAnyValue(x => x.BookContext, x => x.BookContext.FilePath, (_, _) => BookContext?.FilePath != null));
this.WhenAnyValue(x => x.BookContext, x => x.BookContext!.FilePath, (_, _) => BookContext?.FilePath != null));

this.WhenAnyValue(x => x.BookContext, x => x.BookContext!.FilePath, (_, _) => BookContext?.FilePath)
.Select(x => x == null ? "Vocup" : $"Vocup - {Path.GetFileNameWithoutExtension(x)}")
Expand All @@ -47,7 +47,9 @@ public MainFormViewModel(IVocupSettings settings)
.ToPropertyEx(this, x => x.FullyPracticed);
}

// TODO: Replace this nullable property with BookViewModel to have less nullability issues.
[Reactive] public BookContext? BookContext { get; set; }
[Reactive] public string SearchText { get; set; } = string.Empty;
[ObservableAsProperty] public string Title { get; } = "Vocup";
[ObservableAsProperty] public int Unpracticed { get; }
[ObservableAsProperty] public int WronglyPracticed { get; }
Expand Down
22 changes: 19 additions & 3 deletions src/Vocup/Forms/PrintWordSelection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public PrintWordSelection(BookContext bookContext)

ListBox.BeginUpdate();
foreach (Word word in book.Words)
ListBox.Items.Add($"{word.MotherTongueCombined} - {word.ForeignLanguageCombined}", true);
ListBox.Items.Add(new WordListItem(word), true);
ListBox.EndUpdate();

CbUnpracticed.Enabled = book.Unpracticed > 0;
Expand Down Expand Up @@ -106,9 +106,10 @@ private void SetItemsChecked(Func<Word, bool> predicate, bool value)
{
ListBox.BeginUpdate();

for (int i = 0; i < book.Words.Count; i++)
for (int i = 0; i < ListBox.Items.Count; i++)
{
if (predicate(book.Words[i]))
WordListItem item = (WordListItem)ListBox.Items[i];
if (predicate(item.Word))
{
ListBox.SetItemChecked(i, value);
}
Expand Down Expand Up @@ -204,4 +205,19 @@ private void PrintList_PrintPage(object sender, System.Drawing.Printing.PrintPag

pageNumber++;
}

private class WordListItem
{
public WordListItem(Word word)
{
Word = word;
}

public Word Word { get; }

public override string ToString()
{
return $"{Word.MotherTongueCombined} - {Word.ForeignLanguageCombined}";
}
}
}
10 changes: 6 additions & 4 deletions src/Vocup/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ public MainForm()
ViewModel = new MainFormViewModel(Program.Settings);

#pragma warning disable CA1416 // Validate platform compatibility
this.Bind(ViewModel, vm => vm.SearchText, x => x.TbSearchWord.Text);

this.OneWayBind(ViewModel, vm => vm.Title, x => x.Text);

this.OneWayBind(ViewModel, vm => vm.BookContext, x => x.GroupBook.Enabled, context => context != null);
Expand All @@ -38,10 +40,10 @@ public MainForm()
this.OneWayBind(ViewModel, vm => vm.BookContext.Book.Words.Count, x => x.GroupSearch.Enabled, count => count > 0);
this.OneWayBind(ViewModel, vm => vm.BookContext.Book.Words.Count, x => x.TsmiExport.Enabled, count => count > 0);

this.OneWayBind(ViewModel, vm => vm.BookContext.Book.Unpracticed, x => x.StatisticsPanel.Unpracticed);
this.OneWayBind(ViewModel, vm => vm.BookContext.Book.WronglyPracticed, x => x.StatisticsPanel.WronglyPracticed);
this.OneWayBind(ViewModel, vm => vm.BookContext.Book.CorrectlyPracticed, x => x.StatisticsPanel.CorrectlyPracticed);
this.OneWayBind(ViewModel, vm => vm.BookContext.Book.FullyPracticed, x => x.StatisticsPanel.FullyPracticed);
this.OneWayBind(ViewModel, vm => vm.Unpracticed, x => x.StatisticsPanel.Unpracticed);
this.OneWayBind(ViewModel, vm => vm.WronglyPracticed, x => x.StatisticsPanel.WronglyPracticed);
this.OneWayBind(ViewModel, vm => vm.CorrectlyPracticed, x => x.StatisticsPanel.CorrectlyPracticed);
this.OneWayBind(ViewModel, vm => vm.FullyPracticed, x => x.StatisticsPanel.FullyPracticed);

this.BindCommand(ViewModel, vm => vm.OpenCommand, x => x.TsmiOpenBook);
this.BindCommand(ViewModel, vm => vm.OpenCommand, x => x.TsbOpenBook);
Expand Down

0 comments on commit be6d689

Please sign in to comment.