Implemented displaying errors.

This commit is contained in:
Tobias Erbshäußer
2020-06-10 13:31:48 +02:00
parent 0300090806
commit 9313ecb775
17 changed files with 1800 additions and 11 deletions
+2
View File
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/CodeAnnotations/NamespacesWithAnnotations/=ucalc_002EAnnotations/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
+1378
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -4,6 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCalc"
xmlns:controls="clr-namespace:UCalc.Controls"
mc:Ignorable="d"
Title="MietRechner"
Width="800"
@@ -21,7 +22,8 @@
<TabControl Name="TabControl"
BorderBrush="White">
<TabItem Visibility="Collapsed">
<Frame Source="Pages/LandlordPage.xaml"/>
<Frame Source="Pages/LandlordPage.xaml"
LoadCompleted="OnLandlordFrameLoadCompleted"/>
</TabItem>
<TabItem Visibility="Collapsed">
<Frame Source="Pages/HousePage.xaml"/>
+14 -3
View File
@@ -1,22 +1,25 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using UCalc.Data;
using UCalc.Models;
using UCalc.Pages;
namespace UCalc
{
public partial class BillingWindow
{
private readonly Billing _savedBilling;
public Billing Billing { get; }
public BillingModel Model { get; }
public BillingWindow(Billing savedBilling, Billing billing)
{
_savedBilling = savedBilling;
Billing = billing;
InitializeComponent();
Model = new BillingModel(Billing);
Title =
$"MietRechner - Abrechnung von {billing.StartDate.ToShortDateString()} - {billing.EndDate.Date.ToShortDateString()}";
}
@@ -28,9 +31,17 @@ namespace UCalc
private void OnSideBarFrameLoadCompleted(object sender, NavigationEventArgs e)
{
var sideBar = (SideBar) SideBarFrame.Content;
var sideBar = (SideBar) ((Frame) sender).Content;
sideBar.TabControl = TabControl;
sideBar.LandlordButton.Selected = true;
sideBar.Model = Model;
}
private void OnLandlordFrameLoadCompleted(object sender, NavigationEventArgs e)
{
var page = (LandlordPage) ((Frame) sender).Content;
page.Model = Model.LandlordModel;
}
}
}
+12 -2
View File
@@ -5,5 +5,15 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCalc.Controls"
mc:Ignorable="d">
<Grid />
</UserControl>
<Border CornerRadius="3"
BorderBrush="Red"
Background="Red">
<Label
Content="{Binding Path=Model.ErrorCount, RelativeSource={RelativeSource AncestorType=local:ErrorCounter}}"
Foreground="White" />
</Border>
</UserControl>
+9 -1
View File
@@ -1,7 +1,15 @@
namespace UCalc.Controls
using System.Windows;
using UCalc.Models;
namespace UCalc.Controls
{
public partial class ErrorCounter
{
public Model Model { get; set; }
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register(
"Model", typeof(Model), typeof(ErrorCounter), new PropertyMetadata((Model) null));
public ErrorCounter()
{
InitializeComponent();
+51
View File
@@ -0,0 +1,51 @@
<UserControl x:Class="UCalc.Controls.ErrorIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCalc.Controls"
mc:Ignorable="d"
Width="16"
Height="16">
<UserControl.Resources>
<local:ErrorToVisibilityConverter x:Key="ErrorToVisibilityConverter" />
<local:ErrorToInVisibilityConverter x:Key="ErrorToInVisibilityConverter" />
</UserControl.Resources>
<StackPanel ToolTip="{Binding Path=Error, RelativeSource={RelativeSource AncestorType=local:ErrorIcon}}">
<Viewbox
Visibility="{Binding Path=Error, RelativeSource={RelativeSource AncestorType=local:ErrorIcon}, Converter={StaticResource ErrorToInVisibilityConverter}}"
Stretch="Uniform">
<Canvas Width="512" Height="512">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0" />
</Canvas.RenderTransform>
<Path Fill="DarkGreen">
<Path.Data>
<PathGeometry
Figures="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"
FillRule="NonZero" />
</Path.Data>
</Path>
</Canvas>
</Viewbox>
<Viewbox
Visibility="{Binding Path=Error, RelativeSource={RelativeSource AncestorType=local:ErrorIcon}, Converter={StaticResource ErrorToVisibilityConverter}}"
Stretch="Uniform">
<Canvas Width="512" Height="512">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0" />
</Canvas.RenderTransform>
<Path Fill="Red">
<Path.Data>
<PathGeometry
Figures="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"
FillRule="NonZero" />
</Path.Data>
</Path>
</Canvas>
</Viewbox>
</StackPanel>
</UserControl>
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.Windows;
using System.Windows.Data;
namespace UCalc.Controls
{
public class ErrorToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null || "".Equals(value))
{
return Visibility.Collapsed;
}
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new InvalidOperationException();
}
}
public class ErrorToInVisibilityConverter : IValueConverter
{
private readonly ErrorToVisibilityConverter _converter = new ErrorToVisibilityConverter();
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var result = _converter.Convert(value, targetType, parameter, culture) as Visibility?;
return result == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new InvalidOperationException();
}
}
public partial class ErrorIcon
{
public string Error { get; set; }
public static readonly DependencyProperty ErrorProperty = DependencyProperty.Register(
"Error", typeof(string), typeof(ErrorIcon), new PropertyMetadata((string) null));
public ErrorIcon()
{
InitializeComponent();
}
}
}
+21
View File
@@ -0,0 +1,21 @@
using UCalc.Data;
namespace UCalc.Models
{
public class BillingModel : Model
{
public LandlordModel LandlordModel { get; }
public BillingModel(Billing billing)
{
LandlordModel = new LandlordModel(billing.Landlord);
Properties = LandlordModel.Properties;
}
public override void Apply()
{
LandlordModel.Apply();
}
}
}
+20
View File
@@ -0,0 +1,20 @@
using UCalc.Data;
namespace UCalc.Models
{
public class HouseModel : Model
{
private readonly House _data;
public ModelProperty<string> Street { get; }
public ModelProperty<string> HouseNumber { get; }
public ModelProperty<string> City { get; }
public ModelProperty<string> Postcode { get; }
// TODO: Flats?
public HouseModel(House data)
{
_data = data;
}
}
}
+79
View File
@@ -0,0 +1,79 @@
using UCalc.Data;
namespace UCalc.Models
{
public class LandlordModel : Model
{
private readonly Landlord _data;
public ModelProperty<int> Salutation { get; }
public ModelProperty<string> Name { get; }
public ModelProperty<string> MailAddress { get; }
public ModelProperty<string> Phone { get; }
public ModelProperty<string> Street { get; }
public ModelProperty<string> HouseNumber { get; }
public ModelProperty<string> City { get; }
public ModelProperty<string> Postcode { get; }
public ModelProperty<string> Iban { get; }
public ModelProperty<string> Bic { get; }
public ModelProperty<string> BankName { get; }
public LandlordModel(Landlord data)
{
_data = data;
Salutation = new ModelProperty<int>(this, (int) _data.Salutation, null);
Name = new ModelProperty<string>(this, _data.Name, ModelPropertyValidators.IsNotEmpty);
MailAddress = new ModelProperty<string>(this, _data.MailAddress, ModelPropertyValidators.IsNotEmpty);
Phone = new ModelProperty<string>(this, _data.Phone, ModelPropertyValidators.IsNotEmpty);
Street = new ModelProperty<string>(this, _data.Address.Street, ModelPropertyValidators.IsNotEmpty);
HouseNumber =
new ModelProperty<string>(this, _data.Address.HouseNumber, ModelPropertyValidators.IsNotEmpty);
City = new ModelProperty<string>(this, _data.Address.City, ModelPropertyValidators.IsNotEmpty);
Postcode = new ModelProperty<string>(this, _data.Address.Postcode, ModelPropertyValidators.IsNotEmpty);
Iban = new ModelProperty<string>(this, _data.BankAccount.Iban, ModelPropertyValidators.IsNotEmpty);
Bic = new ModelProperty<string>(this, _data.BankAccount.Bic, ModelPropertyValidators.IsNotEmpty);
BankName = new ModelProperty<string>(this, _data.BankAccount.BankName, ModelPropertyValidators.IsNotEmpty);
Properties = new ModelProperty[]
{Salutation, Name, MailAddress, Phone, Street, HouseNumber, City, Postcode, Iban, Bic, BankName};
}
public override void Apply()
{
base.Apply();
_data.Salutation = (Salutation) Salutation.Value;
Salutation.Modified = false;
_data.Name = Name.Value;
Name.Modified = false;
_data.MailAddress = MailAddress.Value;
MailAddress.Modified = false;
_data.Phone = Phone.Value;
Phone.Modified = false;
_data.Address.Street = Street.Value;
Street.Modified = false;
_data.Address.HouseNumber = HouseNumber.Value;
HouseNumber.Modified = false;
_data.Address.City = City.Value;
City.Modified = false;
_data.Address.Postcode = Postcode.Value;
Postcode.Modified = false;
_data.BankAccount.Iban = Iban.Value;
Iban.Modified = false;
_data.BankAccount.Bic = Bic.Value;
Bic.Modified = false;
_data.BankAccount.BankName = BankName.Value;
BankName.Modified = false;
}
}
}
+118
View File
@@ -0,0 +1,118 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using ucalc.Annotations;
namespace UCalc.Models
{
public class ModelProperty : INotifyPropertyChanged
{
private readonly Model _model;
private object _value;
private string _error;
private readonly Func<object, string> _validate;
public object Value
{
get => _value;
set
{
if (_value.Equals(value))
{
return;
}
var oldError = Error;
Error = _validate?.Invoke(value);
if (oldError == null && Error != null || oldError != null && Error == null)
{
_model.OnPropertyChanged("ErrorCount");
}
Modified = true;
_value = value;
}
}
public string Error
{
get => _error;
private set
{
if (_error == value)
{
return;
}
_error = value;
OnPropertyChanged();
}
}
public bool Modified { get; set; }
public ModelProperty(Model model, object value, Func<object, string> validate)
{
_model = model;
_value = value;
_error = validate?.Invoke(value);
_validate = validate;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class ModelProperty<T> : ModelProperty
{
public new T Value
{
get => (T) base.Value;
set => base.Value = value;
}
public ModelProperty(Model model, T value, Func<T, string> validate) : base(model, value,
validate == null ? (Func<object, string>) null : o => validate((T) o))
{
}
}
public static class ModelPropertyValidators
{
public static string IsNotEmpty(string data)
{
return string.IsNullOrEmpty(data) ? "Geben Sie einen Wert ein" : null;
}
}
public abstract class Model : INotifyPropertyChanged
{
public ModelProperty[] Properties { get; protected set; }
public bool Modified => Properties.Select(property => property.Modified).Any();
public int ErrorCount => Properties.Select(property => string.IsNullOrEmpty(property.Error) ? 0 : 1).Sum();
public virtual void Apply()
{
if (ErrorCount > 0)
{
throw new InvalidOperationException();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
+19 -2
View File
@@ -4,6 +4,23 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCalc.Pages"
xmlns:controls="clr-namespace:UCalc.Controls"
mc:Ignorable="d">
<Grid />
</Page>
<ScrollViewer>
<StackPanel>
<DockPanel>
<Label DockPanel.Dock="Left" Content="Name:" />
<controls:ErrorIcon DockPanel.Dock="Right"
Error="{Binding Path=Model.Name.Error, RelativeSource={RelativeSource AncestorType=local:LandlordPage}}" />
<TextBox
Text="{Binding Path=Model.Name.Value, RelativeSource={RelativeSource AncestorType=local:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
</DockPanel>
</StackPanel>
</ScrollViewer>
</Page>
+4 -2
View File
@@ -1,9 +1,11 @@
using System.Windows.Controls;
using UCalc.Models;
namespace UCalc.Pages
{
public partial class LandlordPage : Page
public partial class LandlordPage
{
public LandlordModel Model { get; set; }
public LandlordPage()
{
InitializeComponent();
+7
View File
@@ -5,6 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:UCalc"
xmlns:controls="clr-namespace:UCalc.Controls"
xmlns:pages="clr-namespace:UCalc.Pages"
mc:Ignorable="d"
Background="{x:Static local:Constants.SubMainColor}">
@@ -115,6 +116,12 @@
</Canvas>
</Viewbox>
<controls:ErrorCounter x:Name="LandlordErrorCounter"
DockPanel.Dock="Right"
Margin="0, 12, 12, 12"
VerticalAlignment="Center"
Model="{Binding Path=Model.LandlordModel, RelativeSource={RelativeSource AncestorType=pages:SideBar}}"/>
<Label Content="Vermieter"
Margin="0, 12, 12, 12"
VerticalAlignment="Center"
+2
View File
@@ -2,12 +2,14 @@
using System.Windows;
using System.Windows.Controls;
using UCalc.Controls;
using UCalc.Models;
namespace UCalc.Pages
{
public partial class SideBar
{
public TabControl TabControl { get; set; }
public BillingModel Model { get; set; }
public SideBar()
{
+6
View File
@@ -31,6 +31,9 @@
<Page Update="Controls\ErrorCounter.xaml">
<Generator></Generator>
</Page>
<Page Update="Controls\ErrorIcon.xaml">
<Generator></Generator>
</Page>
</ItemGroup>
<ItemGroup>
@@ -58,6 +61,9 @@
<Compile Update="Controls\ErrorCounter.xaml.cs">
<DependentUpon>ErrorCounter.xaml</DependentUpon>
</Compile>
<Compile Update="Controls\ErrorIcon.xaml.cs">
<DependentUpon>ErrorIcon.xaml</DependentUpon>
</Compile>
</ItemGroup>
</Project>