Fixed issues relating to proper creation and recording of coin collection totals, along with proper modal dialog functionality. #3
No files matched your search
@@ -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
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.25)
|
||||||
|
|
||||||
|
project("PcgsInvUi" CSharp)
|
||||||
|
|
||||||
|
add_subdirectory(PcgsInvUi)
|
||||||
@@ -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"
|
||||||
|
)
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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(() => { });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
@@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
@@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user