Fixed issues relating to proper creation and recording of coin collection totals, along with proper modal dialog functionality. #3

Merged
BobdaFett merged 3 commits from vas-working into master 2023-11-23 23:18:22 +00:00
14 changed files with 109 additions and 43 deletions

No files matched your search

+9
View File
@@ -2,3 +2,12 @@
/PcgsInvUi/[Oo]bj/ /PcgsInvUi/[Oo]bj/
[Oo]bj/ [Oo]bj/
[Bb]in/ [Bb]in/
ALL_BUILD.vcxproj
ALL_BUILD.vcxproj.filters
ZERO_CHECK.vcxproj
ZERO_CHECK.vcxproj.filters
CMakeCache.txt
CMakeFiles/
.idea/
cmake_install.cmake
coin_collection
+5
View File
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project("PcgsInvUi" CSharp)
add_subdirectory(PcgsInvUi)
+47
View File
@@ -0,0 +1,47 @@
cmake_minimum_required(VERSION 3.25)
project(PcgsInvUi LANGUAGES CSharp)
include(CSharpUtilities)
add_executable(PcgsInvUi
App.axaml.cs
Program.cs
ViewLocator.cs
App.axaml
app.manifest
Models/Coin.cs
Services/CoinCollection.cs
Services/CoinDatabase.cs
Services/PcgsClient.cs
ViewModels/CoinListViewModel.cs
ViewModels/DeleteWindowViewModel.cs
ViewModels/EditViewModel.cs
ViewModels/ErrorWindowViewModel.cs
ViewModels/FindWindowViewModel.cs
ViewModels/MainWindowViewModel.cs
ViewModels/NewViewModel.cs
ViewModels/ViewModelBase.cs
Views/DeleteWindow.axaml
Views/DeleteWindow.axaml.cs
Views/ErrorWindow.axaml
Views/ErrorWindow.axaml.cs
Views/FindWindow.axaml
Views/FindWindow.axaml.cs
Views/MainWindow.axaml
Views/MainWindow.axaml.cs
Views/NewView.axaml
Views/NewView.axaml.cs
)
# Set the .NET Framework version for the executable.
set_property(TARGET PcgsInvUi PROPERTY VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.7.2")
# Set the executable to be 64-bit.
set_property(TARGET PcgsInvUi PROPERTY WIN64_EXECUTABLE TRUE)
# Set the C# language version (defaults to 3.0)
set(CMAKE_CSharp_FLAGS "/langversion:latest")
# Add the .NET reference libraries as dependencies.
set_property(TARGET PcgsInvUi PROPERTY VS_DOTNET_REFERENCES
"Microsoft.CSharp"
)
+5 -3
View File
@@ -37,14 +37,16 @@ public class CoinDatabase {
private SQLiteConnection CreateConnection() { private SQLiteConnection CreateConnection() {
// Check if database exists. // Check if database exists.
if (!System.IO.File.Exists("%USERPROFILE%\\coin_collection")) { if (!System.IO.File.Exists("coin_collection")) {
// Create the database. // Create the database.
SQLiteConnection.CreateFile("%USERPROFILE%\\coin_collection"); Console.Write("Creating database... ");
SQLiteConnection.CreateFile("coin_collection");
Console.WriteLine("Done.");
} }
// Create a connection to the database. // Create a connection to the database.
SQLiteConnection connection = SQLiteConnection connection =
new SQLiteConnection("DataSource=%USERPROFILE%\\coin_collection"); new SQLiteConnection("DataSource=coin_collection");
// Open the connection. // Open the connection.
try { try {
@@ -1,15 +1,14 @@
using System.Reactive; using System.Reactive;
using PcgsInvUi.Views;
using ReactiveUI; using ReactiveUI;
namespace PcgsInvUi.ViewModels; namespace PcgsInvUi.ViewModels;
public class DeleteWindowViewModel : ViewModelBase { public class DeleteWindowViewModel : ViewModelBase {
public ReactiveCommand<Unit, object> OkCommand { get; } public ReactiveCommand<Unit, object> OkCommand { get; }
public ReactiveCommand<DeleteWindow, Unit> CancelCommand { get; } public ReactiveCommand<Unit, object> CancelCommand { get; }
public DeleteWindowViewModel() { public DeleteWindowViewModel() {
OkCommand = ReactiveCommand.Create(() => (object)true); OkCommand = ReactiveCommand.Create(() => (object)true);
CancelCommand = ReactiveCommand.Create<DeleteWindow>(window => window.Close()); CancelCommand = ReactiveCommand.Create(() => (object)false);
} }
} }
+2 -3
View File
@@ -1,5 +1,4 @@
using System; using System.Reactive;
using System.Reactive;
using PcgsInvUi.Models; using PcgsInvUi.Models;
using ReactiveUI; using ReactiveUI;
@@ -25,4 +24,4 @@ public class EditViewModel : ViewModelBase {
// Setup OkCommand - all Coin-related properties must be non-whitespace. // Setup OkCommand - all Coin-related properties must be non-whitespace.
OkCommand = ReactiveCommand.Create(() => { }); OkCommand = ReactiveCommand.Create(() => { });
} }
} }
+4 -7
View File
@@ -1,6 +1,4 @@
using System.Reactive; using System.Reactive;
using System.Security.Principal;
using PcgsInvUi.Views;
using ReactiveUI; using ReactiveUI;
namespace PcgsInvUi.ViewModels; namespace PcgsInvUi.ViewModels;
@@ -11,16 +9,15 @@ public class ErrorWindowViewModel : ViewModelBase {
get => _message; get => _message;
set => this.RaiseAndSetIfChanged(ref _message, value); set => this.RaiseAndSetIfChanged(ref _message, value);
} }
private string _message; private string _message;
public ReactiveCommand<ErrorWindow, Unit> CloseCommand { get; } public ReactiveCommand<Unit, object> CloseCommand { get; }
public ErrorWindowViewModel(string message) public ErrorWindowViewModel(string message)
{ {
DisplayedMessage = message; _message = message;
CloseCommand = ReactiveCommand.Create<ErrorWindow>(window => window.Close()); CloseCommand = ReactiveCommand.Create(() => (object)false);
} }
} }
+15 -9
View File
@@ -10,6 +10,7 @@ using ReactiveUI;
namespace PcgsInvUi.ViewModels; namespace PcgsInvUi.ViewModels;
// TODO Create proper sums for total value.
// TODO Error handling for API calls. // TODO Error handling for API calls.
// TODO Manual handling of API key. // TODO Manual handling of API key.
// TODO Use CoinFacts link. // TODO Use CoinFacts link.
@@ -41,7 +42,7 @@ public class MainWindowViewModel : ViewModelBase {
public Interaction<DeleteWindowViewModel, Boolean> ShowDeleteWindow { get; } public Interaction<DeleteWindowViewModel, Boolean> ShowDeleteWindow { get; }
public ReactiveCommand<Unit, Unit> ExportCommand { get; } public ReactiveCommand<Unit, Unit> ExportCommand { get; }
public Interaction<Unit, Uri> ShowExportWindow { get; } public Interaction<Unit, Uri> ShowExportWindow { get; }
public Interaction<ErrorWindowViewModel, Unit> ShowErrorWindow { get; } public Interaction<ErrorWindowViewModel, bool> ShowErrorWindow { get; }
private ViewModelBase _sideContent; private ViewModelBase _sideContent;
private Coin? _selectedCoin; private Coin? _selectedCoin;
@@ -56,7 +57,7 @@ public class MainWindowViewModel : ViewModelBase {
TotalValue = DisplayedList.Sum(x => x.TotalPrice); TotalValue = DisplayedList.Sum(x => x.TotalPrice);
// Set up the ability to show the error window. // Set up the ability to show the error window.
ShowErrorWindow = new Interaction<ErrorWindowViewModel, Unit>(); ShowErrorWindow = new Interaction<ErrorWindowViewModel, bool>();
// Set up the ability to open the delete window. // Set up the ability to open the delete window.
ShowDeleteWindow = new Interaction<DeleteWindowViewModel, bool>(); ShowDeleteWindow = new Interaction<DeleteWindowViewModel, bool>();
@@ -67,7 +68,7 @@ public class MainWindowViewModel : ViewModelBase {
var result = await ShowDeleteWindow.Handle(deleteViewModel); var result = await ShowDeleteWindow.Handle(deleteViewModel);
if (result && SelectedCoin is not null) { if (result && SelectedCoin is not null) {
ConnectedCoinDatabase.DeleteCoin(SelectedCoin); ConnectedCoinDatabase.DeleteCoin(SelectedCoin);
ConnectedCoinDatabase.Collection.Remove(SelectedCoin); // possible null deref - ignored due to button being disabled. ConnectedCoinDatabase.Collection.Remove(SelectedCoin);
} }
}, deleteEnabled); }, deleteEnabled);
@@ -83,10 +84,10 @@ public class MainWindowViewModel : ViewModelBase {
catch (IOException e) { catch (IOException e) {
// Something is wrong with the file after it's been created. // Something is wrong with the file after it's been created.
Console.WriteLine(e.Message); Console.WriteLine(e.Message);
ShowErrorWindow.Handle(new ErrorWindowViewModel(e.Message)); await ShowErrorWindow.Handle(new ErrorWindowViewModel(e.Message));
} catch (Exception e) { } catch (Exception e) {
Console.WriteLine(e.Message); Console.WriteLine(e.Message);
ShowErrorWindow.Handle(new ErrorWindowViewModel(e.Message)); await ShowErrorWindow.Handle(new ErrorWindowViewModel(e.Message));
} }
}); });
@@ -114,10 +115,15 @@ public class MainWindowViewModel : ViewModelBase {
// TODO Clear the text boxes. // TODO Clear the text boxes.
}); });
// Change TotalValue anytime SelectedCoin.TotalPrice changes. // Update TotalValue anytime a coin's quantity changes.
// Possible null deref - how do you remove this? // Possible null reference is currently ignored - SelectedCoin will never be null.
this.WhenAnyValue(x => x.SelectedCoin.TotalPrice) this.WhenAnyValue(x => x.SelectedCoin.TotalPrice)
.Subscribe(_ => TotalValue = ConnectedCoinDatabase.Collection.Sum(x => x.TotalPrice)); .Subscribe(_ => TotalValue = ConnectedCoinDatabase.Collection.Sum(x => x.TotalPrice));
// Update TotalValue anytime a coin is added or removed.
ConnectedCoinDatabase.Collection.CollectionChanged += (sender, args) => {
TotalValue = ConnectedCoinDatabase.Collection.Sum(x => x.TotalPrice);
};
} }
} }
+3 -3
View File
@@ -18,7 +18,7 @@
<Button Grid.Row="1" Grid.Column="1" Margin="5" <Button Grid.Row="1" Grid.Column="1" Margin="5"
Width="100" Width="100"
HorizontalAlignment="Stretch" VerticalAlignment="Center" HorizontalAlignment="Stretch" VerticalAlignment="Center"
HorizontalContentAlignment="Center" IsEnabled="False" HorizontalContentAlignment="Center" IsEnabled="True"
Content="Use X button" Command="{Binding CancelCommand}" /> Content="No" Command="{Binding CancelCommand}" />
</Grid> </Grid>
</Window> </Window>
+2 -1
View File
@@ -9,5 +9,6 @@ public partial class DeleteWindow : ReactiveWindow<DeleteWindowViewModel> {
public DeleteWindow() { public DeleteWindow() {
InitializeComponent(); InitializeComponent();
this.WhenActivated(d => d(ViewModel!.OkCommand.Subscribe(Close))); this.WhenActivated(d => d(ViewModel!.OkCommand.Subscribe(Close)));
this.WhenActivated(d => d(ViewModel!.CancelCommand.Subscribe(Close)));
} }
} }
+2 -3
View File
@@ -12,8 +12,7 @@
Margin="15" Margin="15"
Content="{Binding DisplayedMessage}" /> Content="{Binding DisplayedMessage}" />
<Button Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" <Button Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom"
Margin="10" Name="CloseButton" IsEnabled="False" Margin="10" Name="CloseButton" IsEnabled="True"
Content="Use X button" Command="{Binding CloseCommand, Mode=OneWay}" Content="OK" Command="{Binding CloseCommand, Mode=OneWay}" />
CommandParameter="{Binding ElementName=NameErrorWindow}"/>
</Grid> </Grid>
</Window> </Window>
+4 -1
View File
@@ -1,5 +1,7 @@
using System;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
using PcgsInvUi.ViewModels; using PcgsInvUi.ViewModels;
using ReactiveUI;
namespace PcgsInvUi.Views; namespace PcgsInvUi.Views;
@@ -7,5 +9,6 @@ public partial class ErrorWindow : ReactiveWindow<ErrorWindowViewModel> {
public ErrorWindow() public ErrorWindow()
{ {
InitializeComponent(); InitializeComponent();
this.WhenActivated(d => d(ViewModel!.CloseCommand.Subscribe(Close)));
} }
} }
+3 -4
View File
@@ -5,8 +5,7 @@
xmlns:viewModels="clr-namespace:PcgsInvUi.ViewModels" xmlns:viewModels="clr-namespace:PcgsInvUi.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="PcgsInvUi.Views.MainWindow" x:DataType="viewModels:MainWindowViewModel" x:Class="PcgsInvUi.Views.MainWindow" x:DataType="viewModels:MainWindowViewModel"
Title="Main Window" Title="Main Window" WindowStartupLocation="CenterScreen" WindowState="Maximized" >
WindowStartupLocation="CenterOwner">
<SplitView IsPaneOpen="True" <SplitView IsPaneOpen="True"
DisplayMode="Inline" DisplayMode="Inline"
PanePlacement="Right"> PanePlacement="Right">
@@ -49,7 +48,7 @@
Binding="{Binding Designation}" Binding="{Binding Designation}"
IsReadOnly="True" /> IsReadOnly="True" />
<DataGridTextColumn Header="Est. Price" Width="*" <DataGridTextColumn Header="Est. Price" Width="*"
Binding="{Binding PriceGuideValue}" Binding="{Binding PriceGuideValue, StringFormat='${0:0.00}'}"
IsReadOnly="True" /> IsReadOnly="True" />
<DataGridTextColumn Header="PCGS #" Width="*" <DataGridTextColumn Header="PCGS #" Width="*"
Binding="{Binding PCGSNo}" Binding="{Binding PCGSNo}"
@@ -78,4 +77,4 @@
</DockPanel> </DockPanel>
</Grid> </Grid>
</SplitView> </SplitView>
</Window> </Window>
+5 -5
View File
@@ -18,7 +18,7 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel> {
// this.WhenActivated(d => d(ViewModel!.ShowFindWindow.RegisterHandler(ShowFindWindowAsync))); // this.WhenActivated(d => d(ViewModel!.ShowFindWindow.RegisterHandler(ShowFindWindowAsync)));
} }
private async Task ShowDeleteWindowAsync(InteractionContext<DeleteWindowViewModel, Boolean> interaction) { private async Task ShowDeleteWindowAsync(InteractionContext<DeleteWindowViewModel, bool> interaction) {
var window = new DeleteWindow(); var window = new DeleteWindow();
window.DataContext = interaction.Input; window.DataContext = interaction.Input;
@@ -53,11 +53,11 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel> {
} }
} }
private async Task ShowErrorWindowAsync(InteractionContext<ErrorWindowViewModel, Unit> interaction) { private async Task ShowErrorWindowAsync(InteractionContext<ErrorWindowViewModel, bool> interaction) {
var window = new ErrorWindow(); var window = new ErrorWindow();
window.DataContext = interaction.Input; window.DataContext = interaction.Input;
await window.ShowDialog(this); var result = await window.ShowDialog<bool>(this);
interaction.SetOutput(Unit.Default); interaction.SetOutput(result);
} }
} }