Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51f1eb8c65 | ||
|
|
3a819ce180 |
No files matched your search
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ReactiveUI" Version="23.2.28" />
|
||||||
|
<PackageReference Include="ReactiveUI.SourceGenerators" Version="3.1.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,14 +1,11 @@
|
|||||||
using System;
|
using System.Net.Http.Headers;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using PcgsInvUi.Models;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.SourceGenerators;
|
||||||
|
|
||||||
namespace PcgsInvUi.Services;
|
namespace PcgsApi;
|
||||||
|
|
||||||
public class PcgsClient : ReactiveObject {
|
public partial class PcgsClient : ReactiveObject {
|
||||||
public enum ErrorType {
|
public enum ErrorType {
|
||||||
None,
|
None,
|
||||||
NoCoinFound,
|
NoCoinFound,
|
||||||
@@ -16,14 +13,9 @@ public class PcgsClient : ReactiveObject {
|
|||||||
ApiKeyInvalid
|
ApiKeyInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
public int NumApiRequests {
|
protected readonly string _apiKey;
|
||||||
get => _numApiRequests;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _numApiRequests, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _apiUri = "https://api.pcgs.com/publicapi";
|
protected readonly string _apiUri = "https://api.pcgs.com/publicapi";
|
||||||
private readonly string _apiKey;
|
|
||||||
private int _numApiRequests;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the PcgsClient class.
|
/// Creates a new instance of the PcgsClient class.
|
||||||
@@ -33,6 +25,8 @@ public class PcgsClient : ReactiveObject {
|
|||||||
_apiKey = apiKey;
|
_apiKey = apiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Reactive] private int _numApiRequests;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the PcgsClient class.
|
/// Creates a new instance of the PcgsClient class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -53,7 +47,9 @@ public class PcgsClient : ReactiveObject {
|
|||||||
public async Task<bool> VerifyCredentials() {
|
public async Task<bool> VerifyCredentials() {
|
||||||
// Create a way to check if the api key given is valid
|
// Create a way to check if the api key given is valid
|
||||||
// I think the best way to do this is to make a request to the api and see if it returns the expected response.
|
// I think the best way to do this is to make a request to the api and see if it returns the expected response.
|
||||||
var result = await this.GetCoinFactsByGrade(1, "AG-03"); // This is a known invalid coin id - this is because the api is very fast with invalid requests.
|
var result =
|
||||||
|
await GetCoinFactsByGrade(1,
|
||||||
|
"AG-03"); // This is a known invalid coin id - this is because the api is very fast with invalid requests.
|
||||||
if (result.Item1 == ErrorType.ApiKeyInvalid) return false;
|
if (result.Item1 == ErrorType.ApiKeyInvalid) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -65,20 +61,21 @@ public class PcgsClient : ReactiveObject {
|
|||||||
/// <param name="grade">The grade of the coin.</param>
|
/// <param name="grade">The grade of the coin.</param>
|
||||||
/// <param name="plusGrade">Whether or not the coin is a plus grade.</param>
|
/// <param name="plusGrade">Whether or not the coin is a plus grade.</param>
|
||||||
/// <returns>A tuple containing the error type and the coin information.</returns>
|
/// <returns>A tuple containing the error type and the coin information.</returns>
|
||||||
public async Task<(ErrorType, Coin?)> GetCoinFactsByGrade(int pcgsNumber, string grade, bool plusGrade = false) {
|
public async Task<(ErrorType, PcgsCoin?)>
|
||||||
using (HttpClient client = new HttpClient()) {
|
GetCoinFactsByGrade(int pcgsNumber, string grade, bool plusGrade = false) {
|
||||||
|
using (var client = new HttpClient()) {
|
||||||
var gradeParam = GetGradeFromString(grade);
|
var gradeParam = GetGradeFromString(grade);
|
||||||
|
|
||||||
string requestUri =
|
var requestUri =
|
||||||
$"{_apiUri}/coindetail/GetCoinFactsByGrade/?PCGSNo={pcgsNumber}&GradeNo={gradeParam}&PlusGrade={plusGrade}";
|
$"{_apiUri}/coindetail/GetCoinFactsByGrade/?PCGSNo={pcgsNumber}&GradeNo={gradeParam}&PlusGrade={plusGrade}";
|
||||||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", _apiKey);
|
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", _apiKey);
|
||||||
Console.WriteLine($"Sending request to {requestUri}");
|
Console.WriteLine($"Sending request to {requestUri}");
|
||||||
HttpResponseMessage response = await client.GetAsync(requestUri);
|
var response = await client.GetAsync(requestUri);
|
||||||
Console.WriteLine("Got response.");
|
Console.WriteLine("Got response.");
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode) {
|
if (response.IsSuccessStatusCode) {
|
||||||
// Check response for errors.
|
// Check response for errors.
|
||||||
string jsonResponse = await response.Content.ReadAsStringAsync();
|
var jsonResponse = await response.Content.ReadAsStringAsync();
|
||||||
var parsedResponse = ParseJsonResponse(jsonResponse);
|
var parsedResponse = ParseJsonResponse(jsonResponse);
|
||||||
return parsedResponse;
|
return parsedResponse;
|
||||||
}
|
}
|
||||||
@@ -93,7 +90,8 @@ public class PcgsClient : ReactiveObject {
|
|||||||
/// <param name="grade">The grade string.</param>
|
/// <param name="grade">The grade string.</param>
|
||||||
/// <returns>The grade number.</returns>
|
/// <returns>The grade number.</returns>
|
||||||
private int GetGradeFromString(string grade) {
|
private int GetGradeFromString(string grade) {
|
||||||
var actualGrade = int.Parse(grade.Substring(grade.Length - 2)); // Throws an exception if the grade doesn't exist.
|
var actualGrade =
|
||||||
|
int.Parse(grade.Substring(grade.Length - 2)); // Throws an exception if the grade doesn't exist.
|
||||||
Console.WriteLine($"Grade is {actualGrade}");
|
Console.WriteLine($"Grade is {actualGrade}");
|
||||||
return actualGrade;
|
return actualGrade;
|
||||||
}
|
}
|
||||||
@@ -103,26 +101,26 @@ public class PcgsClient : ReactiveObject {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="json">The json response.</param>
|
/// <param name="json">The json response.</param>
|
||||||
/// <returns>A tuple containing an error type and the coin information.</returns>
|
/// <returns>A tuple containing an error type and the coin information.</returns>
|
||||||
private (ErrorType, Coin?) ParseJsonResponse(string json) {
|
private (ErrorType, PcgsCoin?) ParseJsonResponse(string json) {
|
||||||
Console.WriteLine(json);
|
Console.WriteLine(json);
|
||||||
// Check for errors in the response
|
// Check for errors in the response
|
||||||
if (json.Contains("\"ServerMessage\":\"No data found\"")) return (ErrorType.NoCoinFound, null);
|
if (json.Contains("\"ServerMessage\":\"No data found\"")) return (ErrorType.NoCoinFound, null);
|
||||||
if (json.Contains("\"IsValidRequest\":false")) return (ErrorType.InvalidRequestFormat, null);
|
if (json.Contains("\"IsValidRequest\":false")) return (ErrorType.InvalidRequestFormat, null);
|
||||||
|
|
||||||
var newCoin = JsonSerializer.Deserialize<Coin>(json);
|
var newCoin = JsonSerializer.Deserialize<PcgsCoin>(json);
|
||||||
return (ErrorType.None, newCoin);
|
return (ErrorType.None, newCoin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exception for invalid request format
|
// Exception for invalid request format
|
||||||
class InvalidRequestFormatException : Exception {
|
internal class InvalidRequestFormatException : Exception {
|
||||||
public InvalidRequestFormatException() { }
|
public InvalidRequestFormatException() { }
|
||||||
public InvalidRequestFormatException(string message) : base(message) { }
|
public InvalidRequestFormatException(string message) : base(message) { }
|
||||||
public InvalidRequestFormatException(string message, Exception inner) : base(message, inner) { }
|
public InvalidRequestFormatException(string message, Exception inner) : base(message, inner) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exception for no coin found
|
// Exception for no coin found
|
||||||
class CoinNotFoundException : Exception {
|
internal class CoinNotFoundException : Exception {
|
||||||
public CoinNotFoundException() { }
|
public CoinNotFoundException() { }
|
||||||
public CoinNotFoundException(string message) : base(message) { }
|
public CoinNotFoundException(string message) : base(message) { }
|
||||||
public CoinNotFoundException(string message, Exception inner) : base(message, inner) { }
|
public CoinNotFoundException(string message, Exception inner) : base(message, inner) { }
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.SourceGenerators;
|
||||||
|
|
||||||
|
namespace PcgsApi;
|
||||||
|
|
||||||
|
public partial class PcgsCoin : ReactiveObject {
|
||||||
|
[Reactive] private string _pcgsNumber;
|
||||||
|
[Reactive] private string _name;
|
||||||
|
[Reactive] private int _year;
|
||||||
|
[Reactive] private string _denomination;
|
||||||
|
[Reactive] private string _mintMark;
|
||||||
|
[Reactive] private string _grade;
|
||||||
|
[Reactive] private string _coinFactsLink;
|
||||||
|
[Reactive] private string _majorVariety;
|
||||||
|
[Reactive] private string _minorVariety;
|
||||||
|
[Reactive] private string _dieVariety;
|
||||||
|
[Reactive] private string _seriesName;
|
||||||
|
[Reactive] private string _category;
|
||||||
|
[Reactive] private string _designation;
|
||||||
|
[Reactive] private int _certificateNumber;
|
||||||
|
[Reactive] private double _paidFor;
|
||||||
|
[Reactive] private string _notes;
|
||||||
|
[Reactive] private int _quantity;
|
||||||
|
[Reactive] private double _priceGuideValue;
|
||||||
|
[ObservableAsProperty] private double _totalPrice;
|
||||||
|
|
||||||
|
public PcgsCoin() {
|
||||||
|
_totalPriceHelper = this.WhenAnyValue(
|
||||||
|
x => x.Quantity,
|
||||||
|
x => x.PriceGuideValue,
|
||||||
|
(quantity, price) => quantity * price
|
||||||
|
)
|
||||||
|
.Do(_ => Debug.WriteLine("PcgsCoin total price calculated"))
|
||||||
|
.ToProperty(this, nameof(TotalPrice));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<Application xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
x:Class="PcgsInv.App"
|
||||||
|
xmlns:local="using:PcgsInv"
|
||||||
|
RequestedThemeVariant="Light">
|
||||||
|
|
||||||
|
<Application.DataTemplates>
|
||||||
|
<local:ViewLocator />
|
||||||
|
</Application.DataTemplates>
|
||||||
|
|
||||||
|
<Application.Styles>
|
||||||
|
<FluentTheme/>
|
||||||
|
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml"/>
|
||||||
|
</Application.Styles>
|
||||||
|
</Application>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
|
using Avalonia.Markup.Xaml;
|
||||||
|
using PcgsInv.ViewModels;
|
||||||
|
using PcgsInv.Views;
|
||||||
|
|
||||||
|
namespace PcgsInv;
|
||||||
|
|
||||||
|
public class App : Application {
|
||||||
|
public override void Initialize() {
|
||||||
|
AvaloniaXamlLoader.Load(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnFrameworkInitializationCompleted() {
|
||||||
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
|
desktop.MainWindow = new MainWindow {
|
||||||
|
DataContext = new MainWindowViewModel()
|
||||||
|
};
|
||||||
|
|
||||||
|
base.OnFrameworkInitializationCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
@@ -0,0 +1,47 @@
|
|||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.SourceGenerators;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using DynamicData;
|
||||||
|
using DynamicData.Binding;
|
||||||
|
using PcgsApi;
|
||||||
|
|
||||||
|
namespace PcgsInv.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains all information related to a collection of coins.
|
||||||
|
/// </summary>
|
||||||
|
public partial class CoinCollection : ReactiveObject {
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the collection.
|
||||||
|
/// </summary>
|
||||||
|
[Reactive] private string _name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The collection of <see cref="PcgsCoin"/> objects.
|
||||||
|
/// </summary>
|
||||||
|
[Reactive] private ObservableCollection<PcgsCoin> _coins;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The total value of the collection.
|
||||||
|
/// </summary>
|
||||||
|
[ObservableAsProperty] private double _totalValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new CoinCollection instance.
|
||||||
|
/// </summary>
|
||||||
|
public CoinCollection() {
|
||||||
|
Name = string.Empty;
|
||||||
|
Coins = [];
|
||||||
|
|
||||||
|
Coins.ToObservableChangeSet()
|
||||||
|
.AutoRefresh(x => x.TotalPrice)
|
||||||
|
.ToCollection()
|
||||||
|
.Select(coins => coins.Sum(c => c.TotalPrice))
|
||||||
|
.ToProperty(this, nameof(TotalValue), out _totalValueHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<AvaloniaResource Include="Assets\**"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Avalonia" Version="12.0.4"/>
|
||||||
|
<PackageReference Include="Avalonia.Controls.DataGrid" Version="12.0.0" />
|
||||||
|
<PackageReference Include="Avalonia.Desktop" Version="12.0.4"/>
|
||||||
|
<PackageReference Include="Avalonia.Themes.Fluent" Version="12.0.4"/>
|
||||||
|
<PackageReference Include="Avalonia.Fonts.Inter" Version="12.0.4"/>
|
||||||
|
<PackageReference Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.2">
|
||||||
|
<IncludeAssets Condition="'$(Configuration)' != 'Debug'">None</IncludeAssets>
|
||||||
|
<PrivateAssets Condition="'$(Configuration)' != 'Debug'">All</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="ReactiveUI" Version="23.2.28" />
|
||||||
|
<PackageReference Include="ReactiveUI.Avalonia" Version="12.0.3" />
|
||||||
|
<PackageReference Include="ReactiveUI.SourceGenerators" Version="3.1.0">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Converters\"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\PcgsApi\PcgsApi.csproj"/>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using Avalonia;
|
||||||
|
using ReactiveUI.Avalonia;
|
||||||
|
|
||||||
|
namespace PcgsInv;
|
||||||
|
|
||||||
|
internal sealed class Program {
|
||||||
|
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||||
|
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||||
|
// yet and stuff might break.
|
||||||
|
[STAThread]
|
||||||
|
public static void Main(string[] args) {
|
||||||
|
BuildAvaloniaApp()
|
||||||
|
.StartWithClassicDesktopLifetime(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
|
public static AppBuilder BuildAvaloniaApp()
|
||||||
|
=> AppBuilder.Configure<App>()
|
||||||
|
.UsePlatformDetect()
|
||||||
|
.UseReactiveUI(builder => builder.WithAvalonia())
|
||||||
|
#if DEBUG
|
||||||
|
.WithDeveloperTools()
|
||||||
|
#endif
|
||||||
|
.WithInterFont()
|
||||||
|
.LogToTrace();
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using PcgsInv.ViewModels;
|
||||||
|
|
||||||
|
namespace PcgsInv;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given a view model, returns the corresponding view if possible.
|
||||||
|
/// </summary>
|
||||||
|
[RequiresUnreferencedCode(
|
||||||
|
"Default implementation of ViewLocator involves reflection which may be trimmed away.",
|
||||||
|
Url = "https://docs.avaloniaui.net/docs/concepts/view-locator")]
|
||||||
|
public class ViewLocator : IDataTemplate {
|
||||||
|
public Control? Build(object? param) {
|
||||||
|
if (param is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
|
||||||
|
var type = Type.GetType(name);
|
||||||
|
|
||||||
|
if (type != null) return (Control)Activator.CreateInstance(type)!;
|
||||||
|
|
||||||
|
return new TextBlock { Text = "Not Found: " + name };
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Match(object? data) {
|
||||||
|
return data is ViewModelBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using PcgsApi;
|
||||||
|
using PcgsInv.Models;
|
||||||
|
using ReactiveUI;
|
||||||
|
using ReactiveUI.SourceGenerators;
|
||||||
|
|
||||||
|
namespace PcgsInv.ViewModels;
|
||||||
|
|
||||||
|
public partial class MainWindowViewModel : ViewModelBase {
|
||||||
|
[Reactive] private CoinCollection _collection;
|
||||||
|
[Reactive] private PcgsCoin? _selectedCoin;
|
||||||
|
|
||||||
|
public MainWindowViewModel() {
|
||||||
|
Collection = new CoinCollection();
|
||||||
|
_selectedCoin = null;
|
||||||
|
|
||||||
|
Collection.PropertyChanged += (s, e) => {
|
||||||
|
Debug.WriteLine($"Collection raised event: {e.PropertyName}");
|
||||||
|
};
|
||||||
|
|
||||||
|
this.WhenAnyValue(x => x.Collection.TotalValue)
|
||||||
|
.Subscribe(x => Debug.WriteLine($"Total value was recomputed: {x}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactiveCommand]
|
||||||
|
private void CreateTestingCoin() {
|
||||||
|
Collection.Coins.Add(new PcgsCoin());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace PcgsInv.ViewModels;
|
||||||
|
|
||||||
|
public abstract class ViewModelBase : ReactiveObject { }
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:vm="using:PcgsInv.ViewModels"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
Height="450" Width="800"
|
||||||
|
x:Class="PcgsInv.Views.MainWindow"
|
||||||
|
x:DataType="vm:MainWindowViewModel"
|
||||||
|
Icon="/Assets/avalonia-logo.ico"
|
||||||
|
Title="{Binding Collection.Name, StringFormat='PCGS Inventory - {0}'}">
|
||||||
|
|
||||||
|
<Design.DataContext>
|
||||||
|
<vm:MainWindowViewModel />
|
||||||
|
</Design.DataContext>
|
||||||
|
|
||||||
|
<Grid ColumnDefinitions="3*, Auto, *"
|
||||||
|
RowDefinitions="Auto, *">
|
||||||
|
|
||||||
|
<Menu Grid.Row="0" Grid.ColumnSpan="2">
|
||||||
|
<Menu.Items>
|
||||||
|
<MenuItem Header="File">
|
||||||
|
<MenuItem Header="Hello"/>
|
||||||
|
</MenuItem>
|
||||||
|
</Menu.Items>
|
||||||
|
</Menu>
|
||||||
|
|
||||||
|
<DockPanel Grid.Row="1" Grid.Column="0">
|
||||||
|
<Grid DockPanel.Dock="Top" Margin="5" ColumnDefinitions="Auto, *">
|
||||||
|
<TextBlock Grid.Column="0" VerticalAlignment="Center" Text="Collection name: "/>
|
||||||
|
<TextBox Grid.Column="1" Text="{Binding Collection.Name}" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Button DockPanel.Dock="Top"
|
||||||
|
Command="{Binding CreateTestingCoinCommand}"
|
||||||
|
Content="Create Test Coin"/>
|
||||||
|
|
||||||
|
<TextBlock DockPanel.Dock="Bottom"
|
||||||
|
Margin="5"
|
||||||
|
Text="{Binding Collection.TotalValue, StringFormat='Total Value: ${0}'}"/>
|
||||||
|
|
||||||
|
<DataGrid ItemsSource="{Binding Collection.Coins}"
|
||||||
|
SelectedItem="{Binding SelectedCoin}"
|
||||||
|
Margin="5">
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Width="*" Header="Name" Binding="{Binding Name}"/>
|
||||||
|
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}"/>
|
||||||
|
<DataGridTextColumn Header="Price" Binding="{Binding PriceGuideValue}"/>
|
||||||
|
<DataGridTextColumn Header="Total" Binding="{Binding TotalPrice}"
|
||||||
|
IsReadOnly="True"/>
|
||||||
|
</DataGrid.Columns>
|
||||||
|
</DataGrid>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<GridSplitter Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Background="Gray" ResizeDirection="Columns" Margin="3"/>
|
||||||
|
|
||||||
|
<!-- Some other content -->
|
||||||
|
|
||||||
|
<DockPanel Grid.Row="1" Grid.Column="2">
|
||||||
|
<TextBlock>This is a test!</TextBlock>
|
||||||
|
</DockPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace PcgsInv.Views;
|
||||||
|
|
||||||
|
public partial class MainWindow : Window {
|
||||||
|
public MainWindow() {
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<!-- This manifest is used on Windows only.
|
||||||
|
Don't remove it as it might cause problems with window transparency and embedded controls.
|
||||||
|
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
|
||||||
|
<assemblyIdentity version="1.0.0.0" name="PcgsInv.Desktop"/>
|
||||||
|
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- A list of the Windows versions that this application has been tested on
|
||||||
|
and is designed to work with. Uncomment the appropriate elements
|
||||||
|
and Windows will automatically select the most compatible environment. -->
|
||||||
|
|
||||||
|
<!-- Windows 10 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<Application xmlns="https://github.com/avaloniaui"
|
<Application xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
x:Class="PcgsInvUi.App"
|
x:Class="PcgsInvUi.App"
|
||||||
xmlns:local="using:PcgsInvUi"
|
|
||||||
xmlns:pcgsInvUi="clr-namespace:PcgsInvUi"
|
xmlns:pcgsInvUi="clr-namespace:PcgsInvUi"
|
||||||
RequestedThemeVariant="Light">
|
RequestedThemeVariant="Light">
|
||||||
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using PcgsInvUi.Views;
|
|||||||
|
|
||||||
namespace PcgsInvUi;
|
namespace PcgsInvUi;
|
||||||
|
|
||||||
public partial class App : Application {
|
public class App : Application {
|
||||||
public override void Initialize() {
|
public override void Initialize() {
|
||||||
AvaloniaXamlLoader.Load(this);
|
AvaloniaXamlLoader.Load(this);
|
||||||
}
|
}
|
||||||
@@ -17,14 +17,13 @@ public partial class App : Application {
|
|||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
|
||||||
var coins = new CoinDatabase();
|
var coins = new CoinDatabase();
|
||||||
desktop.MainWindow = new MainWindow {
|
desktop.MainWindow = new MainWindow {
|
||||||
DataContext = new MainWindowViewModel(coins),
|
DataContext = new MainWindowViewModel(coins)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allow the application to save the database when it exits.
|
// Allow the application to save the database when it exits.
|
||||||
desktop.Exit += (sender, args) => {
|
desktop.Exit += (sender, args) => { coins.UpdateCollection("CollectionTable"); };
|
||||||
coins.UpdateCollection("CollectionTable");
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
base.OnFrameworkInitializationCompleted();
|
base.OnFrameworkInitializationCompleted();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.Models;
|
|
||||||
|
|
||||||
public class Coin : ReactiveObject {
|
|
||||||
public string PCGSNo {
|
|
||||||
get => _pcgsNo;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _pcgsNo, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _pcgsNo;
|
|
||||||
|
|
||||||
public string Name {
|
|
||||||
get => _name;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _name;
|
|
||||||
|
|
||||||
public int Year {
|
|
||||||
get => _year;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _year, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _year;
|
|
||||||
|
|
||||||
public string Denomination {
|
|
||||||
get => _denomination;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _denomination, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _denomination;
|
|
||||||
|
|
||||||
public string MintMark {
|
|
||||||
get => _mintMark;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _mintMark, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _mintMark;
|
|
||||||
|
|
||||||
public string Grade {
|
|
||||||
get => _grade;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _grade, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _grade;
|
|
||||||
|
|
||||||
public double PriceGuideValue {
|
|
||||||
get => _priceGuideValue;
|
|
||||||
set {
|
|
||||||
TotalPrice = value * Quantity;
|
|
||||||
this.RaiseAndSetIfChanged(ref _priceGuideValue, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _priceGuideValue;
|
|
||||||
|
|
||||||
public string CoinFactsLink {
|
|
||||||
get => _coinFactsLink;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _coinFactsLink, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _coinFactsLink;
|
|
||||||
|
|
||||||
public string MajorVariety {
|
|
||||||
get => _majorVariety;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _majorVariety, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _majorVariety;
|
|
||||||
|
|
||||||
public string MinorVariety {
|
|
||||||
get => _minorVariety;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _minorVariety, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _minorVariety;
|
|
||||||
|
|
||||||
public string DieVariety {
|
|
||||||
get => _dieVariety;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _dieVariety, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _dieVariety;
|
|
||||||
|
|
||||||
public string SeriesName {
|
|
||||||
get => _seriesName;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _seriesName, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _seriesName;
|
|
||||||
|
|
||||||
public string Category {
|
|
||||||
get => _category;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _category, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _category;
|
|
||||||
|
|
||||||
public string Designation {
|
|
||||||
get => _designation;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _designation, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _designation;
|
|
||||||
|
|
||||||
public int CertificateNumber {
|
|
||||||
get => _certificateNumber;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _certificateNumber, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _certificateNumber;
|
|
||||||
|
|
||||||
public int Quantity {
|
|
||||||
get => _quantity;
|
|
||||||
set {
|
|
||||||
TotalPrice = value * PriceGuideValue;
|
|
||||||
this.RaiseAndSetIfChanged(ref _quantity, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int _quantity;
|
|
||||||
|
|
||||||
public double TotalPrice {
|
|
||||||
get => _totalPrice;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _totalPrice, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _totalPrice;
|
|
||||||
|
|
||||||
public double PaidFor {
|
|
||||||
get => _paidFor;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _paidFor, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private double _paidFor;
|
|
||||||
|
|
||||||
public string Notes {
|
|
||||||
get => _notes;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _notes, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string _notes;
|
|
||||||
|
|
||||||
public Coin() {
|
|
||||||
PCGSNo = "";
|
|
||||||
Name = "";
|
|
||||||
Year = 0;
|
|
||||||
Denomination = "";
|
|
||||||
MintMark = "";
|
|
||||||
Grade = "";
|
|
||||||
PriceGuideValue = 0;
|
|
||||||
CoinFactsLink = "";
|
|
||||||
MajorVariety = "";
|
|
||||||
MinorVariety = "";
|
|
||||||
DieVariety = "";
|
|
||||||
SeriesName = "";
|
|
||||||
Category = "";
|
|
||||||
Designation = "";
|
|
||||||
CertificateNumber = 0;
|
|
||||||
Quantity = 0;
|
|
||||||
PaidFor = 0;
|
|
||||||
Notes = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+18
-11
@@ -1,13 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||||
<Company>BobdaFett</Company>
|
<Company>BobdaFett</Company>
|
||||||
<AssemblyVersion>0.0.5</AssemblyVersion>
|
<AssemblyVersion>0.0.5</AssemblyVersion>
|
||||||
|
<LangVersion>latestmajor</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -17,16 +18,17 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Avalonia" Version="11.0.5" />
|
<PackageReference Include="Avalonia" Version="12.0.4"/>
|
||||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.0.5" />
|
<PackageReference Include="Avalonia.Controls.DataGrid" Version="12.0.0"/>
|
||||||
<PackageReference Include="Avalonia.Desktop" Version="11.0.5" />
|
<PackageReference Include="Avalonia.Desktop" Version="12.0.4"/>
|
||||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.5" />
|
<PackageReference Include="Avalonia.Themes.Fluent" Version="12.0.4"/>
|
||||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.5" />
|
<PackageReference Include="Avalonia.Fonts.Inter" Version="12.0.4"/>
|
||||||
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.3.17"/>
|
||||||
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.5" />
|
<PackageReference Include="Avalonia.ReactiveUI" Version="11.3.8"/>
|
||||||
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.2"/>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3"/>
|
||||||
<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
|
<PackageReference Include="System.Data.SQLite" Version="2.0.3"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@
|
|||||||
<Compile Include="obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs"/>
|
<Compile Include="obj\Debug\net6.0\.NETCoreApp,Version=v6.0.AssemblyAttributes.cs"/>
|
||||||
<Compile Include="obj\Debug\net6.0\PcgsInvUi.AssemblyInfo.cs"/>
|
<Compile Include="obj\Debug\net6.0\PcgsInvUi.AssemblyInfo.cs"/>
|
||||||
<Compile Remove="obj\**"/>
|
<Compile Remove="obj\**"/>
|
||||||
<Compile Remove="Services\CoinCollection.cs" />
|
<Compile Remove="Services\CoinCollection.cs"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
@@ -90,6 +92,11 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Models\"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
using Avalonia;
|
using System;
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using System;
|
|
||||||
using PcgsInvUi.ViewModels;
|
|
||||||
|
|
||||||
namespace PcgsInvUi;
|
namespace PcgsInvUi;
|
||||||
|
|
||||||
class Program {
|
internal class Program {
|
||||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||||
// yet and stuff might break.
|
// yet and stuff might break.
|
||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main(string[] args) => BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
public static void Main(string[] args) {
|
||||||
|
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||||
|
}
|
||||||
|
|
||||||
// Avalonia configuration, don't remove; also used by visual designer.
|
// Avalonia configuration, don't remove; also used by visual designer.
|
||||||
public static AppBuilder BuildAvaloniaApp()
|
public static AppBuilder BuildAvaloniaApp() {
|
||||||
=> AppBuilder.Configure<App>()
|
return AppBuilder.Configure<App>()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
.WithInterFont()
|
.WithInterFont()
|
||||||
.LogToTrace()
|
.LogToTrace()
|
||||||
.UseReactiveUI();
|
.UseReactiveUI();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Data.SQLite;
|
using System.Data.SQLite;
|
||||||
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using PcgsInvUi.Models;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.Services;
|
namespace PcgsInvUi.Services;
|
||||||
|
|
||||||
public class CoinDatabase {
|
public class CoinDatabase {
|
||||||
public SQLiteConnection Connection { get; set; }
|
|
||||||
private Boolean IsConnected { get; set; }
|
|
||||||
public ObservableCollection<Coin> Collection { get; set; }
|
|
||||||
public Boolean IsClientConnected { get; set; }
|
|
||||||
|
|
||||||
private PcgsClient? _pcgsClient;
|
private PcgsClient? _pcgsClient;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -25,11 +20,16 @@ public class CoinDatabase {
|
|||||||
CreateCollection("CollectionTable");
|
CreateCollection("CollectionTable");
|
||||||
CreateApiTable();
|
CreateApiTable();
|
||||||
Console.WriteLine("Connected to database.");
|
Console.WriteLine("Connected to database.");
|
||||||
Collection = new ObservableCollection<Coin>();
|
Collection = new ObservableCollection<PcgsCoin>();
|
||||||
GetCollection("CollectionTable");
|
GetCollection("CollectionTable");
|
||||||
Console.WriteLine("Got collection.");
|
Console.WriteLine("Got collection.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SQLiteConnection Connection { get; set; }
|
||||||
|
private bool IsConnected { get; set; }
|
||||||
|
public ObservableCollection<PcgsCoin> Collection { get; set; }
|
||||||
|
public bool IsClientConnected { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Destructor. Currently not used, due to the strange nature of desktop applications.
|
/// Destructor. Currently not used, due to the strange nature of desktop applications.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -47,7 +47,7 @@ public class CoinDatabase {
|
|||||||
/// <returns>True if the API key was found, false otherwise.</returns>
|
/// <returns>True if the API key was found, false otherwise.</returns>
|
||||||
public async Task<bool> TryInitApiClient() {
|
public async Task<bool> TryInitApiClient() {
|
||||||
Console.Write("Attempting to initialize API client... ");
|
Console.Write("Attempting to initialize API client... ");
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText = "SELECT API_KEY FROM ApiTable";
|
cmd.CommandText = "SELECT API_KEY FROM ApiTable";
|
||||||
|
|
||||||
using (var reader = cmd.ExecuteReader()) {
|
using (var reader = cmd.ExecuteReader()) {
|
||||||
@@ -70,13 +70,14 @@ public class CoinDatabase {
|
|||||||
Console.WriteLine("Failed. API key not found.");
|
Console.WriteLine("Failed. API key not found.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return IsClientConnected;
|
return IsClientConnected;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Atttempts to initialize the PCGS API client.
|
/// Atttempts to initialize the PCGS API client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name=apiKey>The API key to verify.</param>
|
/// <param name= apiKey>The API key to verify.</param>
|
||||||
/// <returns>A Task with a return value that returns true if the client intializes properly.</returns>
|
/// <returns>A Task with a return value that returns true if the client intializes properly.</returns>
|
||||||
public async Task<bool> TryInitApiClient(string apiKey) {
|
public async Task<bool> TryInitApiClient(string apiKey) {
|
||||||
Console.Write("Attempting to initialize API client with key param... ");
|
Console.Write("Attempting to initialize API client with key param... ");
|
||||||
@@ -104,7 +105,7 @@ public class CoinDatabase {
|
|||||||
/// <returns>The SQLiteConnection that corresponds to the connected database.</returns>
|
/// <returns>The SQLiteConnection that corresponds to the connected database.</returns>
|
||||||
private SQLiteConnection CreateConnection() {
|
private SQLiteConnection CreateConnection() {
|
||||||
// Check if database exists.
|
// Check if database exists.
|
||||||
if (!System.IO.File.Exists("coin_collection")) {
|
if (!File.Exists("coin_collection")) {
|
||||||
// If not, create the database.
|
// If not, create the database.
|
||||||
Console.Write("Creating database... ");
|
Console.Write("Creating database... ");
|
||||||
SQLiteConnection.CreateFile("coin_collection.sqlite");
|
SQLiteConnection.CreateFile("coin_collection.sqlite");
|
||||||
@@ -112,7 +113,7 @@ public class CoinDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a connection to the database.
|
// Create a connection to the database.
|
||||||
SQLiteConnection connection =
|
var connection =
|
||||||
new SQLiteConnection("DataSource=coin_collection");
|
new SQLiteConnection("DataSource=coin_collection");
|
||||||
|
|
||||||
// Open the connection.
|
// Open the connection.
|
||||||
@@ -139,7 +140,7 @@ public class CoinDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a SQL command.
|
// Create a SQL command.
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText =
|
cmd.CommandText =
|
||||||
"CREATE TABLE IF NOT EXISTS ApiTable (" +
|
"CREATE TABLE IF NOT EXISTS ApiTable (" +
|
||||||
"API_KEY TEXT, " +
|
"API_KEY TEXT, " +
|
||||||
@@ -163,7 +164,7 @@ public class CoinDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a SQL command.
|
// Create a SQL command.
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText =
|
cmd.CommandText =
|
||||||
$"CREATE TABLE IF NOT EXISTS {collectionName} (" +
|
$"CREATE TABLE IF NOT EXISTS {collectionName} (" +
|
||||||
"PCGS_NUMBER TEXT," +
|
"PCGS_NUMBER TEXT," +
|
||||||
@@ -193,7 +194,7 @@ public class CoinDatabase {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Inserts a Coin object into the database.
|
/// Inserts a Coin object into the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void InsertCoin(Coin coin) {
|
public void InsertCoin(PcgsCoin pcgsCoin) {
|
||||||
Console.WriteLine("Inserting coin...");
|
Console.WriteLine("Inserting coin...");
|
||||||
// Use our existing connection to insert a coin to the database.
|
// Use our existing connection to insert a coin to the database.
|
||||||
if (!IsConnected) {
|
if (!IsConnected) {
|
||||||
@@ -203,16 +204,16 @@ public class CoinDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a SQL command.
|
// Create a SQL command.
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText =
|
cmd.CommandText =
|
||||||
"INSERT INTO CollectionTable (PCGS_NUMBER, GRADE, YEAR," +
|
"INSERT INTO CollectionTable (PCGS_NUMBER, GRADE, YEAR," +
|
||||||
"DENOMINATION, MINT_MARK, PRICE_GUIDE_VALUE, COIN_FACTS_LINK," +
|
"DENOMINATION, MINT_MARK, PRICE_GUIDE_VALUE, COIN_FACTS_LINK," +
|
||||||
"MAJOR_VARIETY, MINOR_VARIETY, DIE_VARIETY, SERIES_NAME, CATEGORY, DESIGNATION," +
|
"MAJOR_VARIETY, MINOR_VARIETY, DIE_VARIETY, SERIES_NAME, CATEGORY, DESIGNATION," +
|
||||||
"CERT_NUM, QUANTITY, NOTES) " +
|
"CERT_NUM, QUANTITY, NOTES) " +
|
||||||
$"VALUES ('{coin.PCGSNo}', '{coin.Grade}', {coin.Year}, '{coin.Denomination}', '{coin.MintMark}', {coin.PriceGuideValue}," +
|
$"VALUES ('{pcgsCoin.PcgsNumber}', '{pcgsCoin.Grade}', {pcgsCoin.Year}, '{pcgsCoin.Denomination}', '{pcgsCoin.MintMark}', {pcgsCoin.PriceGuideValue}," +
|
||||||
$"'{coin.CoinFactsLink}', '{coin.MajorVariety}', '{coin.MinorVariety}', '{coin.DieVariety}', '{coin.SeriesName}', " +
|
$"'{pcgsCoin.CoinFactsLink}', '{pcgsCoin.MajorVariety}', '{pcgsCoin.MinorVariety}', '{pcgsCoin.DieVariety}', '{pcgsCoin.SeriesName}', " +
|
||||||
$"'{coin.Category}', '{coin.Designation}', {coin.CertificateNumber}, {coin.Quantity}, @Notes)";
|
$"'{pcgsCoin.Category}', '{pcgsCoin.Designation}', {pcgsCoin.CertificateNumber}, {pcgsCoin.Quantity}, @Notes)";
|
||||||
cmd.Parameters.AddWithValue("@Notes", coin.Notes);
|
cmd.Parameters.AddWithValue("@Notes", pcgsCoin.Notes);
|
||||||
|
|
||||||
// Execute the command.
|
// Execute the command.
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
@@ -257,20 +258,21 @@ public class CoinDatabase {
|
|||||||
/// <param name="pcgsNumber">The PCGS number of the coin.</param>
|
/// <param name="pcgsNumber">The PCGS number of the coin.</param>
|
||||||
/// <param name="grade">The grade of the coin.</param>
|
/// <param name="grade">The grade of the coin.</param>
|
||||||
/// <returns>The coin if it exists, null otherwise.</returns>
|
/// <returns>The coin if it exists, null otherwise.</returns>
|
||||||
public Coin? GetCoin(int pcgsNumber, string grade) {
|
public PcgsCoin? GetCoin(int pcgsNumber, string grade) {
|
||||||
Console.WriteLine($"Getting coin {pcgsNumber}, {grade}...");
|
Console.WriteLine($"Getting coin {pcgsNumber}, {grade}...");
|
||||||
int gradeInt = GetGradeFromString(grade);
|
var gradeInt = GetGradeFromString(grade);
|
||||||
|
|
||||||
// Check the collection to see if the coin exists.
|
// Check the collection to see if the coin exists.
|
||||||
// We can't make a more efficient algorithm since there's not really an ordering to the collection.
|
// We can't make a more efficient algorithm since there's not really an ordering to the collection.
|
||||||
foreach (var coin in Collection) {
|
foreach (var coin in Collection)
|
||||||
if (coin.PCGSNo == pcgsNumber.ToString() && coin.Grade.Contains(gradeInt.ToString())) { // This has the possibility of a false positive for single digit grades.
|
if (coin.PcgsNumber == pcgsNumber.ToString() && coin.Grade.Contains(gradeInt.ToString())) {
|
||||||
|
// This has the possibility of a false positive for single digit grades.
|
||||||
if (gradeInt < 10)
|
if (gradeInt < 10)
|
||||||
if (char.IsDigit(coin.Grade[3])) continue; // TODO For right now, we're going to assume that the first 2 characters are ciruclation strings, and the next 2 are grade numbers.
|
if (char.IsDigit(coin.Grade[3]))
|
||||||
|
continue; // TODO For right now, we're going to assume that the first 2 characters are ciruclation strings, and the next 2 are grade numbers.
|
||||||
Console.WriteLine("Found coin.");
|
Console.WriteLine("Found coin.");
|
||||||
return coin;
|
return coin;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Couldn't find coin.");
|
Console.WriteLine("Couldn't find coin.");
|
||||||
return null;
|
return null;
|
||||||
@@ -282,23 +284,22 @@ public class CoinDatabase {
|
|||||||
/// <param name="collectionName">The name of the collection table.</param>
|
/// <param name="collectionName">The name of the collection table.</param>
|
||||||
public void GetCollection(string collectionName) {
|
public void GetCollection(string collectionName) {
|
||||||
Console.WriteLine("Getting collection...");
|
Console.WriteLine("Getting collection...");
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText = $"SELECT * FROM {collectionName}";
|
cmd.CommandText = $"SELECT * FROM {collectionName}";
|
||||||
|
|
||||||
using (var reader = cmd.ExecuteReader()) {
|
using (var reader = cmd.ExecuteReader()) {
|
||||||
while (reader.Read()) {
|
while (reader.Read())
|
||||||
// Create coin from reader then add to list.
|
// Create coin from reader then add to list.
|
||||||
Collection.Add(CoinFromReader(reader));
|
Collection.Add(CoinFromReader(reader));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a CSV formatted string from a collection.
|
/// Creates a CSV formatted string from a collection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collectionName">The name of the collection table.</param>
|
/// <param name="collectionName">The name of the collection table.</param>
|
||||||
/// <returns>A CSV formatted string.</returns>
|
/// <returns>A CSV formatted string.</returns>
|
||||||
public String CollectionToCSV(string collectionName) {
|
public string CollectionToCSV(string collectionName) {
|
||||||
var cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText = $"SELECT * FROM {collectionName}";
|
cmd.CommandText = $"SELECT * FROM {collectionName}";
|
||||||
|
|
||||||
@@ -322,23 +323,20 @@ public class CoinDatabase {
|
|||||||
using (var reader = cmd.ExecuteReader()) {
|
using (var reader = cmd.ExecuteReader()) {
|
||||||
while (reader.Read()) {
|
while (reader.Read()) {
|
||||||
// Read information from the reader, then add to CSV string.
|
// Read information from the reader, then add to CSV string.
|
||||||
for (int i = 0; i < numHeaders; i++) {
|
for (var i = 0; i < numHeaders; i++) {
|
||||||
// Get the type of each column.
|
// Get the type of each column.
|
||||||
var type = reader.GetFieldType(i);
|
var type = reader.GetFieldType(i);
|
||||||
Console.WriteLine("Type: " + type);
|
Console.WriteLine("Type: " + type);
|
||||||
if (type == typeof(Int64)) {
|
if (type == typeof(long))
|
||||||
resultString += reader.GetInt32(i) + ",";
|
resultString += reader.GetInt32(i) + ",";
|
||||||
}
|
else if (type == typeof(double))
|
||||||
else if (type == typeof(Double)) {
|
|
||||||
resultString += reader.GetDouble(i) + ",";
|
resultString += reader.GetDouble(i) + ",";
|
||||||
}
|
else if (type == typeof(string))
|
||||||
else if (type == typeof(String)) {
|
|
||||||
resultString += reader.GetString(i) + ",";
|
resultString += reader.GetString(i) + ",";
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
resultString += "NULL" + ",";
|
resultString += "NULL" + ",";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
resultString += "\n";
|
resultString += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,28 +348,28 @@ public class CoinDatabase {
|
|||||||
/// Saves a Coin object to the database.
|
/// Saves a Coin object to the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collectionName">The name of the collection table.</param>
|
/// <param name="collectionName">The name of the collection table.</param>
|
||||||
/// <param name="coin">The coin to save.</param>
|
/// <param name="pcgsCoin">The coin to save.</param>
|
||||||
public void SaveCoin(string collectionName, Coin coin) {
|
public void SaveCoin(string collectionName, PcgsCoin pcgsCoin) {
|
||||||
// Get and replace the coin from the database.
|
// Get and replace the coin from the database.
|
||||||
Console.WriteLine("Saving coin...");
|
Console.WriteLine("Saving coin...");
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText = $"UPDATE {collectionName} " +
|
cmd.CommandText = $"UPDATE {collectionName} " +
|
||||||
$"SET YEAR = {coin.Year}, " +
|
$"SET YEAR = {pcgsCoin.Year}, " +
|
||||||
$"DENOMINATION = \'{coin.Denomination}\', " +
|
$"DENOMINATION = \'{pcgsCoin.Denomination}\', " +
|
||||||
$"MINT_MARK = \'{coin.MintMark}\', " +
|
$"MINT_MARK = \'{pcgsCoin.MintMark}\', " +
|
||||||
$"PRICE_GUIDE_VALUE = \'{coin.PriceGuideValue}\', " +
|
$"PRICE_GUIDE_VALUE = \'{pcgsCoin.PriceGuideValue}\', " +
|
||||||
$"COIN_FACTS_LINK = \'{coin.CoinFactsLink}\', " +
|
$"COIN_FACTS_LINK = \'{pcgsCoin.CoinFactsLink}\', " +
|
||||||
$"MAJOR_VARIETY = \'{coin.MajorVariety}\', " +
|
$"MAJOR_VARIETY = \'{pcgsCoin.MajorVariety}\', " +
|
||||||
$"MINOR_VARIETY = \'{coin.MinorVariety}\', " +
|
$"MINOR_VARIETY = \'{pcgsCoin.MinorVariety}\', " +
|
||||||
$"DIE_VARIETY = \'{coin.DieVariety}\', " +
|
$"DIE_VARIETY = \'{pcgsCoin.DieVariety}\', " +
|
||||||
$"SERIES_NAME = \'{coin.SeriesName}\', " +
|
$"SERIES_NAME = \'{pcgsCoin.SeriesName}\', " +
|
||||||
$"CATEGORY = \'{coin.Category}\', " +
|
$"CATEGORY = \'{pcgsCoin.Category}\', " +
|
||||||
$"DESIGNATION = \'{coin.Designation}\', " +
|
$"DESIGNATION = \'{pcgsCoin.Designation}\', " +
|
||||||
$"CERT_NUM = \'{coin.CertificateNumber}\', " +
|
$"CERT_NUM = \'{pcgsCoin.CertificateNumber}\', " +
|
||||||
$"QUANTITY = {coin.Quantity}, " +
|
$"QUANTITY = {pcgsCoin.Quantity}, " +
|
||||||
$"NOTES = @Notes " +
|
$"NOTES = @Notes " +
|
||||||
$"WHERE PCGS_NUMBER = {coin.PCGSNo} AND GRADE = \'{coin.Grade}\'";
|
$"WHERE PCGS_NUMBER = {pcgsCoin.PcgsNumber} AND GRADE = \'{pcgsCoin.Grade}\'";
|
||||||
cmd.Parameters.AddWithValue("@Notes", coin.Notes);
|
cmd.Parameters.AddWithValue("@Notes", pcgsCoin.Notes);
|
||||||
Console.WriteLine(cmd.CommandText);
|
Console.WriteLine(cmd.CommandText);
|
||||||
// Execute the command.
|
// Execute the command.
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
@@ -384,47 +382,47 @@ public class CoinDatabase {
|
|||||||
public void UpdateCollection(string collectionName) {
|
public void UpdateCollection(string collectionName) {
|
||||||
// Update the database with the contents of the collection.
|
// Update the database with the contents of the collection.
|
||||||
// TODO This is a very inefficient way of doing this. I should be able to do this in one command.
|
// TODO This is a very inefficient way of doing this. I should be able to do this in one command.
|
||||||
foreach (var coin in Collection) {
|
foreach (var coin in
|
||||||
|
Collection)
|
||||||
SaveCoin(collectionName, coin); // CAREFUL! This will not create a coin if it doesn't currently exist.
|
SaveCoin(collectionName, coin); // CAREFUL! This will not create a coin if it doesn't currently exist.
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a Coin from the information in a reader specifically from this database.
|
/// Creates a Coin from the information in a reader specifically from this database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reader">The reader to get the information from.</param>
|
/// <param name="reader">The reader to get the information from.</param>
|
||||||
private Coin CoinFromReader(SQLiteDataReader reader) {
|
private PcgsCoin CoinFromReader(SQLiteDataReader reader) {
|
||||||
// Create a coin while filtering out any possible null values - they throw exceptions.
|
// Create a coin while filtering out any possible null values - they throw exceptions.
|
||||||
Coin coin = new Coin();
|
PcgsCoin pcgsCoin = new PcgsCoin();
|
||||||
if (!reader.IsDBNull(0)) coin.PCGSNo = reader.GetString(0);
|
if (!reader.IsDBNull(0)) pcgsCoin.PcgsNumber = reader.GetString(0);
|
||||||
if (!reader.IsDBNull(1)) coin.Grade = reader.GetString(1);
|
if (!reader.IsDBNull(1)) pcgsCoin.Grade = reader.GetString(1);
|
||||||
if (!reader.IsDBNull(2)) coin.Year = reader.GetInt32(2);
|
if (!reader.IsDBNull(2)) pcgsCoin.Year = reader.GetInt32(2);
|
||||||
if (!reader.IsDBNull(3)) coin.Denomination = reader.GetString(3);
|
if (!reader.IsDBNull(3)) pcgsCoin.Denomination = reader.GetString(3);
|
||||||
if (!reader.IsDBNull(4)) coin.MintMark = reader.GetString(4);
|
if (!reader.IsDBNull(4)) pcgsCoin.MintMark = reader.GetString(4);
|
||||||
if (!reader.IsDBNull(5)) coin.PriceGuideValue = reader.GetDouble(5);
|
if (!reader.IsDBNull(5)) pcgsCoin.PriceGuideValue = reader.GetDouble(5);
|
||||||
if (!reader.IsDBNull(6)) coin.CoinFactsLink = reader.GetString(6);
|
if (!reader.IsDBNull(6)) pcgsCoin.CoinFactsLink = reader.GetString(6);
|
||||||
if (!reader.IsDBNull(7)) coin.MajorVariety = reader.GetString(7);
|
if (!reader.IsDBNull(7)) pcgsCoin.MajorVariety = reader.GetString(7);
|
||||||
if (!reader.IsDBNull(8)) coin.MinorVariety = reader.GetString(8);
|
if (!reader.IsDBNull(8)) pcgsCoin.MinorVariety = reader.GetString(8);
|
||||||
if (!reader.IsDBNull(9)) coin.DieVariety = reader.GetString(9);
|
if (!reader.IsDBNull(9)) pcgsCoin.DieVariety = reader.GetString(9);
|
||||||
if (!reader.IsDBNull(10)) coin.SeriesName = reader.GetString(10);
|
if (!reader.IsDBNull(10)) pcgsCoin.SeriesName = reader.GetString(10);
|
||||||
if (!reader.IsDBNull(11)) coin.Category = reader.GetString(11);
|
if (!reader.IsDBNull(11)) pcgsCoin.Category = reader.GetString(11);
|
||||||
if (!reader.IsDBNull(12)) coin.Designation = reader.GetString(12);
|
if (!reader.IsDBNull(12)) pcgsCoin.Designation = reader.GetString(12);
|
||||||
if (!reader.IsDBNull(13)) coin.CertificateNumber = reader.GetInt32(13);
|
if (!reader.IsDBNull(13)) pcgsCoin.CertificateNumber = reader.GetInt32(13);
|
||||||
if (!reader.IsDBNull(14)) coin.Quantity = reader.GetInt32(14);
|
if (!reader.IsDBNull(14)) pcgsCoin.Quantity = reader.GetInt32(14);
|
||||||
if (!reader.IsDBNull(15)) coin.Notes = reader.GetString(15);
|
if (!reader.IsDBNull(15)) pcgsCoin.Notes = reader.GetString(15);
|
||||||
coin.TotalPrice = coin.Quantity * coin.PriceGuideValue;
|
// pcgsCoin.TotalPrice = pcgsCoin.Quantity * pcgsCoin.PriceGuideValue;
|
||||||
return coin;
|
return pcgsCoin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes a Coin object from the database.
|
/// Deletes a Coin object from the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="delCoin">The coin to delete.</param>
|
/// <param name="delPcgsCoin">The coin to delete.</param>
|
||||||
public void DeleteCoin(Coin delCoin) {
|
public void DeleteCoin(PcgsCoin delPcgsCoin) {
|
||||||
SQLiteCommand cmd = Connection.CreateCommand();
|
var cmd = Connection.CreateCommand();
|
||||||
cmd.CommandText = "DELETE FROM CollectionTable WHERE PCGS_NUMBER = @PcgsNumber AND GRADE = @Grade";
|
cmd.CommandText = "DELETE FROM CollectionTable WHERE PCGS_NUMBER = @PcgsNumber AND GRADE = @Grade";
|
||||||
cmd.Parameters.AddWithValue("@PcgsNumber", delCoin.PCGSNo);
|
cmd.Parameters.AddWithValue("@PcgsNumber", delPcgsCoin.PcgsNumber);
|
||||||
cmd.Parameters.AddWithValue("@Grade", delCoin.Grade);
|
cmd.Parameters.AddWithValue("@Grade", delPcgsCoin.Grade);
|
||||||
|
|
||||||
cmd.ExecuteNonQuery();
|
cmd.ExecuteNonQuery();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ public class ViewLocator : IDataTemplate {
|
|||||||
var name = data.GetType().FullName!.Replace("ViewModel", "View");
|
var name = data.GetType().FullName!.Replace("ViewModel", "View");
|
||||||
var type = Type.GetType(name);
|
var type = Type.GetType(name);
|
||||||
|
|
||||||
if (type != null) {
|
if (type != null) return (Control)Activator.CreateInstance(type)!;
|
||||||
return (Control)Activator.CreateInstance(type)!;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TextBlock { Text = "Not Found: " + name };
|
return new TextBlock { Text = "Not Found: " + name };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,18 @@
|
|||||||
using ReactiveUI;
|
using System.Diagnostics;
|
||||||
using System.Reactive;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class ApiKeyViewModel : ViewModelBase {
|
public partial class ApiKeyViewModel : ViewModelBase {
|
||||||
public string ApiKeyInput {
|
[ObservableProperty]
|
||||||
get => _apiKeyInput;
|
public partial string ApiKeyInput { get; set; }
|
||||||
set => this.RaiseAndSetIfChanged(ref _apiKeyInput, value);
|
|
||||||
}
|
|
||||||
private string _apiKeyInput = "";
|
|
||||||
|
|
||||||
public bool OkEnabled {
|
[ObservableProperty]
|
||||||
get => _okEnabled;
|
public partial bool OkEnabled { get; set; }
|
||||||
set => this.RaiseAndSetIfChanged(ref _okEnabled, value);
|
|
||||||
}
|
|
||||||
private bool _okEnabled;
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, string> OkCommand { get; }
|
[RelayCommand]
|
||||||
|
public void OkCommand() {
|
||||||
public ApiKeyViewModel() {
|
Debug.WriteLine("Running OkCommand from ApiKeyViewModel");
|
||||||
var okEnabled = this.WhenAnyValue(
|
|
||||||
x => x.ApiKeyInput,
|
|
||||||
x => !string.IsNullOrWhiteSpace(x));
|
|
||||||
|
|
||||||
|
|
||||||
// Get the API key from the user.
|
|
||||||
OkCommand = ReactiveCommand.Create(() => ApiKeyInput, okEnabled);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,20 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using PcgsInvUi.Models;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class CoinListViewModel : ViewModelBase {
|
public partial class CoinListViewModel : ViewModelBase {
|
||||||
public ObservableCollection<Coin> CoinCollection { get; set; }
|
public CoinListViewModel(IEnumerable<PcgsCoin> items) {
|
||||||
private float _totalValue;
|
CoinCollection = new ObservableCollection<PcgsCoin>(items);
|
||||||
|
|
||||||
public float TotalValue {
|
|
||||||
get => _totalValue;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _totalValue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Coin? SelectedCoin { get; set; }
|
|
||||||
|
|
||||||
public CoinListViewModel(IEnumerable<Coin> items) {
|
|
||||||
CoinCollection = new ObservableCollection<Coin>(items);
|
|
||||||
TotalValue = 0;
|
TotalValue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<PcgsCoin> CoinCollection { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial float TotalValue { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial PcgsCoin? SelectedCoin { get; set; }
|
||||||
}
|
}
|
||||||
@@ -4,11 +4,11 @@ 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> CancelCommand { get; }
|
|
||||||
|
|
||||||
public DeleteWindowViewModel() {
|
public DeleteWindowViewModel() {
|
||||||
OkCommand = ReactiveCommand.Create(() => (object)true);
|
OkCommand = ReactiveCommand.Create(() => (object)true);
|
||||||
CancelCommand = ReactiveCommand.Create(() => (object)false);
|
CancelCommand = ReactiveCommand.Create(() => (object)false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, object> OkCommand { get; }
|
||||||
|
public ReactiveCommand<Unit, object> CancelCommand { get; }
|
||||||
}
|
}
|
||||||
@@ -1,27 +1,26 @@
|
|||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using PcgsInvUi.Models;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class EditViewModel : ViewModelBase {
|
public class EditViewModel : ViewModelBase {
|
||||||
public Coin CurrentCoin { get; set; }
|
public EditViewModel(PcgsCoin pcgsCoin) {
|
||||||
|
CurrentPcgsCoin = pcgsCoin;
|
||||||
public ReactiveCommand<Unit, Unit> OkCommand { get; }
|
|
||||||
|
|
||||||
public EditViewModel(Coin coin) {
|
|
||||||
CurrentCoin = coin;
|
|
||||||
|
|
||||||
var okEnabled = this.WhenAnyValue(
|
var okEnabled = this.WhenAnyValue(
|
||||||
x => x.CurrentCoin.PCGSNo,
|
x => x.CurrentPcgsCoin.PcgsNumber,
|
||||||
x => x.CurrentCoin.Grade,
|
x => x.CurrentPcgsCoin.Grade,
|
||||||
x => x.CurrentCoin.Quantity,
|
x => x.CurrentPcgsCoin.Quantity,
|
||||||
(id, grade, quantity) => !string.IsNullOrWhiteSpace(id) &&
|
(id, grade, quantity) => !string.IsNullOrWhiteSpace(id) &&
|
||||||
!string.IsNullOrWhiteSpace(grade) &&
|
!string.IsNullOrWhiteSpace(grade) &&
|
||||||
(quantity != 0)
|
quantity != 0
|
||||||
);
|
);
|
||||||
|
|
||||||
// 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(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PcgsCoin CurrentPcgsCoin { get; set; }
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> OkCommand { get; }
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,22 @@
|
|||||||
using System.Reactive;
|
using Avalonia.Controls;
|
||||||
using ReactiveUI;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class ErrorWindowViewModel : ViewModelBase {
|
public partial class ErrorWindowViewModel : ViewModelBase {
|
||||||
|
private readonly Window _dialog;
|
||||||
|
|
||||||
public string DisplayedMessage {
|
public ErrorWindowViewModel(Window dialog, string message) {
|
||||||
get => _message;
|
_dialog = dialog;
|
||||||
set => this.RaiseAndSetIfChanged(ref _message, value);
|
Message = message;
|
||||||
}
|
|
||||||
private string _message;
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, object> CloseCommand { get; }
|
|
||||||
|
|
||||||
public ErrorWindowViewModel(string message)
|
|
||||||
{
|
|
||||||
_message = message;
|
|
||||||
|
|
||||||
CloseCommand = ReactiveCommand.Create(() => (object)false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string Message { get; set; }
|
||||||
|
|
||||||
|
[RelayCommand]
|
||||||
|
public void Close() {
|
||||||
|
_dialog.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,45 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using PcgsInvUi.Models;
|
using System.Threading.Tasks;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using PcgsInvUi.Services;
|
using PcgsInvUi.Services;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class MainWindowViewModel : ViewModelBase {
|
public partial class MainWindowViewModel : ViewModelBase {
|
||||||
public ViewModelBase SidebarContent {
|
|
||||||
get => _sideContent;
|
|
||||||
private set => this.RaiseAndSetIfChanged(ref _sideContent, value);
|
|
||||||
}
|
|
||||||
public ObservableCollection<Coin> DisplayedList { get; set; }
|
|
||||||
public CoinDatabase ConnectedCoinDatabase { get; set; }
|
|
||||||
public Coin? SelectedCoin {
|
|
||||||
get => _selectedCoin;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _selectedCoin, value);
|
|
||||||
}
|
|
||||||
public double TotalValue {
|
|
||||||
get => _totalValue;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _totalValue, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> DeleteCommand { get; }
|
|
||||||
public Interaction<DeleteWindowViewModel, Boolean> ShowDeleteWindow { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> ExportCommand { get; }
|
|
||||||
public Interaction<Unit, Uri> ShowExportWindow { get; }
|
|
||||||
public Interaction<ErrorWindowViewModel, bool> ShowErrorWindow { get; }
|
|
||||||
|
|
||||||
private ViewModelBase _sideContent;
|
|
||||||
private Coin? _selectedCoin;
|
|
||||||
private double _totalValue;
|
|
||||||
|
|
||||||
public MainWindowViewModel(CoinDatabase coins) {
|
public MainWindowViewModel(CoinDatabase coins) {
|
||||||
ConnectedCoinDatabase = coins;
|
ConnectedCoinDatabase = coins;
|
||||||
var keyFound = Task.Run(() => coins.TryInitApiClient()).Result;
|
var keyFound = Task.Run(coins.TryInitApiClient).Result;
|
||||||
Console.WriteLine("Function completed.");
|
Console.WriteLine("Function completed.");
|
||||||
var newViewModel = new NewViewModel();
|
var newViewModel = new NewViewModel();
|
||||||
var apiKeyViewModel = new ApiKeyViewModel();
|
var apiKeyViewModel = new ApiKeyViewModel();
|
||||||
@@ -48,17 +22,21 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
TotalValue = DisplayedList.Sum(x => x.TotalPrice);
|
TotalValue = DisplayedList.Sum(x => x.TotalPrice);
|
||||||
|
|
||||||
// Setup interaction to show ApiKeyWindow
|
// Setup interaction to show ApiKeyWindow
|
||||||
apiKeyViewModel.OkCommand.Subscribe(async apiKey => {
|
apiKeyViewModel.OkCommandCommand.Subscribe(async apiKey => {
|
||||||
if (await ConnectedCoinDatabase.TryInitApiClient(apiKey))
|
if (await ConnectedCoinDatabase.TryInitApiClient(apiKey))
|
||||||
SidebarContent = newViewModel; // Must assign this to the observable property rather than private variable.
|
SidebarContent =
|
||||||
|
newViewModel; // Must assign this to the observable property rather than private variable.
|
||||||
});
|
});
|
||||||
|
|
||||||
// Check if API key must be entered.
|
// Check if API key must be entered.
|
||||||
if (!keyFound) {
|
if (!keyFound) {
|
||||||
Console.WriteLine("API key must be entered by user.");
|
Console.WriteLine("API key must be entered by user.");
|
||||||
// Show the API key input view.
|
// Show the API key input view.
|
||||||
_sideContent = apiKeyViewModel;
|
SidebarContent = apiKeyViewModel;
|
||||||
} else _sideContent = newViewModel;
|
}
|
||||||
|
else {
|
||||||
|
SidebarContent = newViewModel;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the ability to show the error window.
|
// Set up the ability to show the error window.
|
||||||
ShowErrorWindow = new Interaction<ErrorWindowViewModel, bool>();
|
ShowErrorWindow = new Interaction<ErrorWindowViewModel, bool>();
|
||||||
@@ -89,7 +67,8 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
// 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);
|
||||||
await 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);
|
||||||
await ShowErrorWindow.Handle(new ErrorWindowViewModel(e.Message));
|
await ShowErrorWindow.Handle(new ErrorWindowViewModel(e.Message));
|
||||||
}
|
}
|
||||||
@@ -105,7 +84,8 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
switch (result) {
|
switch (result) {
|
||||||
case PcgsClient.ErrorType.ApiKeyInvalid:
|
case PcgsClient.ErrorType.ApiKeyInvalid:
|
||||||
Console.WriteLine("API key is invalid - showing window.");
|
Console.WriteLine("API key is invalid - showing window.");
|
||||||
await ShowErrorWindow.Handle(new ErrorWindowViewModel("API key is invalid - authorization failed."));
|
await ShowErrorWindow.Handle(
|
||||||
|
new ErrorWindowViewModel("API key is invalid - authorization failed."));
|
||||||
break;
|
break;
|
||||||
case PcgsClient.ErrorType.InvalidRequestFormat:
|
case PcgsClient.ErrorType.InvalidRequestFormat:
|
||||||
Console.WriteLine("Request format is invalid - showing window.");
|
Console.WriteLine("Request format is invalid - showing window.");
|
||||||
@@ -113,7 +93,8 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
break;
|
break;
|
||||||
case PcgsClient.ErrorType.NoCoinFound:
|
case PcgsClient.ErrorType.NoCoinFound:
|
||||||
Console.WriteLine("No coin was found with the given parameters.");
|
Console.WriteLine("No coin was found with the given parameters.");
|
||||||
await ShowErrorWindow.Handle(new ErrorWindowViewModel("No coin was found with the given parameters."));
|
await ShowErrorWindow.Handle(
|
||||||
|
new ErrorWindowViewModel("No coin was found with the given parameters."));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +113,24 @@ public class MainWindowViewModel : ViewModelBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial ViewModelBase SidebarContent { get; private set; }
|
||||||
|
|
||||||
|
public ObservableCollection<PcgsCoin> DisplayedList { get; set; }
|
||||||
|
public CoinDatabase ConnectedCoinDatabase { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial PcgsCoin? SelectedCoin { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial double TotalValue { get; set; }
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> DeleteCommand { get; }
|
||||||
|
public Interaction<DeleteWindowViewModel, bool> ShowDeleteWindow { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> ExportCommand { get; }
|
||||||
|
public Interaction<Unit, Uri> ShowExportWindow { get; }
|
||||||
|
public Interaction<ErrorWindowViewModel, bool> ShowErrorWindow { get; }
|
||||||
|
|
||||||
// Create destructor to save the database when the application exits.
|
// Create destructor to save the database when the application exits.
|
||||||
// This is necessary because the database is initialized in this class.
|
// This is necessary because the database is initialized in this class.
|
||||||
~MainWindowViewModel() {
|
~MainWindowViewModel() {
|
||||||
|
|||||||
@@ -1,31 +1,14 @@
|
|||||||
using System.Reactive;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
using System.Reactive;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class NewViewModel : ViewModelBase {
|
public class NewViewModel : ViewModelBase {
|
||||||
private string _pcgsNumber = "";
|
|
||||||
private string _grade = "";
|
private string _grade = "";
|
||||||
|
private string _pcgsNumber = "";
|
||||||
private string _quantity = "";
|
private string _quantity = "";
|
||||||
|
|
||||||
public string PcgsNumber {
|
|
||||||
get => _pcgsNumber;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _pcgsNumber, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Grade {
|
|
||||||
get => _grade;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _grade, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Quantity {
|
|
||||||
get => _quantity;
|
|
||||||
set => this.RaiseAndSetIfChanged(ref _quantity, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<string> GradesList { get; }
|
|
||||||
|
|
||||||
public NewViewModel() {
|
public NewViewModel() {
|
||||||
var okEnabled = this.WhenAnyValue(
|
var okEnabled = this.WhenAnyValue(
|
||||||
x => x.PcgsNumber,
|
x => x.PcgsNumber,
|
||||||
@@ -39,9 +22,7 @@ public class NewViewModel : ViewModelBase {
|
|||||||
() => (int.Parse(PcgsNumber), Grade, int.Parse(Quantity)),
|
() => (int.Parse(PcgsNumber), Grade, int.Parse(Quantity)),
|
||||||
okEnabled);
|
okEnabled);
|
||||||
|
|
||||||
ClearCommand = ReactiveCommand.Create(() => {
|
ClearCommand = ReactiveCommand.Create(() => { ClearText(); });
|
||||||
ClearText();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize grade values for use in the view.
|
// Initialize grade values for use in the view.
|
||||||
// This must be typed out manually, as there is no way to get a list of grades from the API.
|
// This must be typed out manually, as there is no way to get a list of grades from the API.
|
||||||
@@ -79,6 +60,23 @@ public class NewViewModel : ViewModelBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string PcgsNumber {
|
||||||
|
get => _pcgsNumber;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _pcgsNumber, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Grade {
|
||||||
|
get => _grade;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _grade, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Quantity {
|
||||||
|
get => _quantity;
|
||||||
|
set => this.RaiseAndSetIfChanged(ref _quantity, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<string> GradesList { get; }
|
||||||
|
|
||||||
public ReactiveCommand<Unit, (int, string, int)> OkCommand { get; }
|
public ReactiveCommand<Unit, (int, string, int)> OkCommand { get; }
|
||||||
public ReactiveCommand<Unit, Unit> ClearCommand { get; }
|
public ReactiveCommand<Unit, Unit> ClearCommand { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using ReactiveUI;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace PcgsInvUi.ViewModels;
|
namespace PcgsInvUi.ViewModels;
|
||||||
|
|
||||||
public class ViewModelBase : ReactiveObject { }
|
public class ViewModelBase : ObservableObject { }
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
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.ApiKeyView" x:DataType="viewModels:ApiKeyViewModel" >
|
x:Class="PcgsInvUi.Views.ApiKeyView" x:DataType="viewModels:ApiKeyViewModel">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<Label Content="API key was not found or did not authenticate." />
|
<Label Content="API key was not found or did not authenticate." />
|
||||||
<Label Content="Please enter your API key below:" />
|
<Label Content="Please enter your API key below:" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using PcgsInvUi.ViewModels;
|
using System;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
using PcgsInvUi.ViewModels;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.Views;
|
namespace PcgsInvUi.Views;
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,11 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="150"
|
mc:Ignorable="d" d:DesignWidth="300" d:DesignHeight="150"
|
||||||
x:Class="PcgsInvUi.Views.ErrorWindow" x:DataType="viewModels:ErrorWindowViewModel"
|
x:Class="PcgsInvUi.Views.ErrorWindow" x:DataType="viewModels:ErrorWindowViewModel"
|
||||||
Title="Error!" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterOwner"
|
Title="Error!" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterOwner"
|
||||||
x:Name="NameErrorWindow" CanResize="False" >
|
x:Name="NameErrorWindow" CanResize="False">
|
||||||
<Grid RowDefinitions="*,*">
|
<Grid RowDefinitions="*,*">
|
||||||
<Label Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Stretch"
|
<Label Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Stretch"
|
||||||
Margin="15"
|
Margin="15"
|
||||||
Content="{Binding DisplayedMessage}" />
|
Content="{Binding Message}" />
|
||||||
<Button Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom"
|
<Button Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom"
|
||||||
Margin="10" Name="CloseButton" IsEnabled="True"
|
Margin="10" Name="CloseButton" IsEnabled="True"
|
||||||
Content="OK" Command="{Binding CloseCommand, Mode=OneWay}" />
|
Content="OK" Command="{Binding CloseCommand, Mode=OneWay}" />
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using System;
|
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using PcgsInvUi.ViewModels;
|
using PcgsInvUi.ViewModels;
|
||||||
using ReactiveUI;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.Views;
|
namespace PcgsInvUi.Views;
|
||||||
|
|
||||||
public partial class ErrorWindow : ReactiveWindow<ErrorWindowViewModel> {
|
public partial class ErrorWindow : ReactiveWindow<ErrorWindowViewModel> {
|
||||||
public ErrorWindow()
|
public ErrorWindow() {
|
||||||
{
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
this.WhenActivated(d => d(ViewModel!.CloseCommand.Subscribe(Close)));
|
this.WhenActivated(d => d(ViewModel!.CloseCommand.Subscribe(Close)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Avalonia.ReactiveUI;
|
using System;
|
||||||
|
using Avalonia.ReactiveUI;
|
||||||
using PcgsInvUi.ViewModels;
|
using PcgsInvUi.ViewModels;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace PcgsInvUi.Views;
|
namespace PcgsInvUi.Views;
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +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" WindowStartupLocation="CenterScreen" WindowState="Maximized" >
|
Title="Main Window" WindowStartupLocation="CenterScreen" WindowState="Maximized">
|
||||||
<SplitView IsPaneOpen="True"
|
<SplitView IsPaneOpen="True"
|
||||||
DisplayMode="Inline"
|
DisplayMode="Inline"
|
||||||
PanePlacement="Right">
|
PanePlacement="Right">
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
Content="{Binding SidebarContent}" />
|
Content="{Binding SidebarContent}" />
|
||||||
<TextBox Grid.Row="1" Margin="5" Watermark="Notes..."
|
<TextBox Grid.Row="1" Margin="5" Watermark="Notes..."
|
||||||
Text="{Binding SelectedCoin.Notes}"
|
Text="{Binding SelectedCoin.Notes}"
|
||||||
IsReadOnly="False" TextWrapping="Wrap"/>
|
IsReadOnly="False" TextWrapping="Wrap" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</SplitView.Pane>
|
</SplitView.Pane>
|
||||||
<Grid RowDefinitions="*, Auto" ShowGridLines="False">
|
<Grid RowDefinitions="*, Auto" ShowGridLines="False">
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
Binding="{Binding PriceGuideValue, StringFormat='${0:0.00}'}"
|
Binding="{Binding PriceGuideValue, StringFormat='${0:0.00}'}"
|
||||||
IsReadOnly="True" />
|
IsReadOnly="True" />
|
||||||
<DataGridTextColumn Header="PCGS #" Width="*"
|
<DataGridTextColumn Header="PCGS #" Width="*"
|
||||||
Binding="{Binding PCGSNo}"
|
Binding="{Binding PcgsNumber}"
|
||||||
IsReadOnly="True" />
|
IsReadOnly="True" />
|
||||||
<DataGridTextColumn Header="Quantity" Width="*"
|
<DataGridTextColumn Header="Quantity" Width="*"
|
||||||
Binding="{Binding Quantity}"
|
Binding="{Binding Quantity}"
|
||||||
|
|||||||
@@ -44,14 +44,12 @@ public partial class MainWindow : ReactiveWindow<MainWindowViewModel> {
|
|||||||
SuggestedStartLocation = await StorageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents)
|
SuggestedStartLocation = await StorageProvider.TryGetWellKnownFolderAsync(WellKnownFolder.Documents)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (file is not null) {
|
if (file is not null)
|
||||||
interationContext.SetOutput(file.Path);
|
interationContext.SetOutput(file.Path);
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
// TODO Handle user closing the dialog.
|
// TODO Handle user closing the dialog.
|
||||||
throw new Exception("User cancelled the file picker.");
|
throw new Exception("User cancelled the file picker.");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ShowErrorWindowAsync(InteractionContext<ErrorWindowViewModel, bool> interaction) {
|
private async Task ShowErrorWindowAsync(InteractionContext<ErrorWindowViewModel, bool> interaction) {
|
||||||
var window = new ErrorWindow();
|
var window = new ErrorWindow();
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="PcgsInvUi.Views.MainWindowRewrite"
|
||||||
|
Title="MainWindowRewrite">
|
||||||
|
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Text="This is a testing block!" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
namespace PcgsInvUi.Views;
|
||||||
|
|
||||||
|
public partial class MainWindowRewrite : Window {
|
||||||
|
public MainWindowRewrite() {
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PcgsInvUi", "PcgsInvUi\PcgsInvUi.csproj", "{887D7BD0-3E71-435D-82CD-3DAF3187D056}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PcgsInvUi", "PcgsInvUi\PcgsInvUi.csproj", "{887D7BD0-3E71-435D-82CD-3DAF3187D056}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PcgsInv", "PcgsInv\PcgsInv.csproj", "{8B62E70B-9F3C-4E1B-9E7D-FBADC680E5D0}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PcgsApi", "PcgsApi\PcgsApi.csproj", "{08B02A6D-EEA5-4335-AC5B-B1347CEBBE88}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -13,5 +17,13 @@ Global
|
|||||||
{887D7BD0-3E71-435D-82CD-3DAF3187D056}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{887D7BD0-3E71-435D-82CD-3DAF3187D056}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{887D7BD0-3E71-435D-82CD-3DAF3187D056}.Release|Any CPU.Build.0 = Release|Any CPU
|
{887D7BD0-3E71-435D-82CD-3DAF3187D056}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{887D7BD0-3E71-435D-82CD-3DAF3187D056}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
{887D7BD0-3E71-435D-82CD-3DAF3187D056}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||||
|
{8B62E70B-9F3C-4E1B-9E7D-FBADC680E5D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{8B62E70B-9F3C-4E1B-9E7D-FBADC680E5D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{8B62E70B-9F3C-4E1B-9E7D-FBADC680E5D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{8B62E70B-9F3C-4E1B-9E7D-FBADC680E5D0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{08B02A6D-EEA5-4335-AC5B-B1347CEBBE88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{08B02A6D-EEA5-4335-AC5B-B1347CEBBE88}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{08B02A6D-EEA5-4335-AC5B-B1347CEBBE88}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{08B02A6D-EEA5-4335-AC5B-B1347CEBBE88}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
Reference in new issue
Block a user