Implemented tenant model.
This commit is contained in:
@@ -17,26 +17,33 @@
|
|||||||
<Frame Name="SideBarFrame"
|
<Frame Name="SideBarFrame"
|
||||||
Source="Pages/SideBar.xaml"
|
Source="Pages/SideBar.xaml"
|
||||||
Width="240"
|
Width="240"
|
||||||
LoadCompleted="OnSideBarFrameLoadCompleted"/>
|
LoadCompleted="OnSideBarFrameLoadCompleted"
|
||||||
|
Focusable="False" />
|
||||||
|
|
||||||
<TabControl Name="TabControl"
|
<TabControl Name="TabControl"
|
||||||
BorderBrush="White">
|
BorderBrush="White">
|
||||||
<TabItem Visibility="Collapsed">
|
<TabItem Visibility="Collapsed">
|
||||||
<Frame Source="Pages/LandlordPage.xaml"
|
<Frame Source="Pages/LandlordPage.xaml"
|
||||||
LoadCompleted="OnLandlordFrameLoadCompleted"/>
|
LoadCompleted="OnLandlordFrameLoadCompleted"
|
||||||
|
Focusable="False" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem Visibility="Collapsed">
|
<TabItem Visibility="Collapsed">
|
||||||
<Frame Source="Pages/HousePage.xaml"
|
<Frame Source="Pages/HousePage.xaml"
|
||||||
LoadCompleted="OnHouseFrameLoadCompleted"/>
|
LoadCompleted="OnHouseFrameLoadCompleted"
|
||||||
|
Focusable="False" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem Visibility="Collapsed">
|
<TabItem Visibility="Collapsed">
|
||||||
<Frame Source="Pages/TenantsPage.xaml"/>
|
<Frame Source="Pages/TenantsPage.xaml"
|
||||||
|
LoadCompleted="OnTenantsFrameLoadCompleted"
|
||||||
|
Focusable="False" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem Visibility="Collapsed">
|
<TabItem Visibility="Collapsed">
|
||||||
<Frame Source="Pages/CostsPage.xaml"/>
|
<Frame Source="Pages/CostsPage.xaml"
|
||||||
|
Focusable="False" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
<TabItem Visibility="Collapsed">
|
<TabItem Visibility="Collapsed">
|
||||||
<Frame Source="Pages/DetailsPage.xaml"/>
|
<Frame Source="Pages/DetailsPage.xaml"
|
||||||
|
Focusable="False" />
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|||||||
@@ -10,18 +10,16 @@ namespace UCalc
|
|||||||
{
|
{
|
||||||
public partial class BillingWindow
|
public partial class BillingWindow
|
||||||
{
|
{
|
||||||
public Billing Billing { get; }
|
public Model Model { get; }
|
||||||
public BillingModel Model { get; }
|
|
||||||
|
|
||||||
public BillingWindow(Billing savedBilling, Billing billing)
|
public BillingWindow(Billing billing)
|
||||||
{
|
{
|
||||||
Billing = billing;
|
Model = new Model(billing);
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Model = new BillingModel(Billing);
|
|
||||||
|
|
||||||
Title =
|
Title =
|
||||||
$"MietRechner - Abrechnung von {billing.StartDate.ToShortDateString()} - {billing.EndDate.Date.ToShortDateString()}";
|
$"MietRechner - Abrechnung von {billing.StartDate.ToString(Constants.DateFormat)} - {billing.EndDate.Date.ToString(Constants.DateFormat)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnClosed(object sender, EventArgs e)
|
private void OnClosed(object sender, EventArgs e)
|
||||||
@@ -41,13 +39,21 @@ namespace UCalc
|
|||||||
private void OnLandlordFrameLoadCompleted(object sender, NavigationEventArgs e)
|
private void OnLandlordFrameLoadCompleted(object sender, NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
var page = (LandlordPage) ((Frame) sender).Content;
|
var page = (LandlordPage) ((Frame) sender).Content;
|
||||||
page.Model = Model.LandlordModel;
|
page.Landlord = Model.Root.Landlord;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnHouseFrameLoadCompleted(object sender, NavigationEventArgs e)
|
private void OnHouseFrameLoadCompleted(object sender, NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
var page = (HousePage) ((Frame) sender).Content;
|
var page = (HousePage) ((Frame) sender).Content;
|
||||||
page.Model = Model.HouseModel;
|
page.House = Model.Root.House;
|
||||||
|
page.ParentWindow = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTenantsFrameLoadCompleted(object sender, NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
var page = (TenantsPage) ((Frame) sender).Content;
|
||||||
|
page.Tenants = Model.Root.Tenants;
|
||||||
|
page.House = Model.Root.House;
|
||||||
page.ParentWindow = this;
|
page.ParentWindow = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace UCalc
|
|||||||
public static readonly SolidColorBrush MainColor = Brushes.White;
|
public static readonly SolidColorBrush MainColor = Brushes.White;
|
||||||
public static readonly SolidColorBrush SubMainColor = new SolidColorBrush(Color.FromRgb(0x00, 0x7A, 0xCC));
|
public static readonly SolidColorBrush SubMainColor = new SolidColorBrush(Color.FromRgb(0x00, 0x7A, 0xCC));
|
||||||
|
|
||||||
|
public const string DecimalFormat = ".00";
|
||||||
|
public const string DateFormat = "dd.MM.yyyy";
|
||||||
|
|
||||||
public static readonly ImmutableList<string> SalutationStrs =
|
public static readonly ImmutableList<string> SalutationStrs =
|
||||||
((Salutation[]) Enum.GetValues(typeof(Salutation))).Select(value => value.AsString()).ToImmutableList();
|
((Salutation[]) Enum.GetValues(typeof(Salutation))).Select(value => value.AsString()).ToImmutableList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
|
using UCalc.Models;
|
||||||
|
|
||||||
namespace UCalc.Controls
|
namespace UCalc.Controls
|
||||||
{
|
{
|
||||||
public class ErrorsToVisibilityConverter : IValueConverter
|
public class ErrorsToVisibilityConverter : IValueConverter
|
||||||
{
|
{
|
||||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
return (((ICollection<string>) value)?.Count ?? 0) == 0 ? Visibility.Collapsed : Visibility.Visible;
|
return (((ICollection<string>) value)?.Count ?? 0) == 0 ? Visibility.Collapsed : Visibility.Visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter,
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
System.Globalization.CultureInfo culture)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
@@ -23,31 +24,93 @@ namespace UCalc.Controls
|
|||||||
{
|
{
|
||||||
private readonly ErrorsToVisibilityConverter _converter = new ErrorsToVisibilityConverter();
|
private readonly ErrorsToVisibilityConverter _converter = new ErrorsToVisibilityConverter();
|
||||||
|
|
||||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
var result = _converter.Convert(value, targetType, parameter, culture) as Visibility?;
|
var result = _converter.Convert(value, targetType, parameter, culture) as Visibility?;
|
||||||
return result == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
|
return result == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter,
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
System.Globalization.CultureInfo culture)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ErrorsToCountConverter : IValueConverter
|
||||||
public class ErrorCountToVisibilityConverter : IValueConverter
|
|
||||||
{
|
{
|
||||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
{
|
{
|
||||||
return (int?) value != 0 ? Visibility.Visible : Visibility.Collapsed;
|
return ((ICollection<string>) value)?.Count ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter,
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
System.Globalization.CultureInfo culture)
|
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ErrorsToToolTipConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
var errors = (IReadOnlyList<string>) value;
|
||||||
|
|
||||||
|
return (errors?.Count ?? 0) == 0 ? null : string.Join("\n", errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FlatToRentedConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public TenantProperty Tenant { get; set; }
|
||||||
|
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return Tenant.RentedFlats.Contains((FlatProperty) value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmptyMultiPropertyToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
return value?.Equals(0) ?? false ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DatePickerTextToDateTimeConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
var dateTime = (DateTime?) value;
|
||||||
|
|
||||||
|
return dateTime == null ? "" : dateTime.Value.ToString(Constants.DateFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
var str = (string) value;
|
||||||
|
|
||||||
|
if (DateTime.TryParseExact(str, Constants.DateFormat, null, DateTimeStyles.None, out var d))
|
||||||
|
{
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,16 +7,17 @@
|
|||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<local:ErrorCountToVisibilityConverter x:Key="ErrorCountToVisibilityConverter" />
|
<local:ErrorsToVisibilityConverter x:Key="ErrorsToVisibilityConverter" />
|
||||||
|
<local:ErrorsToCountConverter x:Key="ErrorsToCountConverter" />
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
|
||||||
<Border CornerRadius="3"
|
<Border CornerRadius="3"
|
||||||
BorderBrush="Red"
|
BorderBrush="Red"
|
||||||
Background="Red"
|
Background="Red"
|
||||||
Visibility="{Binding Path=Model.ErrorCount, RelativeSource={RelativeSource AncestorType=local:ErrorCounter}, Converter={StaticResource ErrorCountToVisibilityConverter}}">
|
Visibility="{Binding Path=Property.Errors, RelativeSource={RelativeSource AncestorType=local:ErrorCounter}, Converter={StaticResource ErrorsToVisibilityConverter}}">
|
||||||
|
|
||||||
<Label
|
<Label
|
||||||
Content="{Binding Path=Model.ErrorCount, RelativeSource={RelativeSource AncestorType=local:ErrorCounter}}"
|
Content="{Binding Path=Property.Errors, RelativeSource={RelativeSource AncestorType=local:ErrorCounter}, Converter={StaticResource ErrorsToCountConverter}}"
|
||||||
Foreground="White" />
|
Foreground="White" />
|
||||||
|
|
||||||
</Border>
|
</Border>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ namespace UCalc.Controls
|
|||||||
{
|
{
|
||||||
public partial class ErrorCounter
|
public partial class ErrorCounter
|
||||||
{
|
{
|
||||||
public Model Model { get; set; }
|
public Property Property { get; set; }
|
||||||
|
|
||||||
public static readonly DependencyProperty ModelProperty = DependencyProperty.Register(
|
public static readonly DependencyProperty PropertyProperty = DependencyProperty.Register(
|
||||||
"Model", typeof(Model), typeof(ErrorCounter), new PropertyMetadata((Model) null));
|
"Property", typeof(Property), typeof(ErrorCounter), new PropertyMetadata((Property) null));
|
||||||
|
|
||||||
public ErrorCounter()
|
public ErrorCounter()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,11 +11,12 @@
|
|||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<controls:ErrorsToVisibilityConverter x:Key="ErrorsToVisibilityConverter" />
|
<controls:ErrorsToVisibilityConverter x:Key="ErrorsToVisibilityConverter" />
|
||||||
<controls:ErrorsToInVisibilityConverter x:Key="ErrorsToInVisibilityConverter" />
|
<controls:ErrorsToInVisibilityConverter x:Key="ErrorsToInVisibilityConverter" />
|
||||||
|
<controls:ErrorsToToolTipConverter x:Key="ErrorsToToolTipConverter" />
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
|
||||||
<StackPanel ToolTip="{Binding Path=ErrorsToolTip, RelativeSource={RelativeSource AncestorType=controls:ErrorIcon}}">
|
<StackPanel ToolTip="{Binding Path=Property.Errors, RelativeSource={RelativeSource AncestorType=controls:ErrorIcon}, Converter={StaticResource ErrorsToToolTipConverter}}">
|
||||||
<Viewbox
|
<Viewbox
|
||||||
Visibility="{Binding Path=Errors, RelativeSource={RelativeSource AncestorType=controls:ErrorIcon}, Converter={StaticResource ErrorsToInVisibilityConverter}}"
|
Visibility="{Binding Path=Property.Errors, RelativeSource={RelativeSource AncestorType=controls:ErrorIcon}, Converter={StaticResource ErrorsToInVisibilityConverter}}"
|
||||||
Stretch="Uniform">
|
Stretch="Uniform">
|
||||||
<Canvas Width="512" Height="512">
|
<Canvas Width="512" Height="512">
|
||||||
<Canvas.RenderTransform>
|
<Canvas.RenderTransform>
|
||||||
@@ -32,7 +33,7 @@
|
|||||||
</Viewbox>
|
</Viewbox>
|
||||||
|
|
||||||
<Viewbox
|
<Viewbox
|
||||||
Visibility="{Binding Path=Errors, RelativeSource={RelativeSource AncestorType=controls:ErrorIcon}, Converter={StaticResource ErrorsToVisibilityConverter}}"
|
Visibility="{Binding Path=Property.Errors, RelativeSource={RelativeSource AncestorType=controls:ErrorIcon}, Converter={StaticResource ErrorsToVisibilityConverter}}"
|
||||||
Stretch="Uniform">
|
Stretch="Uniform">
|
||||||
<Canvas Width="512" Height="512">
|
<Canvas Width="512" Height="512">
|
||||||
<Canvas.RenderTransform>
|
<Canvas.RenderTransform>
|
||||||
|
|||||||
@@ -1,40 +1,18 @@
|
|||||||
using System.Collections.Generic;
|
using System.Windows;
|
||||||
using System.ComponentModel;
|
using UCalc.Models;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Windows;
|
|
||||||
using UCalc.Annotations;
|
|
||||||
|
|
||||||
namespace UCalc.Controls
|
namespace UCalc.Controls
|
||||||
{
|
{
|
||||||
public partial class ErrorIcon : INotifyPropertyChanged
|
public partial class ErrorIcon
|
||||||
{
|
{
|
||||||
public ICollection<string> Errors { get; set; }
|
public Property Property { get; set; }
|
||||||
|
|
||||||
public string ErrorsToolTip { get; private set; }
|
public static readonly DependencyProperty PropertyProperty = DependencyProperty.Register(
|
||||||
|
"Property", typeof(Property), typeof(ErrorIcon), new PropertyMetadata((Property) null));
|
||||||
public static readonly DependencyProperty ErrorsProperty = DependencyProperty.Register(
|
|
||||||
"Errors", typeof(ICollection<string>), typeof(ErrorIcon),
|
|
||||||
new PropertyMetadata(null, OnErrorsChanged));
|
|
||||||
|
|
||||||
public ErrorIcon()
|
public ErrorIcon()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnErrorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
var self = (ErrorIcon) d;
|
|
||||||
var newErrors = (ICollection<string>) e.NewValue;
|
|
||||||
self.ErrorsToolTip = newErrors.Count > 0 ? string.Join("\n", newErrors) : null;
|
|
||||||
self.OnPropertyChanged("ErrorsToolTip");
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
@@ -26,5 +27,15 @@ namespace UCalc.Controls
|
|||||||
path.Fill = brush;
|
path.Fill = brush;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsBetween(this DateTime dt, DateTime start, DateTime end)
|
||||||
|
{
|
||||||
|
return dt >= start && dt <= end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Intersects(this DateTime start1, DateTime end1, DateTime start2, DateTime end2)
|
||||||
|
{
|
||||||
|
return start1.IsBetween(start2, end2) || start2.IsBetween(start1, end1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ namespace UCalc.Data
|
|||||||
public int PersonCount { get; set; }
|
public int PersonCount { get; set; }
|
||||||
public BankAccount BankAccount { get; private set; }
|
public BankAccount BankAccount { get; private set; }
|
||||||
public DateTime? EntryDate { get; set; }
|
public DateTime? EntryDate { get; set; }
|
||||||
public DateTime? DepatureDate { get; set; }
|
public DateTime? DepartureDate { get; set; }
|
||||||
public HashSet<Flat> RentedFlats { get; private set; }
|
public HashSet<Flat> RentedFlats { get; private set; }
|
||||||
public decimal PaidRent { get; set; }
|
public decimal PaidRent { get; set; }
|
||||||
public string CustomMessage1 { get; set; }
|
public string CustomMessage1 { get; set; }
|
||||||
@@ -185,7 +185,7 @@ namespace UCalc.Data
|
|||||||
{
|
{
|
||||||
return Id.Equals(other.Id) && Salutation == other.Salutation && Name == other.Name &&
|
return Id.Equals(other.Id) && Salutation == other.Salutation && Name == other.Name &&
|
||||||
PersonCount == other.PersonCount && Equals(BankAccount, other.BankAccount) &&
|
PersonCount == other.PersonCount && Equals(BankAccount, other.BankAccount) &&
|
||||||
Nullable.Equals(EntryDate, other.EntryDate) && Nullable.Equals(DepatureDate, other.DepatureDate) &&
|
Nullable.Equals(EntryDate, other.EntryDate) && Nullable.Equals(DepartureDate, other.DepartureDate) &&
|
||||||
RentedFlats.SequenceEqual(other.RentedFlats) && PaidRent == other.PaidRent &&
|
RentedFlats.SequenceEqual(other.RentedFlats) && PaidRent == other.PaidRent &&
|
||||||
CustomMessage1 == other.CustomMessage1 && CustomMessage2 == other.CustomMessage2;
|
CustomMessage1 == other.CustomMessage1 && CustomMessage2 == other.CustomMessage2;
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ namespace UCalc.Data
|
|||||||
PersonCount = PersonCount,
|
PersonCount = PersonCount,
|
||||||
BankAccount = BankAccount.Clone(),
|
BankAccount = BankAccount.Clone(),
|
||||||
EntryDate = EntryDate,
|
EntryDate = EntryDate,
|
||||||
DepatureDate = DepatureDate,
|
DepartureDate = DepartureDate,
|
||||||
RentedFlats = new HashSet<Flat>(RentedFlats.Select(flat => flatMapper[flat])),
|
RentedFlats = new HashSet<Flat>(RentedFlats.Select(flat => flatMapper[flat])),
|
||||||
PaidRent = PaidRent,
|
PaidRent = PaidRent,
|
||||||
CustomMessage1 = CustomMessage1,
|
CustomMessage1 = CustomMessage1,
|
||||||
|
|||||||
@@ -43,12 +43,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Name.Errors, RelativeSource={RelativeSource AncestorType=local:FlatWindow}}" />
|
Property="{Binding Path=Flat.Name, RelativeSource={RelativeSource AncestorType=local:FlatWindow}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Name.Value, RelativeSource={RelativeSource AncestorType=local:FlatWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Flat.Name.Value, RelativeSource={RelativeSource AncestorType=local:FlatWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -60,12 +60,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Size.Errors, RelativeSource={RelativeSource AncestorType=local:FlatWindow}}" />
|
Property="{Binding Path=Flat.Size, RelativeSource={RelativeSource AncestorType=local:FlatWindow}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Size.Value, RelativeSource={RelativeSource AncestorType=local:FlatWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Flat.Size.Value, RelativeSource={RelativeSource AncestorType=local:FlatWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ namespace UCalc
|
|||||||
{
|
{
|
||||||
public partial class FlatWindow
|
public partial class FlatWindow
|
||||||
{
|
{
|
||||||
public FlatModel Model { get; }
|
public FlatProperty Flat { get; }
|
||||||
|
|
||||||
public FlatWindow(FlatModel model)
|
public FlatWindow(FlatProperty flat)
|
||||||
{
|
{
|
||||||
Model = model;
|
Flat = flat;
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
Title="MietRechner"
|
Title="MietRechner"
|
||||||
Height="400"
|
Height="400"
|
||||||
Width="500"
|
Width="500"
|
||||||
|
WindowStartupLocation="CenterScreen"
|
||||||
ResizeMode="CanMinimize">
|
ResizeMode="CanMinimize">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace UCalc
|
|||||||
|
|
||||||
if (newWindow.ShowDialog() == true)
|
if (newWindow.ShowDialog() == true)
|
||||||
{
|
{
|
||||||
new BillingWindow(newWindow.SavedBilling, newWindow.Billing).Show();
|
new BillingWindow(newWindow.Billing).Show();
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ namespace UCalc
|
|||||||
var billing = new BillingLoader().Load(path);
|
var billing = new BillingLoader().Load(path);
|
||||||
App.RecentlyOpenedList.Add(new RecentlyOpenedItem(path));
|
App.RecentlyOpenedList.Add(new RecentlyOpenedItem(path));
|
||||||
|
|
||||||
new BillingWindow(billing, billing.Clone()).Show();
|
new BillingWindow(billing).Show();
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
catch (IOException)
|
catch (IOException)
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
using UCalc.Data;
|
|
||||||
|
|
||||||
namespace UCalc.Models
|
|
||||||
{
|
|
||||||
public class AddressModel : Model
|
|
||||||
{
|
|
||||||
private readonly Address _data;
|
|
||||||
public ModelProperty<string> Street { get; }
|
|
||||||
public ModelProperty<string> HouseNumber { get; }
|
|
||||||
public ModelProperty<string> City { get; }
|
|
||||||
public ModelProperty<string> Postcode { get; }
|
|
||||||
|
|
||||||
public AddressModel(Address data)
|
|
||||||
{
|
|
||||||
_data = data;
|
|
||||||
|
|
||||||
Street = Add(new ModelProperty<string>("Straße", _data.Street, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
HouseNumber =
|
|
||||||
Add(new ModelProperty<string>("Hausnummer", _data.HouseNumber, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
City = Add(new ModelProperty<string>("Stadt", _data.City, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
Postcode = Add(new ModelProperty<string>("PLZ", _data.Postcode, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply()
|
|
||||||
{
|
|
||||||
_data.Street = Street.Value;
|
|
||||||
Street.ResetModified();
|
|
||||||
|
|
||||||
_data.HouseNumber = HouseNumber.Value;
|
|
||||||
HouseNumber.ResetModified();
|
|
||||||
|
|
||||||
_data.City = City.Value;
|
|
||||||
City.ResetModified();
|
|
||||||
|
|
||||||
_data.Postcode = Postcode.Value;
|
|
||||||
Postcode.ResetModified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class AddressProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public NotEmptyStringProperty Street { get; }
|
||||||
|
public NotEmptyStringProperty HouseNumber { get; }
|
||||||
|
public NotEmptyStringProperty City { get; }
|
||||||
|
public NotEmptyStringProperty Postcode { get; }
|
||||||
|
|
||||||
|
public AddressProperty(Model model, Property parent, Address data) : base(model, parent)
|
||||||
|
{
|
||||||
|
Street = Add(new NotEmptyStringProperty(model, this, "Straße", data.Street));
|
||||||
|
HouseNumber = Add(new NotEmptyStringProperty(model, this, "Hausnummer", data.HouseNumber));
|
||||||
|
City = Add(new NotEmptyStringProperty(model, this, "Stadt", data.City));
|
||||||
|
Postcode = Add(new NotEmptyStringProperty(model, this, "PLZ", data.Postcode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using UCalc.Data;
|
|
||||||
|
|
||||||
namespace UCalc.Models
|
|
||||||
{
|
|
||||||
public class BankAccountModel : Model
|
|
||||||
{
|
|
||||||
private readonly BankAccount _data;
|
|
||||||
public ModelProperty<string> Iban { get; }
|
|
||||||
public ModelProperty<string> Bic { get; }
|
|
||||||
public ModelProperty<string> BankName { get; }
|
|
||||||
|
|
||||||
public BankAccountModel(BankAccount data)
|
|
||||||
{
|
|
||||||
_data = data;
|
|
||||||
|
|
||||||
Iban = Add(new ModelProperty<string>("IBAN", _data.Iban, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
Bic = Add(new ModelProperty<string>("BIC", _data.Bic, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
BankName = Add(new ModelProperty<string>("Name der Bank", _data.BankName,
|
|
||||||
ModelPropertyValidators.IsNotEmpty));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply()
|
|
||||||
{
|
|
||||||
_data.Iban = Iban.Value;
|
|
||||||
Iban.ResetModified();
|
|
||||||
|
|
||||||
_data.Bic = Bic.Value;
|
|
||||||
Bic.ResetModified();
|
|
||||||
|
|
||||||
_data.BankName = BankName.Value;
|
|
||||||
BankName.ResetModified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class BankAccountProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public NotEmptyStringProperty Iban { get; }
|
||||||
|
public NotEmptyStringProperty Bic { get; }
|
||||||
|
public NotEmptyStringProperty BankName { get; }
|
||||||
|
|
||||||
|
public BankAccountProperty(Model model, Property parent, BankAccount data) : base(model, parent)
|
||||||
|
{
|
||||||
|
Iban = Add(new NotEmptyStringProperty(model, this, "IBAN", data.Iban));
|
||||||
|
Bic = Add(new NotEmptyStringProperty(model, this, "BIC", data.Bic));
|
||||||
|
BankName = Add(new NotEmptyStringProperty(model, this, "Name der Bank", data.BankName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using UCalc.Data;
|
|
||||||
|
|
||||||
namespace UCalc.Models
|
|
||||||
{
|
|
||||||
public class BillingModel : Model
|
|
||||||
{
|
|
||||||
public LandlordModel LandlordModel { get; }
|
|
||||||
public HouseModel HouseModel { get; }
|
|
||||||
|
|
||||||
public BillingModel(Billing billing)
|
|
||||||
{
|
|
||||||
LandlordModel = new LandlordModel(billing.Landlord);
|
|
||||||
HouseModel = new HouseModel(billing.House);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply()
|
|
||||||
{
|
|
||||||
LandlordModel.Apply();
|
|
||||||
HouseModel.Apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class BillingProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public LandlordProperty Landlord { get; }
|
||||||
|
public HouseProperty House { get; }
|
||||||
|
public TenantsProperty Tenants { get; }
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Costs
|
||||||
|
|
||||||
|
public BillingProperty(Model model, Property parent, Billing data) : base(model, parent)
|
||||||
|
{
|
||||||
|
Landlord = Add(new LandlordProperty(model, this, data.Landlord));
|
||||||
|
House = Add(new HouseProperty(model, this, data.House));
|
||||||
|
|
||||||
|
var flatToProperty = new Dictionary<Flat, FlatProperty>();
|
||||||
|
for (var i = 0; i < data.House.Flats.Count; ++i)
|
||||||
|
{
|
||||||
|
flatToProperty.Add(data.House.Flats[i], House.Flats[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tenants = Add(new TenantsProperty(model, this, data.Tenants, flatToProperty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using UCalc.Data;
|
|
||||||
|
|
||||||
namespace UCalc.Models
|
|
||||||
{
|
|
||||||
public class FlatModel : Model
|
|
||||||
{
|
|
||||||
public Flat Data { get; }
|
|
||||||
public ModelProperty<string> Name { get; }
|
|
||||||
public ModelProperty<string> Size { get; }
|
|
||||||
|
|
||||||
public FlatModel(Flat data, IReadOnlyList<Flat> flats)
|
|
||||||
{
|
|
||||||
Data = data;
|
|
||||||
|
|
||||||
Name = Add(new ModelProperty<string>("Name", Data.Name, (name, value) =>
|
|
||||||
{
|
|
||||||
var error = ModelPropertyValidators.IsNotEmpty(name, value);
|
|
||||||
|
|
||||||
if (error == "" && flats.Any(flat => !ReferenceEquals(flat, Data) && flat.Name == value))
|
|
||||||
{
|
|
||||||
error = $"{name}: Der Wert \"{value}\" ist nicht eindeutig.";
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}));
|
|
||||||
Size = Add(new ModelProperty<string>("Größe", Data.Size.ToString(), ModelPropertyValidators.IsNaturalInt));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply()
|
|
||||||
{
|
|
||||||
Data.Name = Name.Value;
|
|
||||||
Name.ResetModified();
|
|
||||||
|
|
||||||
Data.Size = int.TryParse(Size.Value, out var n) && n > 0 ? n : 0;
|
|
||||||
Size.ResetModified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class FlatNameProperty : ValueProperty<string>
|
||||||
|
{
|
||||||
|
public FlatNameProperty(Model model, Property parent, string name, string value) : base(model, parent, name,
|
||||||
|
value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
var error = "";
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
if (Model.Root.House.Flats.Any(flat => !ReferenceEquals(this, flat.Name) && flat.Name.Value == Value))
|
||||||
|
{
|
||||||
|
error = $"{Name}: Der Name ist nicht eindeutig.";
|
||||||
|
}
|
||||||
|
|
||||||
|
validator.ValidateRange(Model.Root.House.Flats.Select(flat => flat.Name));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FlatProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public FlatNameProperty Name { get; }
|
||||||
|
public NaturalNumberProperty Size { get; }
|
||||||
|
|
||||||
|
public FlatProperty(Model model, Property parent, Flat data) : base(model, parent)
|
||||||
|
{
|
||||||
|
Name = Add(new FlatNameProperty(model, this, "Name", data.Name));
|
||||||
|
Size = Add(new NaturalNumberProperty(model, this, "Größe", data.Size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class FlatsProperty : MultiProperty<FlatProperty>
|
||||||
|
{
|
||||||
|
public FlatsProperty(Model model, Property parent, IEnumerable<Flat> data) : base(model, parent,
|
||||||
|
"Wohnungen: Geben Sie eine oder mehr Wohnungen an.")
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
foreach (var flat in data)
|
||||||
|
{
|
||||||
|
base.Add(new FlatProperty(Model, this, flat));
|
||||||
|
}
|
||||||
|
|
||||||
|
Modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add()
|
||||||
|
{
|
||||||
|
FlatProperty flat;
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
flat = new FlatProperty(Model, this, new Flat {Name = $"Wohnung {Properties.Count + 1}"});
|
||||||
|
base.Add(flat);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Validate(flat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void Remove(FlatProperty flat)
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
base.Remove(flat);
|
||||||
|
|
||||||
|
// Revalidate flat names and flat lists in tenants and costs
|
||||||
|
validator.ValidateRange(Properties.Select(otherFlat => otherFlat.Name));
|
||||||
|
|
||||||
|
foreach (var tenant in Model.Root.Tenants)
|
||||||
|
{
|
||||||
|
tenant.RentedFlats.Remove(flat);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Revalidate all flats + revalidate tenant rent lists + costs flat lists
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
using UCalc.Data;
|
|
||||||
|
|
||||||
namespace UCalc.Models
|
|
||||||
{
|
|
||||||
public class HouseModel : Model
|
|
||||||
{
|
|
||||||
private readonly House _data;
|
|
||||||
public NestedModelProperty<AddressModel> Address { get; }
|
|
||||||
public MultiModelProperty<FlatModel> Flats { get; }
|
|
||||||
|
|
||||||
public HouseModel(House data)
|
|
||||||
{
|
|
||||||
_data = data;
|
|
||||||
|
|
||||||
Address = Add(new NestedModelProperty<AddressModel>(new AddressModel(_data.Address)));
|
|
||||||
Flats = Add(new MultiModelProperty<FlatModel>());
|
|
||||||
|
|
||||||
foreach (var flat in data.Flats)
|
|
||||||
{
|
|
||||||
Flats.Add(new FlatModel(flat, _data.Flats));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply()
|
|
||||||
{
|
|
||||||
Address.Model.Apply();
|
|
||||||
|
|
||||||
foreach (var model in Flats.Models)
|
|
||||||
{
|
|
||||||
model.Apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public FlatModel AddFlat()
|
|
||||||
{
|
|
||||||
var flat = new Flat {Name = $"Wohnung {_data.Flats.Count + 1}"};
|
|
||||||
_data.Flats.Add(flat);
|
|
||||||
|
|
||||||
var model = new FlatModel(flat, _data.Flats);
|
|
||||||
Flats.Add(model);
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveFlat(FlatModel model)
|
|
||||||
{
|
|
||||||
_data.Flats.Remove(model.Data);
|
|
||||||
|
|
||||||
Flats.Remove(model);
|
|
||||||
|
|
||||||
if (model.Errors.Count > 0)
|
|
||||||
{
|
|
||||||
OnPropertyChanged("Errors");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class HouseProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public AddressProperty Address { get; }
|
||||||
|
public FlatsProperty Flats { get; }
|
||||||
|
|
||||||
|
public HouseProperty(Model model, Property parent, House data) : base(model, parent)
|
||||||
|
{
|
||||||
|
Address = Add(new AddressProperty(model, this, data.Address));
|
||||||
|
Flats = Add(new FlatsProperty(model, this, data.Flats));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
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 NestedModelProperty<AddressModel> Address { get; }
|
|
||||||
public NestedModelProperty<BankAccountModel> BankAccount { get; }
|
|
||||||
|
|
||||||
public LandlordModel(Landlord data)
|
|
||||||
{
|
|
||||||
_data = data;
|
|
||||||
|
|
||||||
Salutation = Add(new ModelProperty<int>("Anrede", (int) _data.Salutation, null));
|
|
||||||
Name = Add(new ModelProperty<string>("Name", _data.Name, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
MailAddress =
|
|
||||||
Add(new ModelProperty<string>("Email Adresse", _data.MailAddress, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
Phone = Add(new ModelProperty<string>("Telefonnummer", _data.Phone, ModelPropertyValidators.IsNotEmpty));
|
|
||||||
Address = Add(new NestedModelProperty<AddressModel>(new AddressModel(_data.Address)));
|
|
||||||
BankAccount = Add(new NestedModelProperty<BankAccountModel>(new BankAccountModel(_data.BankAccount)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Apply()
|
|
||||||
{
|
|
||||||
_data.Salutation = (Salutation) Salutation.Value;
|
|
||||||
Salutation.ResetModified();
|
|
||||||
|
|
||||||
_data.Name = Name.Value;
|
|
||||||
Name.ResetModified();
|
|
||||||
|
|
||||||
_data.MailAddress = MailAddress.Value;
|
|
||||||
MailAddress.ResetModified();
|
|
||||||
|
|
||||||
_data.Phone = Phone.Value;
|
|
||||||
Phone.ResetModified();
|
|
||||||
|
|
||||||
Address.Model.Apply();
|
|
||||||
|
|
||||||
BankAccount.Model.Apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class LandlordProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public SalutationProperty Salutation { get; }
|
||||||
|
public NotEmptyStringProperty Name { get; }
|
||||||
|
public NotEmptyStringProperty MailAddress { get; }
|
||||||
|
public NotEmptyStringProperty Phone { get; }
|
||||||
|
public AddressProperty Address { get; }
|
||||||
|
public BankAccountProperty BankAccount { get; }
|
||||||
|
|
||||||
|
public LandlordProperty(Model model, Property parent, Landlord data) : base(model, parent)
|
||||||
|
{
|
||||||
|
Salutation = Add(new SalutationProperty(model, this, "Anrede", data.Salutation));
|
||||||
|
Name = Add(new NotEmptyStringProperty(model, this, "Name", data.Name));
|
||||||
|
MailAddress = Add(new NotEmptyStringProperty(model, this, "Email Adresse", data.MailAddress));
|
||||||
|
Phone = Add(new NotEmptyStringProperty(model, this, "Telefonnummer", data.Phone));
|
||||||
|
Address = Add(new AddressProperty(model, this, data.Address));
|
||||||
|
BankAccount = Add(new BankAccountProperty(model, this, data.BankAccount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
-188
@@ -1,234 +1,152 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using UCalc.Annotations;
|
using UCalc.Annotations;
|
||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
namespace UCalc.Models
|
namespace UCalc.Models
|
||||||
{
|
{
|
||||||
public abstract class ModelBaseProperty : INotifyPropertyChanged
|
public class Model : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
protected static readonly List<string> EmptyList = new List<string>();
|
public class Validator : IDisposable
|
||||||
public abstract IReadOnlyCollection<string> Errors { get; }
|
|
||||||
public abstract bool Modified { get; }
|
|
||||||
|
|
||||||
protected void OnChildPropertyChanged(object sender, PropertyChangedEventArgs args)
|
|
||||||
{
|
{
|
||||||
if (args.PropertyName == "Errors" || args.PropertyName == "Modified")
|
private readonly Model _model;
|
||||||
|
private int _counter;
|
||||||
|
private readonly HashSet<Property> _validated;
|
||||||
|
private readonly HashSet<Tuple<Property, string>> _notifications;
|
||||||
|
|
||||||
|
public Validator(Model model)
|
||||||
{
|
{
|
||||||
OnPropertyChanged(args.PropertyName);
|
_model = model;
|
||||||
|
_validated = new HashSet<Property>();
|
||||||
|
_notifications = new HashSet<Tuple<Property, string>>();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public void Notify(Property property, string propertyName)
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NestedModelProperty<T> : ModelBaseProperty where T : Model
|
|
||||||
{
|
|
||||||
public T Model { get; }
|
|
||||||
|
|
||||||
public NestedModelProperty(T model)
|
|
||||||
{
|
|
||||||
Model = model;
|
|
||||||
|
|
||||||
Model.PropertyChanged += OnChildPropertyChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IReadOnlyCollection<string> Errors => Model.Errors;
|
|
||||||
|
|
||||||
public override bool Modified => Model.Modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MultiModelProperty<T> : ModelBaseProperty where T : Model
|
|
||||||
{
|
|
||||||
private readonly ObservableCollection<T> _models;
|
|
||||||
|
|
||||||
public MultiModelProperty()
|
|
||||||
{
|
|
||||||
_models = new ObservableCollection<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(T model)
|
|
||||||
{
|
|
||||||
_models.Add(model);
|
|
||||||
|
|
||||||
model.PropertyChanged += OnChildPropertyChanged;
|
|
||||||
|
|
||||||
if (model.Errors.Count > 0)
|
|
||||||
{
|
{
|
||||||
OnPropertyChanged("Errors");
|
_notifications.Add(new Tuple<Property, string>(property, propertyName));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Remove(T model)
|
if (property != null)
|
||||||
{
|
|
||||||
model.PropertyChanged -= OnChildPropertyChanged;
|
|
||||||
|
|
||||||
_models.Remove(model);
|
|
||||||
|
|
||||||
if (model.Errors.Count > 0)
|
|
||||||
{
|
|
||||||
OnPropertyChanged("Errors");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IReadOnlyList<T> Models => _models;
|
|
||||||
|
|
||||||
public override IReadOnlyCollection<string> Errors
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var errors = new List<string>();
|
|
||||||
|
|
||||||
foreach (var model in _models)
|
|
||||||
{
|
{
|
||||||
errors.AddRange(model.Errors);
|
property = property.Parent;
|
||||||
|
|
||||||
|
while (property != null)
|
||||||
|
{
|
||||||
|
_notifications.Add(new Tuple<Property, string>(property, propertyName));
|
||||||
|
property = property.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
_notifications.Add(new Tuple<Property, string>(null, propertyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Modified => _models.Select(model => model.Modified).Any();
|
public void Validate(Property property)
|
||||||
}
|
|
||||||
|
|
||||||
public class ModelProperty<T> : ModelBaseProperty
|
|
||||||
{
|
|
||||||
public string Name { get; }
|
|
||||||
private T _value;
|
|
||||||
private readonly List<string> _errors;
|
|
||||||
private readonly Func<string, T, string> _validate;
|
|
||||||
private bool _modified;
|
|
||||||
|
|
||||||
public T Value
|
|
||||||
{
|
|
||||||
get => _value;
|
|
||||||
set
|
|
||||||
{
|
{
|
||||||
if (_value.Equals(value))
|
if (property == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldError = _errors[0];
|
if (_validated.Add(property))
|
||||||
_errors[0] = _validate?.Invoke(Name, value) ?? "";
|
|
||||||
|
|
||||||
if (oldError != _errors[0])
|
|
||||||
{
|
{
|
||||||
OnPropertyChanged("Errors");
|
property.Validate();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!_modified)
|
public void ValidateRange(IEnumerable<Property> properties)
|
||||||
|
{
|
||||||
|
foreach (var property in properties)
|
||||||
{
|
{
|
||||||
OnPropertyChanged("Modified");
|
Validate(property);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_modified = true;
|
public void IncValidationCounter()
|
||||||
_value = value;
|
{
|
||||||
|
++_counter;
|
||||||
|
}
|
||||||
|
|
||||||
OnPropertyChanged("Value");
|
public void Dispose()
|
||||||
|
{
|
||||||
|
--_counter;
|
||||||
|
|
||||||
|
if (_counter == 0)
|
||||||
|
{
|
||||||
|
_validated.Clear();
|
||||||
|
|
||||||
|
var sortedNotifications = new List<Tuple<Property, string>>(_notifications);
|
||||||
|
sortedNotifications.Sort((x, y) =>
|
||||||
|
{
|
||||||
|
var (prop1, propName1) = x;
|
||||||
|
var (prop2, propName2) = y;
|
||||||
|
|
||||||
|
if (prop1 == null)
|
||||||
|
{
|
||||||
|
return prop2 == null ? string.CompareOrdinal(propName1, propName2) : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop2 == null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReferenceEquals(prop1, prop2))
|
||||||
|
{
|
||||||
|
return string.CompareOrdinal(propName1, propName2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop1.IsParentOf(prop2))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop2.IsParentOf(prop1))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var (property, propertyName) in sortedNotifications)
|
||||||
|
{
|
||||||
|
if (property == null)
|
||||||
|
{
|
||||||
|
_model.OnPropertyChanged(propertyName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
property.OnPropertyChanged(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_notifications.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ModelProperty(string name, T value, Func<string, T, string> validate)
|
private readonly Validator _validator;
|
||||||
|
public BillingProperty Root { get; }
|
||||||
|
|
||||||
|
public Model(Billing billing)
|
||||||
{
|
{
|
||||||
Name = name;
|
_validator = new Validator(this);
|
||||||
_value = value;
|
|
||||||
_errors = new List<string> {validate?.Invoke(Name, _value) ?? ""};
|
using var validator = BeginValidation();
|
||||||
_validate = validate;
|
Root = new BillingProperty(this, null, billing);
|
||||||
_modified = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IReadOnlyCollection<string> Errors => _errors[0] != "" ? _errors : EmptyList;
|
public Validator BeginValidation()
|
||||||
|
|
||||||
public override bool Modified => _modified;
|
|
||||||
|
|
||||||
public void ResetModified()
|
|
||||||
{
|
{
|
||||||
_modified = false;
|
_validator.IncValidationCounter();
|
||||||
|
return _validator;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static class ModelPropertyValidators
|
|
||||||
{
|
|
||||||
public static string IsNotEmpty(string name, string data)
|
|
||||||
{
|
|
||||||
return string.IsNullOrEmpty(data) ? $"{name}: Geben Sie einen Wert ein." : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string IsNaturalInt(string name, string data)
|
|
||||||
{
|
|
||||||
return !int.TryParse(data, out var n) || n <= 0
|
|
||||||
? $"{name}: Der eingegebene Wert ist keine gültige positive Zahl > 0."
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class Model : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private readonly List<ModelBaseProperty> _properties;
|
|
||||||
|
|
||||||
protected Model()
|
|
||||||
{
|
|
||||||
_properties = new List<ModelBaseProperty>();
|
|
||||||
|
|
||||||
PropertyChanged += (sender, args) =>
|
|
||||||
{
|
|
||||||
if (args.PropertyName == "Errors")
|
|
||||||
{
|
|
||||||
OnPropertyChanged("ErrorCount");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected T Add<T>(T property) where T : ModelBaseProperty
|
|
||||||
{
|
|
||||||
_properties.Add(property);
|
|
||||||
|
|
||||||
property.PropertyChanged += (sender, args) =>
|
|
||||||
{
|
|
||||||
if (args.PropertyName == "Errors" || args.PropertyName == "Modified")
|
|
||||||
{
|
|
||||||
OnPropertyChanged(args.PropertyName);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return property;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Modified => _properties.Select(property => property.Modified).Any();
|
|
||||||
|
|
||||||
public IReadOnlyCollection<string> Errors
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var errors = new List<string>();
|
|
||||||
|
|
||||||
foreach (var property in _properties)
|
|
||||||
{
|
|
||||||
errors.AddRange(property.Errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
return errors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ErrorCount => Errors.Count;
|
|
||||||
|
|
||||||
public abstract void Apply();
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
[NotifyPropertyChangedInvocator]
|
||||||
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,326 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UCalc.Annotations;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public abstract class Property : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
protected static readonly IReadOnlyList<string> EmptyList = new List<string>();
|
||||||
|
|
||||||
|
protected readonly Model Model;
|
||||||
|
public Property Parent { get; }
|
||||||
|
|
||||||
|
public abstract IReadOnlyList<string> Errors { get; }
|
||||||
|
|
||||||
|
private bool _modified;
|
||||||
|
|
||||||
|
public bool Modified
|
||||||
|
{
|
||||||
|
get => _modified;
|
||||||
|
protected set
|
||||||
|
{
|
||||||
|
if (_modified == value)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_modified = value;
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Notify(this, "Modified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Property(Model model, Property parent)
|
||||||
|
{
|
||||||
|
Model = model;
|
||||||
|
Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Validate();
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
[NotifyPropertyChangedInvocator]
|
||||||
|
public virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsParentOf(Property property)
|
||||||
|
{
|
||||||
|
while (property != null)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(this, property))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
property = property.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ValueProperty<T> : Property
|
||||||
|
{
|
||||||
|
protected string Name;
|
||||||
|
private T _value;
|
||||||
|
private readonly List<string> _errors;
|
||||||
|
|
||||||
|
public T Value
|
||||||
|
{
|
||||||
|
get => _value;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_value.Equals(value))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_value = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
Modified = true;
|
||||||
|
validator.Validate(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ValueProperty(Model model, Property parent, string name, T value) : base(model, parent)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
_value = value;
|
||||||
|
_errors = new List<string> {""};
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Validate(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IReadOnlyList<string> Errors => _errors[0] != "" ? _errors : EmptyList;
|
||||||
|
|
||||||
|
public sealed override void Validate()
|
||||||
|
{
|
||||||
|
var oldError = _errors[0];
|
||||||
|
_errors[0] = ValidateValue();
|
||||||
|
|
||||||
|
if (oldError != _errors[0])
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Notify(this, "Errors");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract string ValidateValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AlwaysValidProperty<T> : ValueProperty<T>
|
||||||
|
{
|
||||||
|
public AlwaysValidProperty(Model model, Property parent, string name, T value) : base(model, parent,
|
||||||
|
name, value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NotEmptyStringProperty : ValueProperty<string>
|
||||||
|
{
|
||||||
|
public NotEmptyStringProperty(Model model, Property parent, string name, string value) : base(model, parent,
|
||||||
|
name, value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(Value) ? $"{Name}: Geben Sie einen Wert ein." : "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NaturalNumberProperty : ValueProperty<string>
|
||||||
|
{
|
||||||
|
public NaturalNumberProperty(Model model, Property parent, string name, int value) : base(model, parent, name,
|
||||||
|
value.ToString())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
return !int.TryParse(Value, out var n) || n <= 0
|
||||||
|
? $"{Name}: Der eingegebene Wert ist keine gültige Zahl > 0."
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PositiveDecimalProperty : ValueProperty<string>
|
||||||
|
{
|
||||||
|
public PositiveDecimalProperty(Model model, Property parent, string name, decimal value) : base(model, parent,
|
||||||
|
name,
|
||||||
|
value.ToString(Constants.DecimalFormat))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
return !decimal.TryParse(Value, out var n) || n < 0
|
||||||
|
? $"{Name}: Der eingegebene Wert ist kein gültiger Betrag."
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class NestedProperty : Property
|
||||||
|
{
|
||||||
|
private readonly List<Property> _properties;
|
||||||
|
private readonly List<string> _errors;
|
||||||
|
public override IReadOnlyList<string> Errors => _errors;
|
||||||
|
|
||||||
|
protected NestedProperty(Model model, Property parent) : base(model, parent)
|
||||||
|
{
|
||||||
|
_properties = new List<Property>();
|
||||||
|
_errors = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected T Add<T>(T property) where T : Property
|
||||||
|
{
|
||||||
|
_properties.Add(property);
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Validate()
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.ValidateRange(_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnPropertyChanged(string propertyName = null)
|
||||||
|
{
|
||||||
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case "Errors":
|
||||||
|
_errors.Clear();
|
||||||
|
|
||||||
|
foreach (var property in _properties)
|
||||||
|
{
|
||||||
|
_errors.AddRange(property.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "Modified":
|
||||||
|
Modified = _properties.Any(property => property.Modified);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnPropertyChanged(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class MultiProperty<T> : Property, IReadOnlyList<T>, INotifyCollectionChanged where T : Property
|
||||||
|
{
|
||||||
|
private readonly string _errorOnEmpty;
|
||||||
|
private readonly List<T> _properties;
|
||||||
|
protected IReadOnlyList<T> Properties => _properties;
|
||||||
|
private readonly List<string> _errors;
|
||||||
|
public override IReadOnlyList<string> Errors => _errors;
|
||||||
|
|
||||||
|
protected MultiProperty(Model model, Property parent, string errorOnEmpty = null) : base(model, parent)
|
||||||
|
{
|
||||||
|
_errorOnEmpty = errorOnEmpty;
|
||||||
|
_properties = new List<T>();
|
||||||
|
_errors = new List<string>();
|
||||||
|
|
||||||
|
OnPropertyChanged("Errors");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Add(T property)
|
||||||
|
{
|
||||||
|
_properties.Add(property);
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Notify(this, "Errors");
|
||||||
|
Modified = true;
|
||||||
|
|
||||||
|
OnPropertyChanged("Count");
|
||||||
|
|
||||||
|
CollectionChanged?.Invoke(this,
|
||||||
|
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, property,
|
||||||
|
_properties.Count - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Remove(T property)
|
||||||
|
{
|
||||||
|
var index = _properties.IndexOf(property);
|
||||||
|
_properties.RemoveAt(index);
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Notify(this, "Errors");
|
||||||
|
Modified = true;
|
||||||
|
|
||||||
|
OnPropertyChanged("Count");
|
||||||
|
|
||||||
|
CollectionChanged?.Invoke(this,
|
||||||
|
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, property, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Validate()
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.ValidateRange(_properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed override void OnPropertyChanged(string propertyName = null)
|
||||||
|
{
|
||||||
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case "Errors":
|
||||||
|
_errors.Clear();
|
||||||
|
|
||||||
|
if (_properties.Count == 0)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(_errorOnEmpty))
|
||||||
|
{
|
||||||
|
_errors.Add(_errorOnEmpty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var property in _properties)
|
||||||
|
{
|
||||||
|
_errors.AddRange(property.Errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "Modified":
|
||||||
|
Modified = Modified || _properties.Any(property => property.Modified);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnPropertyChanged(propertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
{
|
||||||
|
return _properties.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Count => _properties.Count;
|
||||||
|
|
||||||
|
public T this[int index] => _properties[index];
|
||||||
|
|
||||||
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class SalutationProperty : AlwaysValidProperty<int>
|
||||||
|
{
|
||||||
|
public SalutationProperty(Model model, Property parent, string name, Salutation value) : base(model, parent,
|
||||||
|
name, (int) value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UCalc.Controls;
|
||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class EntryDateProperty : ValueProperty<DateTime?>
|
||||||
|
{
|
||||||
|
public EntryDateProperty(Model model, Property parent, string name, DateTime? value) : base(model, parent, name,
|
||||||
|
value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
validator.Validate(((TenantProperty) Parent).DepartureDate);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DepatureDateProperty : ValueProperty<DateTime?>
|
||||||
|
{
|
||||||
|
public DepatureDateProperty(Model model, Property parent, string name, DateTime? value) : base(model, parent,
|
||||||
|
name, value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string ValidateValue()
|
||||||
|
{
|
||||||
|
if (Value != null)
|
||||||
|
{
|
||||||
|
var entryDate = ((TenantProperty) Parent).EntryDate.Value;
|
||||||
|
|
||||||
|
if (entryDate != null && entryDate > Value)
|
||||||
|
{
|
||||||
|
return $"{Name}: Das Datum liegt vor dem Einzug.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Validate(((TenantProperty) Parent).RentedFlats);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RentedFlatsProperty : Property
|
||||||
|
{
|
||||||
|
private const string NoFlatsError = "Gemietete Wohnungen: Es wurde keine Wohnung zugewiesen.";
|
||||||
|
private readonly HashSet<FlatProperty> _flatProperties;
|
||||||
|
private readonly List<string> _errors;
|
||||||
|
|
||||||
|
public RentedFlatsProperty(Model model, Property parent, IEnumerable<Flat> data,
|
||||||
|
IReadOnlyDictionary<Flat, FlatProperty> flatToProperty = null) : base(model, parent)
|
||||||
|
{
|
||||||
|
_flatProperties = new HashSet<FlatProperty>();
|
||||||
|
_errors = new List<string>();
|
||||||
|
|
||||||
|
foreach (var flat in data)
|
||||||
|
{
|
||||||
|
_flatProperties.Add(flatToProperty?[flat] ?? throw new InvalidOperationException());
|
||||||
|
}
|
||||||
|
|
||||||
|
Validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IReadOnlyList<string> Errors => _errors;
|
||||||
|
|
||||||
|
public void Add(FlatProperty flat)
|
||||||
|
{
|
||||||
|
if (!_flatProperties.Add(flat))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Validate(this);
|
||||||
|
Modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(FlatProperty flat)
|
||||||
|
{
|
||||||
|
if (!_flatProperties.Remove(flat))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Validate(this);
|
||||||
|
Modified = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(FlatProperty flat)
|
||||||
|
{
|
||||||
|
return _flatProperties.Contains(flat);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed override void Validate()
|
||||||
|
{
|
||||||
|
_errors.Clear();
|
||||||
|
|
||||||
|
if (_flatProperties.Count == 0)
|
||||||
|
{
|
||||||
|
_errors.Add(NoFlatsError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryDate = ((TenantProperty) Parent).EntryDate.Value;
|
||||||
|
var departureDate = ((TenantProperty) Parent).DepartureDate.Value;
|
||||||
|
|
||||||
|
foreach (var flatProperty in _flatProperties)
|
||||||
|
{
|
||||||
|
foreach (var tenant in Model.Root.Tenants)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(this, tenant.RentedFlats))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tenant.RentedFlats.IsRented(flatProperty, entryDate, departureDate))
|
||||||
|
{
|
||||||
|
var error = $"Gemietete Wohnungen: Die Wohnung \"{flatProperty.Name.Value}\" ist bereits ";
|
||||||
|
|
||||||
|
if (entryDate != null)
|
||||||
|
{
|
||||||
|
if (departureDate != null)
|
||||||
|
{
|
||||||
|
_errors.Add(
|
||||||
|
$"von {entryDate.Value.ToString(Constants.DateFormat)} - {departureDate.Value.ToString(Constants.DateFormat)} ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_errors.Add($"seit dem {entryDate.Value.ToString(Constants.DateFormat)} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (departureDate != null)
|
||||||
|
{
|
||||||
|
_errors.Add($"bis zum {departureDate.Value.ToString(Constants.DateFormat)} ");
|
||||||
|
}
|
||||||
|
|
||||||
|
error += "an einen anderen Mieter vermietet.";
|
||||||
|
_errors.Add(error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
validator.Notify(this, "Errors");
|
||||||
|
|
||||||
|
validator.ValidateRange(Model.Root.Tenants);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsRented(FlatProperty flat, DateTime? start, DateTime? end)
|
||||||
|
{
|
||||||
|
if (!_flatProperties.Contains(flat))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var thisStart = ((TenantProperty) Parent).EntryDate.Value ?? DateTime.MinValue;
|
||||||
|
var thisEnd = ((TenantProperty) Parent).DepartureDate.Value ?? DateTime.MaxValue;
|
||||||
|
|
||||||
|
var otherStart = start ?? DateTime.MinValue;
|
||||||
|
var otherEnd = end ?? DateTime.MinValue;
|
||||||
|
|
||||||
|
return thisStart.Intersects(thisEnd, otherStart, otherEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TenantProperty : NestedProperty
|
||||||
|
{
|
||||||
|
public SalutationProperty Salutation { get; }
|
||||||
|
public NotEmptyStringProperty Name { get; }
|
||||||
|
public NaturalNumberProperty PersonCount { get; }
|
||||||
|
public BankAccountProperty BankAccount { get; }
|
||||||
|
public EntryDateProperty EntryDate { get; }
|
||||||
|
public DepatureDateProperty DepartureDate { get; }
|
||||||
|
public RentedFlatsProperty RentedFlats { get; }
|
||||||
|
public PositiveDecimalProperty PaidRent { get; }
|
||||||
|
public AlwaysValidProperty<string> CustomMessage1 { get; }
|
||||||
|
public AlwaysValidProperty<string> CustomMessage2 { get; }
|
||||||
|
|
||||||
|
public TenantProperty(Model model, Property parent, Tenant data,
|
||||||
|
IReadOnlyDictionary<Flat, FlatProperty> flatToProperty = null) : base(model, parent)
|
||||||
|
{
|
||||||
|
Salutation = Add(new SalutationProperty(model, this, "Anrede", data.Salutation));
|
||||||
|
Name = Add(new NotEmptyStringProperty(model, this, "Name", data.Name));
|
||||||
|
PersonCount = Add(new NaturalNumberProperty(model, this, "Personenanzahl", data.PersonCount));
|
||||||
|
BankAccount = Add(new BankAccountProperty(model, this, data.BankAccount));
|
||||||
|
EntryDate = Add(new EntryDateProperty(model, this, "Einzugsdatum", data.EntryDate));
|
||||||
|
DepartureDate = Add(new DepatureDateProperty(model, this, "Auszugsdatum", data.DepartureDate));
|
||||||
|
RentedFlats = Add(new RentedFlatsProperty(model, this, data.RentedFlats, flatToProperty));
|
||||||
|
PaidRent = Add(new PositiveDecimalProperty(model, this, "Bereits gezahlt", data.PaidRent));
|
||||||
|
CustomMessage1 = Add(new AlwaysValidProperty<string>(model, this, "Nachricht 1", data.CustomMessage1));
|
||||||
|
CustomMessage2 = Add(new AlwaysValidProperty<string>(model, this, "Nachricht 2", data.CustomMessage2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UCalc.Data;
|
||||||
|
|
||||||
|
namespace UCalc.Models
|
||||||
|
{
|
||||||
|
public class TenantsProperty : MultiProperty<TenantProperty>
|
||||||
|
{
|
||||||
|
public TenantsProperty(Model model, Property parent, IEnumerable<Tenant> data,
|
||||||
|
IReadOnlyDictionary<Flat, FlatProperty> flatToProperty = null) : base(model, parent,
|
||||||
|
"Mieter: Geben Sie einen oder mehr Mieter an.")
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
foreach (var tenant in data)
|
||||||
|
{
|
||||||
|
base.Add(new TenantProperty(Model, this, tenant, flatToProperty));
|
||||||
|
}
|
||||||
|
|
||||||
|
Modified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add()
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
base.Add(new TenantProperty(Model, this, new Tenant()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void Remove(TenantProperty tenant)
|
||||||
|
{
|
||||||
|
using var validator = Model.BeginValidation();
|
||||||
|
|
||||||
|
base.Remove(tenant);
|
||||||
|
|
||||||
|
validator.ValidateRange(Properties.Select(otherTenant => otherTenant.RentedFlats));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,7 +71,7 @@ namespace UCalc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove depatured renters and costs that were only paid once
|
// Remove departured renters and costs that were only paid once
|
||||||
string summary = "";
|
string summary = "";
|
||||||
billing.StartDate = (DateTime) StartCalendar.SelectedDate;
|
billing.StartDate = (DateTime) StartCalendar.SelectedDate;
|
||||||
billing.EndDate = (DateTime) EndCalendar.SelectedDate;
|
billing.EndDate = (DateTime) EndCalendar.SelectedDate;
|
||||||
|
|||||||
+46
-34
@@ -8,6 +8,10 @@
|
|||||||
xmlns:controls="clr-namespace:UCalc.Controls"
|
xmlns:controls="clr-namespace:UCalc.Controls"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Page.Resources>
|
||||||
|
<controls:EmptyMultiPropertyToVisibilityConverter x:Key="EmptyMultiPropertyToVisibilityConverter" />
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
||||||
VerticalScrollBarVisibility="Auto">
|
VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
@@ -22,12 +26,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.Street.Errors, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
Property="{Binding Path=House.Address.Street, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.Street.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=House.Address.Street.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -39,12 +43,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.HouseNumber.Errors, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
Property="{Binding Path=House.Address.HouseNumber, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.HouseNumber.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=House.Address.HouseNumber.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -56,12 +60,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.City.Errors, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
Property="{Binding Path=House.Address.City, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.City.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=House.Address.City.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -73,45 +77,53 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.Postcode.Errors, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
Property="{Binding Path=House.Address.Postcode, RelativeSource={RelativeSource AncestorType=pages:HousePage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.Postcode.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=House.Address.Postcode.Value, RelativeSource={RelativeSource AncestorType=pages:HousePage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<controls:SectionHeader Header="Wohnungen"
|
<controls:SectionHeader Header="Wohnungen"
|
||||||
Margin="0, 12, 0, 0" />
|
Margin="0, 12, 0, 0" />
|
||||||
|
|
||||||
<controls:HighlightButton Margin="12, 0, 12, 8"
|
<DockPanel Margin="0, 0, 0, 8">
|
||||||
HighlightForeground="{x:Static local:Constants.SubMainColor}"
|
<controls:ErrorIcon Margin="0, 0, 12, 0"
|
||||||
HighlightBackground="{x:Static local:Constants.MainColor}"
|
DockPanel.Dock="Right"
|
||||||
Click="OnAddFlatClick">
|
VerticalAlignment="Center"
|
||||||
<Viewbox Width="24"
|
Property="{Binding Path=House.Flats, RelativeSource={RelativeSource AncestorType=pages:HousePage}}"
|
||||||
Height="24"
|
Visibility="{Binding Path=House.Flats.Count, RelativeSource={RelativeSource AncestorType=pages:HousePage}, Converter={StaticResource EmptyMultiPropertyToVisibilityConverter}}" />
|
||||||
Margin="12, 12, 6, 12"
|
|
||||||
Stretch="Uniform">
|
|
||||||
<Canvas Width="512" Height="512">
|
|
||||||
<Canvas.RenderTransform>
|
|
||||||
<TranslateTransform X="0" Y="0" />
|
|
||||||
</Canvas.RenderTransform>
|
|
||||||
<Path>
|
|
||||||
<Path.Data>
|
|
||||||
<PathGeometry
|
|
||||||
Figures="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"
|
|
||||||
FillRule="NonZero" />
|
|
||||||
</Path.Data>
|
|
||||||
</Path>
|
|
||||||
</Canvas>
|
|
||||||
</Viewbox>
|
|
||||||
|
|
||||||
<Label Content="Wohnung hinzufügen"
|
<controls:HighlightButton Margin="12, 0, 12, 0"
|
||||||
Margin="0, 12, 12, 12" />
|
HighlightForeground="{x:Static local:Constants.SubMainColor}"
|
||||||
</controls:HighlightButton>
|
HighlightBackground="{x:Static local:Constants.MainColor}"
|
||||||
|
Click="OnAddFlatClick">
|
||||||
|
<Viewbox Width="24"
|
||||||
|
Height="24"
|
||||||
|
Margin="12, 12, 6, 12"
|
||||||
|
Stretch="Uniform">
|
||||||
|
<Canvas Width="512" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path>
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Wohnung hinzufügen"
|
||||||
|
Margin="0, 12, 12, 12" />
|
||||||
|
</controls:HighlightButton>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
<ItemsControl
|
<ItemsControl
|
||||||
ItemsSource="{Binding Path=Model.Flats.Models, RelativeSource={RelativeSource AncestorType=pages:HousePage}}"
|
ItemsSource="{Binding Path=House.Flats, RelativeSource={RelativeSource AncestorType=pages:HousePage}}"
|
||||||
Margin="12, 0, 12, 12">
|
Margin="12, 0, 12, 12">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
@@ -143,7 +155,7 @@
|
|||||||
HighlightBackground="{x:Static local:Constants.MainColor}"
|
HighlightBackground="{x:Static local:Constants.MainColor}"
|
||||||
Click="OnFlatEditClick">
|
Click="OnFlatEditClick">
|
||||||
|
|
||||||
<controls:ErrorIcon Errors="{Binding Errors}"
|
<controls:ErrorIcon Property="{Binding .}"
|
||||||
DockPanel.Dock="Left"
|
DockPanel.Dock="Left"
|
||||||
Margin="12, 12, 8, 12" />
|
Margin="12, 12, 8, 12" />
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace UCalc.Pages
|
|||||||
public partial class HousePage
|
public partial class HousePage
|
||||||
{
|
{
|
||||||
public Window ParentWindow { get; set; }
|
public Window ParentWindow { get; set; }
|
||||||
public HouseModel Model { get; set; }
|
public HouseProperty House { get; set; }
|
||||||
|
|
||||||
public HousePage()
|
public HousePage()
|
||||||
{
|
{
|
||||||
@@ -16,25 +16,25 @@ namespace UCalc.Pages
|
|||||||
|
|
||||||
private void OnAddFlatClick(object sender, RoutedEventArgs e)
|
private void OnAddFlatClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Model.AddFlat();
|
House.Flats.Add();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFlatDeleteClick(object sender, RoutedEventArgs e)
|
private void OnFlatDeleteClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var flatModel = (FlatModel) ((HighlightButton) sender).DataContext;
|
var flat = (FlatProperty) ((HighlightButton) sender).DataContext;
|
||||||
|
|
||||||
if (MessageBox.Show($"Möchten Sie die Wohnung \"{flatModel.Data.Name}\" wirlick löschen?", "Löschen?",
|
if (MessageBox.Show($"Möchten Sie die Wohnung \"{flat.Name.Value}\" wirlick löschen?", "Löschen?",
|
||||||
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||||
{
|
{
|
||||||
Model.RemoveFlat(flatModel);
|
House.Flats.Remove(flat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFlatEditClick(object sender, RoutedEventArgs e)
|
private void OnFlatEditClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var flatModel = (FlatModel) ((HighlightButton) sender).DataContext;
|
var flat = (FlatProperty) ((HighlightButton) sender).DataContext;
|
||||||
|
|
||||||
new FlatWindow(flatModel) {Owner = ParentWindow}.ShowDialog();
|
new FlatWindow(flat) {Owner = ParentWindow}.ShowDialog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<ComboBox Margin="0, 0, 28, 0"
|
<ComboBox Margin="0, 0, 28, 0"
|
||||||
ItemsSource="{x:Static local:Constants.SalutationStrs}"
|
ItemsSource="{x:Static local:Constants.SalutationStrs}"
|
||||||
SelectedIndex="{Binding Path=Model.Salutation.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}"/>
|
SelectedIndex="{Binding Path=Landlord.Salutation.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}"/>
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 12, 12, 0">
|
<DockPanel Margin="12, 12, 12, 0">
|
||||||
@@ -33,12 +33,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Name.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.Name, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Name.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.Name.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -50,12 +50,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Phone.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.Phone, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Phone.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.Phone.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -67,12 +67,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.MailAddress.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.MailAddress, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.MailAddress.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.MailAddress.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<controls:SectionHeader Header="Adresse des Eigentümers"
|
<controls:SectionHeader Header="Adresse des Eigentümers"
|
||||||
@@ -87,12 +87,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.Street.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.Address.Street, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.Street.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.Address.Street.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -104,12 +104,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.HouseNumber.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.Address.HouseNumber, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.HouseNumber.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.Address.HouseNumber.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -121,12 +121,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.City.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.Address.City, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.City.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.Address.City.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -138,12 +138,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.Address.Model.Postcode.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.Address.Postcode, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.Address.Model.Postcode.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.Address.Postcode.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<controls:SectionHeader Header="Bankdaten des Eigentümers"
|
<controls:SectionHeader Header="Bankdaten des Eigentümers"
|
||||||
@@ -158,12 +158,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.BankAccount.Model.Iban.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.BankAccount.Iban, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.BankAccount.Model.Iban.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.BankAccount.Iban.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 0">
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
@@ -175,12 +175,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.BankAccount.Model.Bic.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.BankAccount.Bic, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.BankAccount.Model.Bic.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.BankAccount.Bic.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<DockPanel Margin="12, 8, 12, 12">
|
<DockPanel Margin="12, 8, 12, 12">
|
||||||
@@ -192,12 +192,12 @@
|
|||||||
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
DockPanel.Dock="Right"
|
DockPanel.Dock="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Errors="{Binding Path=Model.BankAccount.Model.BankName.Errors, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
Property="{Binding Path=Landlord.BankAccount.BankName, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}}" />
|
||||||
|
|
||||||
<TextBox
|
<TextBox
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
MinHeight="22"
|
MinHeight="22"
|
||||||
Text="{Binding Path=Model.BankAccount.Model.BankName.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
Text="{Binding Path=Landlord.BankAccount.BankName.Value, RelativeSource={RelativeSource AncestorType=pages:LandlordPage}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace UCalc.Pages
|
|||||||
{
|
{
|
||||||
public partial class LandlordPage
|
public partial class LandlordPage
|
||||||
{
|
{
|
||||||
public LandlordModel Model { get; set; }
|
public LandlordProperty Landlord { get; set; }
|
||||||
|
|
||||||
public LandlordPage()
|
public LandlordPage()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
<controls:ErrorCounter DockPanel.Dock="Right"
|
<controls:ErrorCounter DockPanel.Dock="Right"
|
||||||
Margin="0, 12, 12, 12"
|
Margin="0, 12, 12, 12"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Model="{Binding Path=Model.LandlordModel, RelativeSource={RelativeSource AncestorType=pages:SideBar}}"/>
|
Property="{Binding Path=Model.Root.Landlord, RelativeSource={RelativeSource AncestorType=pages:SideBar}}"/>
|
||||||
|
|
||||||
<Label Content="Eigentümer"
|
<Label Content="Eigentümer"
|
||||||
Margin="0, 12, 12, 12"
|
Margin="0, 12, 12, 12"
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
<controls:ErrorCounter DockPanel.Dock="Right"
|
<controls:ErrorCounter DockPanel.Dock="Right"
|
||||||
Margin="0, 12, 12, 12"
|
Margin="0, 12, 12, 12"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Model="{Binding Path=Model.HouseModel, RelativeSource={RelativeSource AncestorType=pages:SideBar}}"/>
|
Property="{Binding Path=Model.Root.House, RelativeSource={RelativeSource AncestorType=pages:SideBar}}"/>
|
||||||
|
|
||||||
<Label Content="Haus"
|
<Label Content="Haus"
|
||||||
Margin="0, 12, 12, 12"
|
Margin="0, 12, 12, 12"
|
||||||
@@ -190,6 +190,11 @@
|
|||||||
</Canvas>
|
</Canvas>
|
||||||
</Viewbox>
|
</Viewbox>
|
||||||
|
|
||||||
|
<controls:ErrorCounter DockPanel.Dock="Right"
|
||||||
|
Margin="0, 12, 12, 12"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Model.Root.Tenants, RelativeSource={RelativeSource AncestorType=pages:SideBar}}"/>
|
||||||
|
|
||||||
<Label Content="Mieter"
|
<Label Content="Mieter"
|
||||||
Margin="0, 12, 12, 12"
|
Margin="0, 12, 12, 12"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace UCalc.Pages
|
|||||||
public partial class SideBar
|
public partial class SideBar
|
||||||
{
|
{
|
||||||
public TabControl TabControl { get; set; }
|
public TabControl TabControl { get; set; }
|
||||||
public BillingModel Model { get; set; }
|
public Model Model { get; set; }
|
||||||
|
|
||||||
public SideBar()
|
public SideBar()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,98 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:UCalc.Pages"
|
xmlns:controls="clr-namespace:UCalc.Controls"
|
||||||
|
xmlns:local="clr-namespace:UCalc"
|
||||||
|
xmlns:pages="clr-namespace:UCalc.Pages"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Grid />
|
|
||||||
|
<Page.Resources>
|
||||||
|
<controls:EmptyMultiPropertyToVisibilityConverter x:Key="EmptyMultiPropertyToVisibilityConverter" />
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
|
<DockPanel>
|
||||||
|
<DockPanel DockPanel.Dock="Top"
|
||||||
|
Margin="0, 0, 0, 8">
|
||||||
|
<controls:ErrorIcon Margin="0, 0, 12, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenants, RelativeSource={RelativeSource AncestorType=pages:TenantsPage}}"
|
||||||
|
Visibility="{Binding Path=Tenants.Count, RelativeSource={RelativeSource AncestorType=pages:TenantsPage}, Converter={StaticResource EmptyMultiPropertyToVisibilityConverter}}" />
|
||||||
|
|
||||||
|
<controls:HighlightButton Margin="12, 0, 12, 0"
|
||||||
|
HighlightForeground="{x:Static local:Constants.SubMainColor}"
|
||||||
|
HighlightBackground="{x:Static local:Constants.MainColor}"
|
||||||
|
Click="OnAddTenantClick">
|
||||||
|
<Viewbox Width="24"
|
||||||
|
Height="24"
|
||||||
|
Margin="12, 12, 6, 12"
|
||||||
|
Stretch="Uniform">
|
||||||
|
<Canvas Width="512" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path>
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Mieter hinzufügen"
|
||||||
|
Margin="0, 12, 12, 12" />
|
||||||
|
</controls:HighlightButton>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
||||||
|
VerticalScrollBarVisibility="Auto">
|
||||||
|
<ItemsControl
|
||||||
|
ItemsSource="{Binding Path=Tenants, RelativeSource={RelativeSource AncestorType=pages:TenantsPage}}"
|
||||||
|
Margin="12, 0, 12, 12">
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<DockPanel>
|
||||||
|
<controls:HighlightButton DockPanel.Dock="Right"
|
||||||
|
HighlightForeground="Red"
|
||||||
|
HighlightBackground="White"
|
||||||
|
Click="OnTenantDeleteClick">
|
||||||
|
<Viewbox Width="24"
|
||||||
|
Height="24"
|
||||||
|
Margin="8, 12, 8, 12"
|
||||||
|
Stretch="Uniform">
|
||||||
|
<Canvas Width="448" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path>
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M32 464a48 48 0 0 0 48 48h288a48 48 0 0 0 48-48V128H32zm272-256a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zm-96 0a16 16 0 0 1 32 0v224a16 16 0 0 1-32 0zM432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
</controls:HighlightButton>
|
||||||
|
|
||||||
|
<controls:HighlightButton HighlightForeground="{x:Static local:Constants.SubMainColor}"
|
||||||
|
HighlightBackground="{x:Static local:Constants.MainColor}"
|
||||||
|
Click="OnTenantEditClick">
|
||||||
|
|
||||||
|
<controls:ErrorIcon Property="{Binding .}"
|
||||||
|
DockPanel.Dock="Left"
|
||||||
|
Margin="12, 12, 8, 12" />
|
||||||
|
|
||||||
|
<Label Content="{Binding Name.Value}"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</controls:HighlightButton>
|
||||||
|
</DockPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</ScrollViewer>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
</Page>
|
</Page>
|
||||||
@@ -1,12 +1,41 @@
|
|||||||
using System.Windows.Controls;
|
using System.Windows;
|
||||||
|
using UCalc.Controls;
|
||||||
|
using UCalc.Models;
|
||||||
|
|
||||||
namespace UCalc.Pages
|
namespace UCalc.Pages
|
||||||
{
|
{
|
||||||
public partial class TenantsPage : Page
|
public partial class TenantsPage
|
||||||
{
|
{
|
||||||
|
public Window ParentWindow { get; set; }
|
||||||
|
public TenantsProperty Tenants { get; set; }
|
||||||
|
public HouseProperty House { get; set; }
|
||||||
|
|
||||||
public TenantsPage()
|
public TenantsPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnAddTenantClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Tenants.Add();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTenantDeleteClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var tenant = (TenantProperty) ((HighlightButton) sender).DataContext;
|
||||||
|
|
||||||
|
if (MessageBox.Show($"Möchten Sie den Mieter \"{tenant.Name.Value}\" wirlick löschen?", "Löschen?",
|
||||||
|
MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
|
||||||
|
{
|
||||||
|
Tenants.Remove(tenant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTenantEditClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var tenant = (TenantProperty) ((HighlightButton) sender).DataContext;
|
||||||
|
|
||||||
|
new TenantWindow(tenant, House) {Owner = ParentWindow}.ShowDialog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,253 @@
|
|||||||
|
<Window x:Class="UCalc.TenantWindow"
|
||||||
|
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"
|
||||||
|
xmlns:controls="clr-namespace:UCalc.Controls"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="Mieter bearbeiten"
|
||||||
|
Width="500"
|
||||||
|
Height="600"
|
||||||
|
MinWidth="400"
|
||||||
|
MinHeight="190"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
ShowInTaskbar="False">
|
||||||
|
|
||||||
|
<Window.Resources>
|
||||||
|
<controls:FlatToRentedConverter x:Key="FlatToRentedConverter" />
|
||||||
|
<controls:DatePickerTextToDateTimeConverter x:Key="DatePickerTextToDateTimeConverter" />
|
||||||
|
</Window.Resources>
|
||||||
|
|
||||||
|
<DockPanel>
|
||||||
|
<StackPanel DockPanel.Dock="Bottom">
|
||||||
|
<Separator Margin="0, 12, 0, 0"
|
||||||
|
Background="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<DockPanel LastChildFill="False">
|
||||||
|
<Button DockPanel.Dock="Right"
|
||||||
|
MinWidth="100"
|
||||||
|
MinHeight="24"
|
||||||
|
Margin="12"
|
||||||
|
Content="OK"
|
||||||
|
Click="OnOkClick" />
|
||||||
|
</DockPanel>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
|
||||||
|
VerticalScrollBarVisibility="Auto">
|
||||||
|
<StackPanel>
|
||||||
|
<controls:SectionHeader Header="Allgemeine Informationen" />
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 12, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Anrede:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<ComboBox Margin="0, 0, 28, 0"
|
||||||
|
ItemsSource="{x:Static local:Constants.SalutationStrs}"
|
||||||
|
SelectedIndex="{Binding Path=Tenant.Salutation.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Name:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.Name, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.Name.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Personenanzahl:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.PersonCount, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.PersonCount.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<controls:SectionHeader Header="Bankdaten"
|
||||||
|
Margin="0, 12, 0, 0" />
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="IBAN:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.BankAccount.Iban, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.BankAccount.Iban.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="BIC:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.BankAccount.Bic, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.BankAccount.Bic.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Name der Bank:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.BankAccount.BankName, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.BankAccount.BankName.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<controls:SectionHeader Header="Ein- und Auszug"
|
||||||
|
Margin="0, 12, 0, 0" />
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Einzug am:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.EntryDate, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
<!-- TODO DisplayDateStart="{}" -->
|
||||||
|
<DatePicker VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.EntryDate.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource DatePickerTextToDateTimeConverter}}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Auszug am:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.DepartureDate, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<DatePicker VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.DepartureDate.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource DatePickerTextToDateTimeConverter}}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<controls:SectionHeader Header="Gemietete Wohnungen"
|
||||||
|
Margin="0, 12, 0, 0" />
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.RentedFlats, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<ListBox Height="120"
|
||||||
|
ItemsSource="{Binding Path=House.Flats, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}">
|
||||||
|
<ListBox.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<CheckBox Content="{Binding Name.Value}"
|
||||||
|
IsChecked="{Binding Path=., Converter={StaticResource FlatToRentedConverter}, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
|
||||||
|
Checked="OnFlatChecked"
|
||||||
|
Unchecked="OnFlatUnchecked"/>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListBox.ItemTemplate>
|
||||||
|
</ListBox>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<controls:SectionHeader Header="Sonstiges"
|
||||||
|
Margin="0, 12, 0, 0" />
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Bereits bezahlt:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.PaidRent, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.PaidRent.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Nachricht 1:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.CustomMessage1, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.CustomMessage1.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<DockPanel Margin="12, 8, 12, 0">
|
||||||
|
<Label DockPanel.Dock="Left"
|
||||||
|
Content="Nachricht 2:"
|
||||||
|
Width="180"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<controls:ErrorIcon Margin="12, 0, 0, 0"
|
||||||
|
DockPanel.Dock="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Property="{Binding Path=Tenant.CustomMessage2, RelativeSource={RelativeSource AncestorType=local:TenantWindow}}" />
|
||||||
|
|
||||||
|
<TextBox VerticalAlignment="Center"
|
||||||
|
MinHeight="22"
|
||||||
|
Text="{Binding Path=Tenant.CustomMessage2.Value, RelativeSource={RelativeSource AncestorType=local:TenantWindow}, UpdateSourceTrigger=PropertyChanged}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
</StackPanel>
|
||||||
|
</ScrollViewer>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using UCalc.Controls;
|
||||||
|
using UCalc.Models;
|
||||||
|
|
||||||
|
namespace UCalc
|
||||||
|
{
|
||||||
|
public partial class TenantWindow
|
||||||
|
{
|
||||||
|
public TenantProperty Tenant { get; }
|
||||||
|
public HouseProperty House { get; }
|
||||||
|
|
||||||
|
public TenantWindow(TenantProperty tenant, HouseProperty house)
|
||||||
|
{
|
||||||
|
Tenant = tenant;
|
||||||
|
House = house;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
((FlatToRentedConverter) FindResource("FlatToRentedConverter")).Tenant = Tenant;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOkClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFlatChecked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var flat = (FlatProperty) ((CheckBox) sender).DataContext;
|
||||||
|
|
||||||
|
Tenant.RentedFlats.Add(flat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnFlatUnchecked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var flat = (FlatProperty) ((CheckBox) sender).DataContext;
|
||||||
|
|
||||||
|
Tenant.RentedFlats.Remove(flat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,6 +40,9 @@
|
|||||||
<Page Update="FlatWindow.xaml">
|
<Page Update="FlatWindow.xaml">
|
||||||
<Generator></Generator>
|
<Generator></Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Update="TenantWindow.xaml">
|
||||||
|
<Generator></Generator>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -76,6 +79,9 @@
|
|||||||
<Compile Update="FlatWindow.xaml.cs">
|
<Compile Update="FlatWindow.xaml.cs">
|
||||||
<DependentUpon>FlatWindow.xaml</DependentUpon>
|
<DependentUpon>FlatWindow.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="TenantWindow.xaml.cs">
|
||||||
|
<DependentUpon>TenantWindow.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
Reference in New Issue
Block a user