Initial Commit

This commit is contained in:
Andre Beging
2017-09-11 05:46:57 +02:00
parent 20199ef17c
commit 3d2d4851cc
37 changed files with 2513 additions and 0 deletions

18
App.config Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="DebtMgr.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
<userSettings>
<DebtMgr.Properties.Settings>
<setting name="Database" serializeAs="String">
<value />
</setting>
</DebtMgr.Properties.Settings>
</userSettings>
</configuration>

7
App.xaml Normal file
View File

@@ -0,0 +1,7 @@
<Application x:Class="DebtMgr.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DebtMgr" StartupUri="View/MainView.xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" xmlns:vm="clr-namespace:DebtMgr.ViewModel" />
</ResourceDictionary>
</Application.Resources>
</Application>

43
App.xaml.cs Normal file
View File

@@ -0,0 +1,43 @@
using System.Data.SqlClient;
using System.Windows;
using DebtMgr.Data;
using DebtMgr.ViewModel;
using SQLite.Net;
namespace DebtMgr
{
/// <summary>
/// Interaktionslogik für "App.xaml"
/// </summary>
public partial class App : Application
{
#region Locator
private static ViewModelLocator _locator;
public static ViewModelLocator Locator => _locator ?? (_locator = new ViewModelLocator());
#endregion
#region Database
private static SQLiteConnection _database;
public static SQLiteConnection Database => _database ?? (_database = new Database(DebtMgr.Properties.Settings.Default.Database));
#endregion
#region DatabasePath
private static string _databasePath;
public static string DatabasePath
{
get => _databasePath;
set
{
_database = null;
_databasePath = value;
}
}
#endregion
}
}

BIN
Content/addperson.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
Content/delete.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

BIN
Content/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

BIN
Content/moneybag.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@@ -0,0 +1,73 @@
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;
namespace DebtMgr.Converters
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> An amount to color converter. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public class AmountToColorConverter : IValueConverter
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Converts. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
///
/// <param name="value"> The value. </param>
/// <param name="targetType"> Type of the target. </param>
/// <param name="parameter"> The parameter. </param>
/// <param name="culture"> The culture. </param>
///
/// <returns> An object. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var defaultReturnValue = new SolidColorBrush(Colors.Black);
if (value == null) return defaultReturnValue;
double doubleValue = 0.0;
if (value is double)
{
doubleValue = (double)value;
}
else if(value is string)
{
if (string.IsNullOrWhiteSpace(value.ToString())) return defaultReturnValue;
doubleValue = Double.Parse(value.ToString());
}
if (doubleValue < 0.001 && doubleValue > -0.001)
return new SolidColorBrush(Colors.Green);
if(doubleValue > 0)
return new SolidColorBrush(Colors.Green);
if (doubleValue < 0)
return new SolidColorBrush(Colors.Red);
return defaultReturnValue;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Convert back. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
///
/// <param name="value"> The value. </param>
/// <param name="targetType"> Type of the target. </param>
/// <param name="parameter"> The parameter. </param>
/// <param name="culture"> The culture. </param>
///
/// <returns> The back converted. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

BIN
CurrencyTextBoxControl.dll Normal file

Binary file not shown.

44
Data/Database.cs Normal file
View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using DebtMgr.Model;
using SQLite.Net;
using SQLite.Net.Interop;
using SQLite.Net.Platform.Generic;
namespace DebtMgr.Data
{
public class Database : SQLiteConnection
{
#region Constructors
public Database(ISQLitePlatform sqlitePlatform, string databasePath, bool storeDateTimeAsTicks = true, IBlobSerializer serializer = null, IDictionary<string, TableMapping> tableMappings = null, IDictionary<Type, string> extraTypeMappings = null, IContractResolver resolver = null) : base(sqlitePlatform, databasePath, storeDateTimeAsTicks, serializer, tableMappings, extraTypeMappings, resolver)
{
}
public Database(ISQLitePlatform sqlitePlatform, string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks = true, IBlobSerializer serializer = null, IDictionary<string, TableMapping> tableMappings = null, IDictionary<Type, string> extraTypeMappings = null, IContractResolver resolver = null) : base(sqlitePlatform, databasePath, openFlags, storeDateTimeAsTicks, serializer, tableMappings, extraTypeMappings, resolver)
{
}
#endregion
public Database(string databasePath) : base(new SQLitePlatformGeneric(), databasePath)
{
CreateTables();
}
#region CreateTables
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Creates the tables. </summary>
///
/// <remarks> Andre Beging, 08.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void CreateTables()
{
CreateTable<Person>();
CreateTable<Transaction>();
}
#endregion
}
}

188
DebtMgr.csproj Normal file
View File

@@ -0,0 +1,188 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{11FFBAAB-CE28-4B77-8C7A-8B15F0007133}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>DebtMgr</RootNamespace>
<AssemblyName>DebtMgr</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Content\icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="CurrencyTextBoxControl">
<HintPath>.\CurrencyTextBoxControl.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight, Version=5.3.0.19026, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL">
<HintPath>packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight.Extras, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=669f0b5e8f868abf, processorArchitecture=MSIL">
<HintPath>packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Extras.dll</HintPath>
</Reference>
<Reference Include="GalaSoft.MvvmLight.Platform, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=5f873c45e98af8a1, processorArchitecture=MSIL">
<HintPath>packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net, Version=3.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\SQLite.Net-PCL.3.0.5\lib\net40\SQLite.Net.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net.Platform.Generic, Version=3.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\SQLite.Net-PCL.3.0.5\lib\net40\SQLite.Net.Platform.Generic.dll</HintPath>
</Reference>
<Reference Include="SQLite.Net.Platform.Win32, Version=3.0.5.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\SQLite.Net-PCL.3.0.5\lib\net4\SQLite.Net.Platform.Win32.dll</HintPath>
</Reference>
<Reference Include="SQLiteNetExtensions, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\SQLiteNetExtensions.1.3.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\SQLiteNetExtensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Converters\AmountToColorConverter.cs" />
<Compile Include="Data\Database.cs" />
<Compile Include="Extensions\ExtensionMethods.cs" />
<Compile Include="Model\Enums.cs" />
<Compile Include="Model\Transaction.cs" />
<Compile Include="Model\Person.cs" />
<Compile Include="ViewModel\Dialogs\AddTransactionViewModel.cs" />
<Compile Include="ViewModel\Dialogs\DatabaseSelectorDialogViewModel.cs" />
<Compile Include="ViewModel\Dialogs\NewPersonDialogViewModel.cs" />
<Compile Include="ViewModel\MainViewModel.cs" />
<Compile Include="ViewModel\ViewModelLocator.cs" />
<Compile Include="View\Dialogs\AddTransactionView.xaml.cs">
<DependentUpon>AddTransactionView.xaml</DependentUpon>
</Compile>
<Compile Include="View\Dialogs\DatabaseSelectorDialogView.xaml.cs">
<DependentUpon>DatabaseSelectorDialogView.xaml</DependentUpon>
</Compile>
<Compile Include="View\Dialogs\NewPersonDialogView.xaml.cs">
<DependentUpon>NewPersonDialogView.xaml</DependentUpon>
</Compile>
<Compile Include="View\MainView.xaml.cs">
<DependentUpon>MainView.xaml</DependentUpon>
</Compile>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="View\Dialogs\AddTransactionView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\Dialogs\DatabaseSelectorDialogView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\Dialogs\NewPersonDialogView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\MainView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="sqlite3.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Resource Include="Content\icon.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Content\addperson.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Content\delete.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Content\moneybag.ico" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="CurrencyTextBoxControl.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

22
DebtMgr.sln Normal file
View File

@@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.13
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DebtMgr", "DebtMgr.csproj", "{11FFBAAB-CE28-4B77-8C7A-8B15F0007133}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{11FFBAAB-CE28-4B77-8C7A-8B15F0007133}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11FFBAAB-CE28-4B77-8C7A-8B15F0007133}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11FFBAAB-CE28-4B77-8C7A-8B15F0007133}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11FFBAAB-CE28-4B77-8C7A-8B15F0007133}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,54 @@
using System.Globalization;
using System.Windows;
namespace DebtMgr.Extensions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> An extension methods. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public static class ExtensionMethods
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Centers the current window on parent </summary>
///
/// <remarks> Andre Beging, 08.09.2017. </remarks>
///
/// <param name="window"> The window to act on. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
public static void CenterOnParent(this Window window)
{
var curApp = Application.Current;
var mainWindow = curApp.MainWindow;
window.Left = mainWindow.Left + (mainWindow.Width - window.ActualWidth) / 2 - (window.Width / 2);
window.Top = mainWindow.Top + (mainWindow.Height - window.ActualHeight) / 2 - (window.Height / 2);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> A string extension method that gets a double. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
///
/// <param name="value"> The value to act on. </param>
/// <param name="defaultValue"> The default value. </param>
///
/// <returns> The double. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public static double GetDouble(this string value, double defaultValue)
{
double result;
// Try parsing in the current culture
if (!double.TryParse(value, NumberStyles.Any, CultureInfo.CurrentCulture, out result) &&
// Then try in US english
!double.TryParse(value, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out result) &&
// Then in neutral language
!double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out result))
{
result = defaultValue;
}
return result;
}
}
}

19
Model/Enums.cs Normal file
View File

@@ -0,0 +1,19 @@
using System.ComponentModel;
namespace DebtMgr.Model
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Values that represent transaction types. </summary>
///
/// <remarks> Andre Beging, 08.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public enum TransactionType
{
[Description("None")]
None,
[Description("Deposit")]
Deposit,
[Description("Charge")]
Charge
}
}

82
Model/Person.cs Normal file
View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes;
namespace DebtMgr.Model
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> A person. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public class Person
{
#region Id
[PrimaryKey]
public Guid Id { get; set; } = Guid.NewGuid();
#endregion
#region Transaction Relation
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Transaction> Transactions { get; set; } = new List<Transaction>();
#endregion
#region Total
/// <summary> Transaction Total </summary>
public double Total
{
get
{
var sum = 0.0;
foreach (var transaction in Transactions)
{
if (transaction.Type == TransactionType.Charge)
sum -= transaction.Amount;
else if (transaction.Type == TransactionType.Deposit)
sum += transaction.Amount;
}
return sum;
}
}
#endregion
#region FirstName
public string FirstName { get; set; }
#endregion
#region LastName
public string LastName { get; set; }
#endregion
#region ToString()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Convert this object into a string representation. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
///
/// <returns> A string that represents this object. </returns>
////////////////////////////////////////////////////////////////////////////////////////////////////
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
#endregion
}
}

93
Model/Transaction.cs Normal file
View File

@@ -0,0 +1,93 @@
using System;
using System.ComponentModel;
using SQLite.Net.Attributes;
using SQLiteNetExtensions.Attributes;
namespace DebtMgr.Model
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> A transaction. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public class Transaction
{
#region Id
[PrimaryKey]
public Guid Id { get; set; } = Guid.NewGuid();
#endregion
#region Person Relation
[ForeignKey(typeof(Person))]
public Guid PersonId { get; set; }
[ManyToOne]
public Person Person { get; set; }
#endregion
#region Description
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets or sets the description. </summary>
///
/// <value> The description. </value>
////////////////////////////////////////////////////////////////////////////////////////////////////
public string Description { get; set; }
#endregion
#region Type
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets or sets the type. </summary>
///
/// <value> The type. </value>
////////////////////////////////////////////////////////////////////////////////////////////////////
public TransactionType Type
{
get
{
if (!string.IsNullOrWhiteSpace(StringType))
{
return (TransactionType)Enum.Parse(typeof(TransactionType), StringType);
}
return TransactionType.None;
}
set { StringType = value.ToString(); }
}
public string StringType;
#endregion
#region Time
public DateTime Time { get; set; }
#endregion
#region Amount
public double Amount { get; set; }
#endregion
#region SignedAmount
[Ignore]
public double SignedAmount
{
get
{
if (Type == TransactionType.Charge) return Amount * -1;
return Amount;
}
}
#endregion
}
}

View File

@@ -0,0 +1,53 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("DebtMgr")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DebtMgr")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
//<UICulture>ImCodeVerwendeteKultur</UICulture> in der .csproj-Datei
//in einer <PropertyGroup> fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
//(Deutschland) verwenden, legen Sie <UICulture> auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
//(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
// oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
//(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
// designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
)]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

63
Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace DebtMgr.Properties {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DebtMgr.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

117
Properties/Resources.resx Normal file
View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

38
Properties/Settings.Designer.cs generated Normal file
View File

@@ -0,0 +1,38 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace DebtMgr.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string Database {
get {
return ((string)(this["Database"]));
}
set {
this["Database"] = value;
}
}
}
}

View File

@@ -0,0 +1,9 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="DebtMgr.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="Database" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>

View File

@@ -0,0 +1,49 @@
<Window x:Class="DebtMgr.View.Dialogs.AddTransactionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:c="clr-namespace:CurrencyTextBoxControl;assembly=CurrencyTextBoxControl"
mc:Ignorable="d"
Icon="../../Content/moneybag.ico"
Name="AddTransactionViewWindow"
Title="{Binding WindowTitle}" Height="300" Width="300"
KeyUp="Window_OnKeyUp">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical">
<Label Content="{Binding ElementName=AddTransactionViewWindow, Path=Title}" FontWeight="Bold" FontSize="18"></Label>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="10 0">
<c:CurrencyTextBox KeyUp="TextBox_OnKeyUp" Name="Amount" Number="{Binding AmountTextBoxText}" StringFormat="0.00 Eur" FontSize="16" Margin="0 0 0 -5"></c:CurrencyTextBox>
<Label Content="Amount in EUR"></Label>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Vertical" Margin="10 0">
<TextBox KeyUp="TextBox_OnKeyUp" Name="Description" Text="{Binding DescriptionTextBoxText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="16" Margin="0 0 0 -5"></TextBox>
<Label Content="Description"></Label>
</StackPanel>
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="10 0">
<DatePicker KeyUp="TextBox_OnKeyUp" SelectedDate="{Binding DatePickerSelectedDate}"></DatePicker>
<Label Content="Date"></Label>
</StackPanel>
<StackPanel Grid.Row="4" Orientation="Vertical" Margin="10 0">
<ComboBox KeyUp="TextBox_OnKeyUp" Name="PersonComboBox" ItemsSource="{Binding PersonComboBoxItemSource}" SelectedItem="{Binding PersonComboBoxSelectedItem}">
</ComboBox>
<Label Content="Person"></Label>
</StackPanel>
<Grid Grid.Row="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Content="Add Deposit" FontSize="14" Padding="5" Margin="10 -10" Command="{Binding AddTransactionButtonClickCommand}"></Button>
</Grid>
</Grid>
</Window>

View File

@@ -0,0 +1,58 @@
using DebtMgr.Extensions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DebtMgr.Model;
namespace DebtMgr.View.Dialogs
{
/// <summary>
/// Interaktionslogik für AddTransactionView.xaml
/// </summary>
public partial class AddTransactionView : Window
{
public AddTransactionView(TransactionType transactionType, Person preselectedPerson)
{
InitializeComponent();
this.CenterOnParent();
App.Locator.AddTransactionView.ClearView();
App.Locator.AddTransactionView.DialogMode = transactionType;
App.Locator.AddTransactionView.PreselectedPerson = preselectedPerson;
App.Locator.AddTransactionView.SetModeSpecificStrings();
App.Locator.AddTransactionView.RequestClose += (s, e) => Close();
DataContext = App.Locator.AddTransactionView;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Event handler. Called by TextBox for on key up events. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Key event information. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void TextBox_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.Enter) || e.Key.Equals(Key.Return))
App.Locator.AddTransactionView.AddTransactionButtonClickCommand.Execute(null);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Event handler. Called by Window for on key up events. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Key event information. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void Window_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.Escape))
Close();
}
}
}

View File

@@ -0,0 +1,30 @@
<Window x:Class="DebtMgr.View.Dialogs.DatabaseSelectorDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
Title="Debt Manager - Select Database" Height="250" Width="400"
KeyUp="Window_OnKeyUp">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="Select existing Database" FontWeight="Bold" FontSize="18" Margin="0 20 0 0"></Label>
<TextBox Grid.Row="1" Grid.Column="0" FontSize="14" Margin="5 5 0 5" IsEnabled="False" Text="{Binding SelectDatabasePathText}"></TextBox>
<Button Grid.Row="1" Grid.Column="1" FontSize="14" Content="Browse" Margin="5" Command="{Binding SelectDatabaseButtonClick}"></Button>
<Separator Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Margin="0 20"></Separator>
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="Create new Database" FontWeight="Bold" FontSize="18"></Label>
<TextBox Grid.Row="4" Grid.Column="0" FontSize="14" Margin="5 5 0 5" IsEnabled="False"></TextBox>
<Button Grid.Row="4" Grid.Column="1" FontSize="14" Content="Create" Margin="5" Command="{Binding CreateDatabaseButtonClick}"></Button>
</Grid>
</Window>

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using DebtMgr.Extensions;
namespace DebtMgr.View.Dialogs
{
/// <summary>
/// Interaktionslogik für DatabaseSelectorDialogView.xaml
/// </summary>
public partial class DatabaseSelectorDialogView : Window
{
public DatabaseSelectorDialogView()
{
InitializeComponent();
this.CenterOnParent();
App.Locator.DatabaseSelectorDialogView.RequestClose += (s, e) => Close();
DataContext = App.Locator.DatabaseSelectorDialogView;
}
private void Window_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.Escape))
Application.Current.Shutdown();
}
}
}

View File

@@ -0,0 +1,36 @@
<Window x:Class="DebtMgr.View.Dialogs.NewPersonDialogView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:local="clr-namespace:DebtMgr.View.Dialogs"
mc:Ignorable="d"
Name="NewPersonDialogViewWindow"
Icon="../../Content/addperson.ico"
Title="New Person" Height="205" Width="300"
KeyUp="Window_KeyUp">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="New Person" FontWeight="Bold" FontSize="18"></Label>
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="10 0">
<TextBox KeyUp="TextBox_OnKeyUp" Name="FirstNameTextBox" Text="{Binding FirstNameTextBoxText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="16" Margin="0 0 0 -5"></TextBox>
<Label Content="First name"></Label>
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Vertical" Margin="10 5">
<TextBox KeyUp="TextBox_OnKeyUp" Text="{Binding LastNameTextBoxText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="16" Margin="0 0 0 -5"></TextBox>
<Label Content="Last name"></Label>
</StackPanel>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Content="Create Person" FontSize="14" Padding="5" Margin="10 -10" Command="{Binding CreatePersonButtonClickCommand}"></Button>
</Grid>
</Grid>
</Window>

View File

@@ -0,0 +1,51 @@
using System.Windows;
using System.Windows.Input;
using DebtMgr.Extensions;
namespace DebtMgr.View.Dialogs
{
/// <summary>
/// Interaktionslogik für NewPersonDialogView.xaml
/// </summary>
public partial class NewPersonDialogView : Window
{
public NewPersonDialogView()
{
InitializeComponent();
this.CenterOnParent();
App.Locator.NewPersonDialogView.RequestClose += (s, e) => Close();
DataContext = App.Locator.NewPersonDialogView;
FirstNameTextBox.Focus();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Event handler. Called by TextBox for on key up events. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Key event information. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void TextBox_OnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.Enter) || e.Key.Equals(Key.Return))
App.Locator.NewPersonDialogView.CreatePersonButtonClickCommand.Execute(null);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Event handler. Called by Window for key up events. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Key event information. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void Window_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key.Equals(Key.Escape))
Close();
}
}
}

137
View/MainView.xaml Normal file
View File

@@ -0,0 +1,137 @@
<Window x:Class="DebtMgr.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:converters="clr-namespace:DebtMgr.Converters"
mc:Ignorable="d"
Icon="../Content/icon.ico"
Title="Debt Manager" Height="600" Width="900">
<Window.Resources>
<converters:AmountToColorConverter x:Key="AmountToColorConverter" />
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<!-- #region Menu -->
<DockPanel Grid.Row="0">
<Menu DockPanel.Dock="Top">
<MenuItem Header="Person">
<MenuItem Header="_New" Command="{Binding MenuNewPersonCommand}" />
<MenuItem Header="_Manage" IsEnabled="False" />
<Separator />
<MenuItem Header="_Exit" Command="{Binding MenuExitCommand}" />
</MenuItem>
</Menu>
</DockPanel>
<!-- #endregion -->
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- #region PersonListView -->
<Grid Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="Overview" FontWeight="Bold" FontSize="22" Margin="0 0 0 -5"></Label>
<TextBlock Grid.Row="1" FontSize="18" Margin="5 0 0 5">
<TextBlock Text="Overall Balance:"></TextBlock>
<TextBlock Text="{Binding OverallBalanceLabel}" Foreground="{Binding OverallBalanceLabel, Converter={StaticResource AmountToColorConverter}}"></TextBlock>
<TextBlock Text="€" Foreground="{Binding OverallBalanceLabel, Converter={StaticResource AmountToColorConverter}}"></TextBlock>
</TextBlock>
<ListView Name="PersonListView" Grid.Row="2" ItemsSource="{Binding PersonListViewItemSource}" SelectedItem="{Binding PersonListViewSelectedItem}">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding FirstName}" Width="100">
<GridViewColumnHeader Command="{Binding SortPersonListViewCommand}" CommandParameter="FirstName">First name</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding LastName}" Width="100">
<GridViewColumnHeader Command="{Binding SortPersonListViewCommand}" CommandParameter="LastName">Last name</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Width="80">
<GridViewColumnHeader Command="{Binding SortPersonListViewCommand}" CommandParameter="Total">Balance</GridViewColumnHeader>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextAlignment="Right" Foreground="{Binding Total, Converter={StaticResource AmountToColorConverter}}" Text="{Binding Total, StringFormat='{}{0:N} €'}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListBox.Resources>
<ContextMenu x:Key="PersonListViewContextMenu">
<MenuItem Header="Add charge" Command="{Binding AddChargeContextMenuCommand}" />
<MenuItem Header="Add deposit" Command="{Binding AddDepositContextMenuCommand}" />
<MenuItem Header="New Person" Command="{Binding NewPersonContextMenuCommand}" />
<MenuItem Header="Delete Person" Command="{Binding DeletePersonContextMenuCommand}" CommandParameter="{Binding Path=SelectedItem}" />
</ContextMenu>
</ListBox.Resources>
<ListBox.ContextMenu>
<StaticResource ResourceKey="PersonListViewContextMenu" />
</ListBox.ContextMenu>
</ListView>
</Grid>
<!-- #endregion -->
<Grid Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Content="{Binding DetailViewHeaderLabelContent}" FontWeight="Bold" FontSize="22" Margin="0 0 0 -5"></Label>
<TextBlock Grid.Row="1" FontSize="18" Margin="5 0 0 5">
<TextBlock Text="Balance:"></TextBlock>
<TextBlock Text="{Binding DetailViewBalanceLabel}" Foreground="{Binding DetailViewBalanceLabel, Converter={StaticResource AmountToColorConverter}}"></TextBlock>
<TextBlock Text="€" Foreground="{Binding DetailViewBalanceLabel, Converter={StaticResource AmountToColorConverter}}"></TextBlock>
</TextBlock>
<ListView Name="TransactionHistoryListView" Grid.Row="2" ItemsSource="{Binding TransactionHistoryListViewItemSource}" SelectedItem="{Binding TransactionHistoryListViewSelectedItem}" HorizontalContentAlignment="Stretch">
<ListView.View>
<GridView>
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="IsEnabled" Value="False"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
<GridViewColumn DisplayMemberBinding="{Binding Time, StringFormat='{}{0:MMM. yyyy}'}" Width="80" Header="Date" />
<GridViewColumn Width="80" Header="Amount">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock TextAlignment="Right" Foreground="{Binding SignedAmount, Converter={StaticResource AmountToColorConverter}}" Text="{Binding SignedAmount, StringFormat='{}{0:N} €'}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Description}" Width="Auto" Header="Description" />
</GridView>
</ListView.View>
<ListBox.Resources>
<ContextMenu x:Key="TransactionHistoryListViewContextMenu">
<MenuItem Header="Add charge" Command="{Binding AddChargeContextMenuCommand}" />
<MenuItem Header="Add deposit" Command="{Binding AddDepositContextMenuCommand}" />
<MenuItem Header="Delete Transaction" Command="{Binding DeleteTransactionContextMenuCommand}" CommandParameter="{Binding Path=SelectedItem}" />
</ContextMenu>
</ListBox.Resources>
<ListBox.ContextMenu>
<StaticResource ResourceKey="TransactionHistoryListViewContextMenu" />
</ListBox.ContextMenu>
</ListView>
</Grid>
</Grid>
</Grid>
</Window>

68
View/MainView.xaml.cs Normal file
View File

@@ -0,0 +1,68 @@
using System;
using System.Windows;
using System.Windows.Input;
namespace DebtMgr.View
{
/// <summary>
/// Interaktionslogik für MainView.xaml
/// </summary>
public partial class MainView : Window
{
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Default constructor. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public MainView()
{
InitializeComponent();
DataContext = App.Locator.MainView;
PersonListView.KeyUp += PersonListViewOnKeyUp;
TransactionHistoryListView.KeyUp += TransactionHistoryListViewOnKeyUp;
}
#region PersonListViewOnKeyUp()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Person list view on key up. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Key event information. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void PersonListViewOnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
if (App.Locator.MainView.DeletePersonContextMenuCommand.CanExecute(null))
App.Locator.MainView.DeletePersonContextMenuCommand.Execute(null);
}
}
#endregion
#region TransactionHistoryListViewOnKeyUp()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Transaction history list view on key up. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
///
/// <param name="sender"> Source of the event. </param>
/// <param name="e"> Key event information. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void TransactionHistoryListViewOnKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Delete)
{
if (App.Locator.MainView.DeleteTransactionContextMenuCommand.CanExecute(null))
App.Locator.MainView.DeleteTransactionContextMenuCommand.Execute(null);
}
}
#endregion
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
namespace DebtMgr.ViewModel.Dialogs
{
public class AddTransactionViewModel : ViewModelBase
{
}
}

View File

@@ -0,0 +1,301 @@
using DebtMgr.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using SQLiteNetExtensions.Extensions;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
namespace DebtMgr.ViewModel.Dialogs
{
public class AddTransactionViewModel : ViewModelBase
{
#region Public Properties
public event EventHandler RequestClose;
public TransactionType DialogMode { get; set; }
public Person PreselectedPerson { get; set; }
#endregion
#region WindowTitle (string) Property
/// <summary>
/// Privater Teil von <see cref="WindowTitle" />
/// </summary>
private string _windowTitle;
/// <summary>
/// Comment
///</summary>
public string WindowTitle
{
get { return _windowTitle; }
set
{
_windowTitle = value;
RaisePropertyChanged(() => WindowTitle);
}
}
#endregion
#region AmountTextBoxText (string) Property
/// <summary>
/// Privater Teil von <see cref="AmountTextBoxText" />
/// </summary>
private string _amountTextBoxText;
/// <summary>
/// Comment
///</summary>
public string AmountTextBoxText
{
get
{
return _amountTextBoxText;
}
set
{
_amountTextBoxText = value;
RaisePropertyChanged(() => AmountTextBoxText);
AddTransactionButtonClickCommand.RaiseCanExecuteChanged();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets the amount text box text as number representation. </summary>
///
/// <value> The amount text box text number representation. </value>
////////////////////////////////////////////////////////////////////////////////////////////////////
public double AmountTextBoxTextNumberRepresentation
{
get
{
if (string.IsNullOrWhiteSpace(_amountTextBoxText)) return 0.0;
return double.Parse(_amountTextBoxText, CultureInfo.InvariantCulture);
}
}
#endregion
#region DescriptionTextBoxText (string) Property
/// <summary>
/// Privater Teil von <see cref="DescriptionTextBoxText" />
/// </summary>
private string _descriptionTextBoxText;
/// <summary>
/// DescriptionTextBoxText
///</summary>
public string DescriptionTextBoxText
{
get { return _descriptionTextBoxText; }
set
{
_descriptionTextBoxText = value;
RaisePropertyChanged(() => DescriptionTextBoxText);
AddTransactionButtonClickCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region DatePickerSelectedDate (DateTime?) Property
/// <summary>
/// Privater Teil von <see cref="DatePickerSelectedDate" />
/// </summary>
private DateTime? _datePickerSelectedDate;
/// <summary>
/// Comment
///</summary>
public DateTime? DatePickerSelectedDate
{
get { return _datePickerSelectedDate; }
set
{
_datePickerSelectedDate = value;
RaisePropertyChanged(() => DatePickerSelectedDate);
AddTransactionButtonClickCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region PersonComboBoxItemSource (List<Person>) Property
/// <summary>
/// Privater Teil von <see cref="PersonComboBoxItemSource" />
/// </summary>
private List<Person> _personComboBoxItemSource;
/// <summary>
/// Comment
///</summary>
public List<Person> PersonComboBoxItemSource
{
get { return _personComboBoxItemSource; }
set
{
_personComboBoxItemSource = value;
RaisePropertyChanged(() => PersonComboBoxItemSource);
}
}
#endregion
#region PersonComboBoxSelectedItem (Person) Property
/// <summary>
/// Privater Teil von <see cref="PersonComboBoxSelectedItem" />
/// </summary>
private Person _personComboBoxSelectedItem;
/// <summary>
/// Comment
///</summary>
public Person PersonComboBoxSelectedItem
{
get { return _personComboBoxSelectedItem; }
set
{
_personComboBoxSelectedItem = value;
RaisePropertyChanged(() => PersonComboBoxSelectedItem);
AddTransactionButtonClickCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region AddTransactionButtonClickCommand Command
/// <summary>
/// Private member backing variable for <see cref="AddTransactionButtonClickCommand" />
/// </summary>
private RelayCommand _addTransactionButtonClickCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand AddTransactionButtonClickCommand => _addTransactionButtonClickCommand ?? (_addTransactionButtonClickCommand = new RelayCommand(AddTransactionButtonClickCommand_Execute, AddTransactionButtonClickCommand_CanExecute));
private bool AddTransactionButtonClickCommand_CanExecute()
{
if (AmountTextBoxTextNumberRepresentation < 0.01) return false;
if (string.IsNullOrWhiteSpace(DescriptionTextBoxText)) return false;
if (PersonComboBoxSelectedItem == null) return false;
if (DatePickerSelectedDate == null) return false;
return true;
}
private void AddTransactionButtonClickCommand_Execute()
{
if (AddTransactionButtonClickCommand_CanExecute())
{
try
{
var person = App.Database.Get<Person>(PersonComboBoxSelectedItem.Id);
App.Database.GetChildren(person);
if (DatePickerSelectedDate != null)
person.Transactions.Add(new Transaction
{
Amount = AmountTextBoxTextNumberRepresentation,
Type = DialogMode,
Description = DescriptionTextBoxText,
PersonId = person.Id,
Time = DatePickerSelectedDate.Value
});
App.Database.InsertOrReplaceWithChildren(person);
RequestClose?.Invoke(null, null);
App.Locator.MainView.UpdatePersonsList();
}
catch (Exception)
{
MessageBox.Show("Something bad happened", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Default constructor. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public AddTransactionViewModel()
{
UpdatesPersonsComboBox();
}
#region UpdatesPersonsComboBox()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Updates persons combo box. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void UpdatesPersonsComboBox()
{
var personList = App.Database.Table<Person>().OrderBy(x => x.FirstName).ToList();
PersonComboBoxItemSource = personList;
}
#endregion
#region SetModeSpecificStrings()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Sets mode specific strings. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void SetModeSpecificStrings()
{
if (DialogMode == TransactionType.Deposit)
{
WindowTitle = "Add Deposit";
}
if (DialogMode == TransactionType.Charge)
{
WindowTitle = "Add Charge";
}
PersonComboBoxSelectedItem =
PersonComboBoxItemSource.FirstOrDefault(x => x.Id == PreselectedPerson?.Id);
}
#endregion
#region ClearView()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Clears the view. </summary>
///
/// <remarks> Andre Beging, 09.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void ClearView()
{
AmountTextBoxText = string.Empty;
DescriptionTextBoxText = string.Empty;
PersonComboBoxSelectedItem = null;
DatePickerSelectedDate = DateTime.Now;
}
#endregion
}
}

View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using DebtMgr.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Win32;
using SQLite.Net;
using SQLite.Net.Platform.Generic;
namespace DebtMgr.ViewModel.Dialogs
{
public class DatabaseSelectorDialogViewModel : ViewModelBase
{
public event EventHandler RequestClose;
#region SelectDatabasePathText (string) Property
/// <summary>
/// Privater Teil von <see cref="SelectDatabasePathText" />
/// </summary>
private string _selectDatabasePathText;
/// <summary>
/// Comment
///</summary>
public string SelectDatabasePathText
{
get { return _selectDatabasePathText; }
set
{
_selectDatabasePathText = value;
RaisePropertyChanged(() => SelectDatabasePathText);
}
}
#endregion
#region SelectDatabaseButtonClick Command
/// <summary>
/// Private member backing variable for <see cref="SelectDatabaseButtonClick" />
/// </summary>
private RelayCommand _selectDatabaseButtonClick = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand SelectDatabaseButtonClick => _selectDatabaseButtonClick ?? (_selectDatabaseButtonClick = new RelayCommand(SelectDatabaseButtonClick_Execute));
private void SelectDatabaseButtonClick_Execute()
{
var openFileDialog = new OpenFileDialog();
openFileDialog.CheckFileExists = true;
openFileDialog.Filter = "Debt Manager Database|*.dmdb|All files|*.*";
//Application.Current.Shutdown();
if (openFileDialog.ShowDialog() == true)
{
var x = new SQLiteConnection(new SQLitePlatformGeneric(), openFileDialog.FileName);
try
{
x.Table<Person>().ToList();
Properties.Settings.Default["Database"] = openFileDialog.FileName;
Properties.Settings.Default.Save();
RequestClose?.Invoke(null, null);
}
catch (Exception)
{
MessageBox.Show(
string.Format("File is not a Debt Manager database\n\n{0}", openFileDialog.FileName),
"File invalid",
MessageBoxButton.OK,
MessageBoxImage.Error);
}
finally
{
x.Close();
}
}
}
#endregion
#region CreateDatabaseButtonClick Command
/// <summary>
/// Private member backing variable for <see cref="CreateDatabaseButtonClick" />
/// </summary>
private RelayCommand _createDatabaseButtonClick = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand CreateDatabaseButtonClick => _createDatabaseButtonClick ?? (_createDatabaseButtonClick = new RelayCommand(CreateDatabaseButtonClick_Execute));
private void CreateDatabaseButtonClick_Execute()
{
var saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Debt Manager Database|*.dmdb|Standard database|*.db";
saveFileDialog.CreatePrompt = true;
if (saveFileDialog.ShowDialog() == true)
{
Properties.Settings.Default["Database"] = saveFileDialog.FileName;
Properties.Settings.Default.Save();
RequestClose?.Invoke(null, null);
}
}
#endregion
}
}

View File

@@ -0,0 +1,125 @@
using System;
using System.Windows;
using DebtMgr.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
namespace DebtMgr.ViewModel.Dialogs
{
public class NewPersonDialogViewModel : ViewModelBase
{
public event EventHandler RequestClose;
#region FirstNameTextBoxText (string) Property
/// <summary>
/// Privater Teil von <see cref="FirstNameTextBoxText" />
/// </summary>
private string _firstNameTextBoxText;
/// <summary>
/// Comment
///</summary>
public string FirstNameTextBoxText
{
get { return _firstNameTextBoxText; }
set
{
_firstNameTextBoxText = value;
RaisePropertyChanged(() => FirstNameTextBoxText);
CreatePersonButtonClickCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region LastNameTextBoxText (string) Property
/// <summary>
/// Privater Teil von <see cref="LastNameTextBoxText" />
/// </summary>
private string _lastNameTextBoxText;
/// <summary>
/// Comment
///</summary>
public string LastNameTextBoxText
{
get { return _lastNameTextBoxText; }
set
{
_lastNameTextBoxText = value;
RaisePropertyChanged(() => LastNameTextBoxText);
CreatePersonButtonClickCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region CreatePersonButtonClickCommand Command
/// <summary>
/// Private member backing variable for <see cref="CreatePersonButtonClickCommand" />
/// </summary>
private RelayCommand _createPersonButtonClickCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand CreatePersonButtonClickCommand => _createPersonButtonClickCommand ?? (_createPersonButtonClickCommand = new RelayCommand(CreatePersonButtonClickCommand_Execute, CreatePersonButtonClickCommand_CanExecute));
private bool CreatePersonButtonClickCommand_CanExecute()
{
if (string.IsNullOrWhiteSpace(FirstNameTextBoxText) || string.IsNullOrWhiteSpace(LastNameTextBoxText))
{
return false;
}
return true;
}
private void CreatePersonButtonClickCommand_Execute()
{
if (CreatePersonButtonClickCommand_CanExecute())
{
var newPerson = new Person
{
FirstName = FirstNameTextBoxText,
LastName = LastNameTextBoxText
};
var resultId = App.Database.Insert(newPerson);
if (resultId == 1)
{
App.Locator.MainView.UpdatePersonsList();
App.Locator.AddTransactionView.UpdatesPersonsComboBox();
RequestClose?.Invoke(null, null);
ClearView();
}
else
{
MessageBox.Show("Something bad happened", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
#endregion
#region ClearView()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Clears the view. </summary>
///
/// <remarks> Andre Beging, 08.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void ClearView()
{
FirstNameTextBoxText = string.Empty;
LastNameTextBoxText = string.Empty;
}
#endregion
}
}

488
ViewModel/MainViewModel.cs Normal file
View File

@@ -0,0 +1,488 @@
using DebtMgr.Model;
using DebtMgr.View.Dialogs;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using SQLiteNetExtensions.Extensions;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System;
using System.Configuration;
using SQLite.Net;
using SQLite.Net.Platform.Generic;
namespace DebtMgr.ViewModel
{
public class MainViewModel : ViewModelBase
{
#region PersonListViewItemSource (List<Person>) Property
/// <summary>
/// Privater Teil von <see cref="PersonListViewItemSource" />
/// </summary>
private List<Person> _personListViewItemSource;
/// <summary>
/// Comment
///</summary>
public List<Person> PersonListViewItemSource
{
get { return _personListViewItemSource; }
set
{
_personListViewItemSource = value;
RaisePropertyChanged(() => PersonListViewItemSource);
}
}
#endregion
#region PersonListViewSelectedItem (Person) Property
/// <summary>
/// Privater Teil von <see cref="PersonListViewSelectedItem" />
/// </summary>
private Person _personListViewSelectedItem;
/// <summary>
/// PersonListViewSelectedItem
///</summary>
public Person PersonListViewSelectedItem
{
get { return _personListViewSelectedItem; }
set
{
_personListViewSelectedItem = value;
RaisePropertyChanged(() => PersonListViewSelectedItem);
DeletePersonContextMenuCommand.RaiseCanExecuteChanged();
UpdateDetailView();
}
}
#endregion
#region DetailViewHeaderLabelContent (string) Property
/// <summary>
/// Privater Teil von <see cref="DetailViewHeaderLabelContent" />
/// </summary>
private string _detailViewHeaderLabelContent;
/// <summary>
/// Comment
///</summary>
public string DetailViewHeaderLabelContent
{
get { return _detailViewHeaderLabelContent; }
set
{
_detailViewHeaderLabelContent = value;
RaisePropertyChanged(() => DetailViewHeaderLabelContent);
}
}
#endregion
#region DetailViewBalanceLabel (string) Property
/// <summary>
/// Privater Teil von <see cref="DetailViewBalanceLabel" />
/// </summary>
private string _detailViewBalanceLabel;
/// <summary>
/// Comment
///</summary>
public string DetailViewBalanceLabel
{
get { return _detailViewBalanceLabel; }
set
{
_detailViewBalanceLabel = value;
RaisePropertyChanged(() => DetailViewBalanceLabel);
}
}
#endregion
#region OverallBalanceLabel (string) Property
/// <summary>
/// Privater Teil von <see cref="OverallBalanceLabel" />
/// </summary>
private string _overallBalanceLabel;
/// <summary>
/// Comment
///</summary>
public string OverallBalanceLabel
{
get { return _overallBalanceLabel; }
set
{
_overallBalanceLabel = value;
RaisePropertyChanged(() => OverallBalanceLabel);
}
}
#endregion
#region TransactionHistoryListViewItemSource (List<Transaction>) Property
/// <summary>
/// Privater Teil von <see cref="TransactionHistoryListViewItemSource" />
/// </summary>
private List<Transaction> _transactionHistoryListViewItemSource;
/// <summary>
/// Comment
///</summary>
public List<Transaction> TransactionHistoryListViewItemSource
{
get { return _transactionHistoryListViewItemSource; }
set
{
_transactionHistoryListViewItemSource = value;
RaisePropertyChanged(() => TransactionHistoryListViewItemSource);
}
}
#endregion
#region TransactionHistoryListViewSelectedItem (Transaction) Property
/// <summary>
/// Privater Teil von <see cref="TransactionHistoryListViewSelectedItem" />
/// </summary>
private Transaction _transactionHistoryListViewSelectedItem;
/// <summary>
/// Comment
///</summary>
public Transaction TransactionHistoryListViewSelectedItem
{
get { return _transactionHistoryListViewSelectedItem; }
set
{
_transactionHistoryListViewSelectedItem = value;
RaisePropertyChanged(() => TransactionHistoryListViewSelectedItem);
DeleteTransactionContextMenuCommand.RaiseCanExecuteChanged();
}
}
#endregion
#region MenuNewPersonCommand Command
/// <summary>
/// Private member backing variable for <see cref="MenuNewPersonCommand" />
/// </summary>
private RelayCommand _menuNewPersonCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand MenuNewPersonCommand => _menuNewPersonCommand ?? (_menuNewPersonCommand = new RelayCommand(MenuNewPersonCommand_Execute, MenuNewPersonCommand_CanExecute));
private bool MenuNewPersonCommand_CanExecute()
{
return true;
}
private void MenuNewPersonCommand_Execute()
{
var window = new NewPersonDialogView();
window.ShowDialog();
}
#endregion
#region SortPersonListViewCommand
/// <summary> The sort person list view command. </summary>
private RelayCommand<string> _sortPersonListViewCommand = null;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Gets the sort person list view command. </summary>
///
/// <value> The sort person list view command. </value>
////////////////////////////////////////////////////////////////////////////////////////////////////
public RelayCommand<string> SortPersonListViewCommand
{
get
{
if (_sortPersonListViewCommand == null)
_sortPersonListViewCommand = new RelayCommand<string>(SortPersonListViewCommand_Execute);
return _sortPersonListViewCommand;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Sort person list view command execute. </summary>
///
/// <remarks> Andre Beging, 08.09.2017. </remarks>
///
/// <param name="columnName"> Name of the column. </param>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void SortPersonListViewCommand_Execute(string columnName)
{
if (string.IsNullOrWhiteSpace(columnName)) return;
switch (columnName)
{
case "FirstName":
PersonListViewItemSource = PersonListViewItemSource.OrderBy(x => x.FirstName).ToList();
break;
case "LastName":
PersonListViewItemSource = PersonListViewItemSource.OrderBy(x => x.LastName).ToList();
break;
case "Total":
PersonListViewItemSource = PersonListViewItemSource.OrderBy(x => x.Total).ToList();
break;
}
}
#endregion
#region AddChargeContextMenuCommand Command
/// <summary>
/// Private member backing variable for <see cref="AddChargeContextMenuCommand" />
/// </summary>
private RelayCommand _addChargeContextMenuCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand AddChargeContextMenuCommand => _addChargeContextMenuCommand ?? (_addChargeContextMenuCommand = new RelayCommand(AddChargeContextMenuCommand_Execute));
private void AddChargeContextMenuCommand_Execute()
{
var window = new AddTransactionView(TransactionType.Charge, PersonListViewSelectedItem);
window.ShowDialog();
}
#endregion
#region AddDepositContextMenuCommand Command
/// <summary>
/// Private member backing variable for <see cref="AddDepositContextMenuCommand" />
/// </summary>
private RelayCommand _addDepositContextMenuCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand AddDepositContextMenuCommand => _addDepositContextMenuCommand ?? (_addDepositContextMenuCommand = new RelayCommand(AddDepositContextMenuCommand_Execute));
private void AddDepositContextMenuCommand_Execute()
{
var window = new AddTransactionView(TransactionType.Deposit, PersonListViewSelectedItem);
window.ShowDialog();
}
#endregion
#region NewPersonContextMenuCommand Command
/// <summary>
/// Private member backing variable for <see cref="NewPersonContextMenuCommand" />
/// </summary>
private RelayCommand _newPersonContextMenuCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand NewPersonContextMenuCommand => _newPersonContextMenuCommand ?? (_newPersonContextMenuCommand = new RelayCommand(NewPersonContextMenuCommand_Execute));
private void NewPersonContextMenuCommand_Execute()
{
var window = new NewPersonDialogView();
window.ShowDialog();
}
#endregion
#region DeletePersonContextMenuCommand Command
/// <summary>
/// Private member backing variable for <see cref="DeletePersonContextMenuCommand" />
/// </summary>
private RelayCommand _deletePersonContextMenuCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand DeletePersonContextMenuCommand => _deletePersonContextMenuCommand ?? (_deletePersonContextMenuCommand = new RelayCommand(DeletePersonContextMenuCommand_Execute, DeletePersonContextMenuCommand_CanExecute));
private bool DeletePersonContextMenuCommand_CanExecute()
{
if (PersonListViewSelectedItem != null)
return true;
return false;
}
private void DeletePersonContextMenuCommand_Execute()
{
if (PersonListViewSelectedItem == null) return;
var result = MessageBox.Show(
string.Format(
"Are you sure to delete?\n\n{0} {1}",
PersonListViewSelectedItem.FirstName,
PersonListViewSelectedItem.LastName),
"Delete Person",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
App.Database.Delete<Person>(PersonListViewSelectedItem.Id);
UpdatePersonsList();
}
}
#endregion
#region DeleteTransactionContextMenuCommand Command
/// <summary>
/// Private member backing variable for <see cref="DeleteTransactionContextMenuCommand" />
/// </summary>
private RelayCommand _deleteTransactionContextMenuCommand = null;
/// <summary>
/// Comment
/// </summary>
public RelayCommand DeleteTransactionContextMenuCommand => _deleteTransactionContextMenuCommand ?? (_deleteTransactionContextMenuCommand = new RelayCommand(DeleteTransactionContextMenuCommand_Execute, DeleteTransactionContextMenuCommand_CanExecute));
private bool DeleteTransactionContextMenuCommand_CanExecute()
{
if (TransactionHistoryListViewSelectedItem != null)
return true;
return false;
}
private void DeleteTransactionContextMenuCommand_Execute()
{
if (TransactionHistoryListViewSelectedItem == null) return;
var result = MessageBox.Show(
string.Format(
"Are you sure to delete?\n\n{1} <20>\n{0}",
TransactionHistoryListViewSelectedItem.Description,
TransactionHistoryListViewSelectedItem.Amount),
"Delete Transaction",
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
App.Database.Delete<Transaction>(TransactionHistoryListViewSelectedItem.Id);
UpdatePersonsList();
}
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Initializes a new instance of the MainViewModel class. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public MainViewModel()
{
CheckDatabase();
UpdatePersonsList();
UpdateDetailView();
}
#region UpdatePersonsList()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Updates the persons list. </summary>
///
/// <remarks> Andre Beging, 08.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
public void UpdatePersonsList()
{
// Remember selection
var rememberSelection = PersonListViewSelectedItem?.Id;
var personList = App.Database.GetAllWithChildren<Person>();
PersonListViewItemSource = personList;
var overallBalance = personList.Sum(x => x.Total);
OverallBalanceLabel = overallBalance.ToString();
// Restore selection
if (rememberSelection != null && PersonListViewItemSource.Any(x => x.Id == rememberSelection))
PersonListViewSelectedItem = PersonListViewItemSource.First(x => x.Id == rememberSelection);
UpdateDetailView();
}
#endregion
#region UpdateDetailView()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Updates the detail view. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void UpdateDetailView()
{
if (PersonListViewSelectedItem == null)
{
DetailViewHeaderLabelContent = string.Empty;
DetailViewBalanceLabel = string.Empty;
TransactionHistoryListViewItemSource = null;
return;
};
DetailViewHeaderLabelContent = string.Format("{0} {1}", PersonListViewSelectedItem.FirstName,
PersonListViewSelectedItem.LastName);
DetailViewBalanceLabel = PersonListViewSelectedItem.Total.ToString();
TransactionHistoryListViewItemSource = PersonListViewSelectedItem.Transactions.OrderByDescending(x => x.Time).ToList();
}
#endregion
#region CheckDatabase()
////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary> Check database. </summary>
///
/// <remarks> Andre Beging, 10.09.2017. </remarks>
////////////////////////////////////////////////////////////////////////////////////////////////////
private void CheckDatabase()
{
var databasePath = Properties.Settings.Default.Database;
if (string.IsNullOrWhiteSpace(databasePath))
{
var window = new DatabaseSelectorDialogView();
var result = window.ShowDialog();
}
// Check if provided file path is a valid database
try
{
App.Database.Table<Person>();
}
catch (Exception)
{
Properties.Settings.Default["Database"] = string.Empty;
CheckDatabase();
}
}
#endregion
}
}

View File

@@ -0,0 +1,61 @@
/*
In App.xaml:
<Application.Resources>
<vm:ViewModelLocator xmlns:vm="clr-namespace:DebtMgr"
x:Key="Locator" />
</Application.Resources>
In the View:
DataContext="{Binding Source={StaticResource Locator}, Path=ViewModelName}"
You can also use Blend to do all this with the tool's support.
See http://www.galasoft.ch/mvvm
*/
using DebtMgr.ViewModel.Dialogs;
using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
namespace DebtMgr.ViewModel
{
/// <summary>
/// This class contains static references to all the view models in the
/// application and provides an entry point for the bindings.
/// </summary>
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
////if (ViewModelBase.IsInDesignModeStatic)
////{
//// // Create design time view services and models
//// SimpleIoc.Default.Register<IDataService, DesignDataService>();
////}
////else
////{
//// // Create run time view services and models
//// SimpleIoc.Default.Register<IDataService, DataService>();
////}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<NewPersonDialogViewModel>();
SimpleIoc.Default.Register<AddTransactionViewModel>();
SimpleIoc.Default.Register<DatabaseSelectorDialogViewModel>();
}
public MainViewModel MainView => ServiceLocator.Current.GetInstance<MainViewModel>();
public NewPersonDialogViewModel NewPersonDialogView => ServiceLocator.Current.GetInstance<NewPersonDialogViewModel>();
public AddTransactionViewModel AddTransactionView => ServiceLocator.Current.GetInstance<AddTransactionViewModel>();
public DatabaseSelectorDialogViewModel DatabaseSelectorDialogView => ServiceLocator.Current.GetInstance<DatabaseSelectorDialogViewModel>();
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
}

9
packages.config Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonServiceLocator" version="1.3" targetFramework="net452" />
<package id="MvvmLight" version="5.3.0.0" targetFramework="net452" />
<package id="MvvmLightLibs" version="5.3.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net452" />
<package id="SQLite.Net-PCL" version="3.0.5" targetFramework="net452" />
<package id="SQLiteNetExtensions" version="1.3.0" targetFramework="net452" />
</packages>

BIN
sqlite3.dll Normal file

Binary file not shown.