Implemented printing.
This commit is contained in:
@@ -186,17 +186,17 @@ namespace UCalc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Print()
|
public void Print()
|
||||||
{
|
{
|
||||||
if (Model.Root.Errors.Count > 0)
|
if (Model.Root.Errors.Count > 0)
|
||||||
{
|
{
|
||||||
MessageBox.Show(
|
MessageBox.Show(
|
||||||
"Bitte beheben Sie zuerst die angezeigten Fehler, bevor Sie das Dokument drucken können.",
|
"Bitte beheben Sie zuerst die angezeigten Fehler, bevor Sie das Dokument drucken können.",
|
||||||
"Fehler!", MessageBoxButton.OK, MessageBoxImage.Error);
|
"Fehler!", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException();
|
new PrintWindow(Model) {Owner = this}.ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnDetailsTabSelected(object sender, RoutedEventArgs e)
|
private void OnDetailsTabSelected(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using UCalc.Controls;
|
using UCalc.Controls;
|
||||||
using UCalc.Data;
|
using UCalc.Data;
|
||||||
@@ -26,5 +27,33 @@ namespace UCalc
|
|||||||
|
|
||||||
public static readonly ImmutableList<string> CostDivisionStrs =
|
public static readonly ImmutableList<string> CostDivisionStrs =
|
||||||
((CostDivision[]) Enum.GetValues(typeof(CostDivision))).Select(value => value.AsString()).ToImmutableList();
|
((CostDivision[]) Enum.GetValues(typeof(CostDivision))).Select(value => value.AsString()).ToImmutableList();
|
||||||
|
|
||||||
|
public static readonly double DinA4Width;
|
||||||
|
public static readonly double DinA4Height;
|
||||||
|
public static readonly Thickness DinA4Padding;
|
||||||
|
|
||||||
|
public static double DinA4ContentWidth => DinA4Width - DinA4Padding.Left - DinA4Padding.Right;
|
||||||
|
|
||||||
|
public static readonly double PrintDefaultFontSize;
|
||||||
|
public static readonly double PrintSubjectFontSize;
|
||||||
|
public static readonly double PrintNewlineFontSize;
|
||||||
|
|
||||||
|
static Constants()
|
||||||
|
{
|
||||||
|
var converter = new LengthConverter();
|
||||||
|
// ReSharper disable PossibleNullReferenceException
|
||||||
|
DinA4Width = (double) converter.ConvertFromInvariantString("29.7cm");
|
||||||
|
DinA4Height = (double) converter.ConvertFromInvariantString("42cm");
|
||||||
|
var dinA4MarginLeftRight = (double) converter.ConvertFromInvariantString("3.18cm");
|
||||||
|
var dinA4MarginTopBottom = (double) converter.ConvertFromInvariantString("2.54cm");
|
||||||
|
|
||||||
|
PrintDefaultFontSize = (double) converter.ConvertFromInvariantString("14pt");
|
||||||
|
PrintSubjectFontSize = (double) converter.ConvertFromInvariantString("16pt");
|
||||||
|
PrintNewlineFontSize = (double) converter.ConvertFromInvariantString("4pt");
|
||||||
|
// ReSharper restore PossibleNullReferenceException
|
||||||
|
|
||||||
|
DinA4Padding = new Thickness(dinA4MarginLeftRight, dinA4MarginTopBottom, dinA4MarginLeftRight,
|
||||||
|
dinA4MarginTopBottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Packaging;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Markup;
|
||||||
|
using System.Windows.Xps.Packaging;
|
||||||
|
using System.Windows.Xps.Serialization;
|
||||||
|
|
||||||
|
namespace UCalc.Controls
|
||||||
|
{
|
||||||
|
public class PrintableDocument : IDisposable
|
||||||
|
{
|
||||||
|
private static readonly Uri DocUri = new Uri($"pack://mietrechner{new Guid()}.xps");
|
||||||
|
private readonly Package _package;
|
||||||
|
private readonly XpsDocument _document;
|
||||||
|
|
||||||
|
private int PageCount =>
|
||||||
|
_document.GetFixedDocumentSequence()!.References.First().GetDocument(false)!.Pages.Count;
|
||||||
|
|
||||||
|
public PrintableDocument(IDocumentPaginatorSource source)
|
||||||
|
{
|
||||||
|
_package = Package.Open(new MemoryStream(), FileMode.Create, FileAccess.ReadWrite);
|
||||||
|
|
||||||
|
PackageStore.AddPackage(DocUri, _package);
|
||||||
|
|
||||||
|
_document = new XpsDocument(_package, CompressionOption.SuperFast, DocUri.AbsoluteUri);
|
||||||
|
var manager = new XpsSerializationManager(new XpsPackagingPolicy(_document), false);
|
||||||
|
|
||||||
|
var paginator = source.DocumentPaginator;
|
||||||
|
manager.SaveAsXaml(paginator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
((IDisposable) _document).Dispose();
|
||||||
|
((IDisposable) _package).Dispose();
|
||||||
|
PackageStore.RemovePackage(DocUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PreviewIn(DocumentViewer viewer)
|
||||||
|
{
|
||||||
|
viewer.Document = _document.GetFixedDocumentSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Print(string description)
|
||||||
|
{
|
||||||
|
var dialog = new PrintDialog {UserPageRangeEnabled = true, MinPage = 1, MaxPage = (uint) PageCount};
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
var documentSequence = _document.GetFixedDocumentSequence();
|
||||||
|
Package convPackage = null;
|
||||||
|
XpsDocument convDocument = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (dialog.PageRangeSelection == PageRangeSelection.UserPages)
|
||||||
|
{
|
||||||
|
convDocument = ExtractPages(_document, dialog.PageRange.PageFrom - 1,
|
||||||
|
dialog.PageRange.PageTo - 1, out convPackage);
|
||||||
|
documentSequence = convDocument.GetFixedDocumentSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.PrintDocument(documentSequence!.DocumentPaginator, description);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
convDocument?.Close();
|
||||||
|
convPackage?.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static XpsDocument ExtractPages(XpsDocument source, int fromPage, int toPage, out Package package)
|
||||||
|
{
|
||||||
|
package = Package.Open(new MemoryStream(), FileMode.Create, FileAccess.ReadWrite);
|
||||||
|
|
||||||
|
var docUri = new Uri("pack://mietrechnerTempTicket.xps");
|
||||||
|
PackageStore.RemovePackage(docUri);
|
||||||
|
PackageStore.AddPackage(docUri, package);
|
||||||
|
|
||||||
|
var document = new XpsDocument(package, CompressionOption.SuperFast, docUri.AbsoluteUri);
|
||||||
|
var pages = source.GetFixedDocumentSequence()!.References.First().GetDocument(false)!.Pages;
|
||||||
|
|
||||||
|
var documentReference = new DocumentReference();
|
||||||
|
var fixedDocument = new FixedDocument();
|
||||||
|
documentReference.SetDocument(fixedDocument);
|
||||||
|
|
||||||
|
for (var i = fromPage; i <= toPage; ++i)
|
||||||
|
{
|
||||||
|
var page = pages[i];
|
||||||
|
var pageContentChild = new PageContent {Source = page.Source};
|
||||||
|
((IUriContext) pageContentChild).BaseUri = ((IUriContext) page).BaseUri;
|
||||||
|
pageContentChild.GetPageRoot(false);
|
||||||
|
fixedDocument.Pages.Add(pageContentChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
var documentSequence = new FixedDocumentSequence();
|
||||||
|
documentSequence.References.Add(documentReference);
|
||||||
|
|
||||||
|
var writer = XpsDocument.CreateXpsDocumentWriter(document);
|
||||||
|
writer.Write(documentSequence);
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,15 +10,17 @@ namespace UCalc.Data
|
|||||||
{
|
{
|
||||||
public Tenant Tenant { get; }
|
public Tenant Tenant { get; }
|
||||||
public IReadOnlyDictionary<Cost, CostCalculationResult> Costs { get; }
|
public IReadOnlyDictionary<Cost, CostCalculationResult> Costs { get; }
|
||||||
|
public decimal SubTotalAmount { get; }
|
||||||
public decimal TotalAmount { get; }
|
public decimal TotalAmount { get; }
|
||||||
public string Details { get; }
|
public string Details { get; }
|
||||||
public string DetailsForLandlord { get; }
|
public string DetailsForLandlord { get; }
|
||||||
|
|
||||||
public TenantCalculationResult(Tenant tenant, IReadOnlyDictionary<Cost, CostCalculationResult> costs,
|
public TenantCalculationResult(Tenant tenant, IReadOnlyDictionary<Cost, CostCalculationResult> costs,
|
||||||
decimal totalAmount, string details, string detailsForLandlord)
|
decimal subTotalAmount, decimal totalAmount, string details, string detailsForLandlord)
|
||||||
{
|
{
|
||||||
Tenant = tenant;
|
Tenant = tenant;
|
||||||
Costs = costs;
|
Costs = costs;
|
||||||
|
SubTotalAmount = subTotalAmount;
|
||||||
TotalAmount = totalAmount;
|
TotalAmount = totalAmount;
|
||||||
Details = details;
|
Details = details;
|
||||||
DetailsForLandlord = detailsForLandlord;
|
DetailsForLandlord = detailsForLandlord;
|
||||||
@@ -616,6 +618,7 @@ namespace UCalc.Data
|
|||||||
var str = $"Zwischensumme: {totalAmount.CeilToString()} €\n";
|
var str = $"Zwischensumme: {totalAmount.CeilToString()} €\n";
|
||||||
str += $"Bereits bezahlt: {tenant.PaidRent.CeilToString()} €\n\n";
|
str += $"Bereits bezahlt: {tenant.PaidRent.CeilToString()} €\n\n";
|
||||||
|
|
||||||
|
var subTotalAmount = totalAmount;
|
||||||
totalAmount -= tenant.PaidRent;
|
totalAmount -= tenant.PaidRent;
|
||||||
totalAmount = totalAmount.Ceil2();
|
totalAmount = totalAmount.Ceil2();
|
||||||
|
|
||||||
@@ -624,7 +627,7 @@ namespace UCalc.Data
|
|||||||
details.Append(str);
|
details.Append(str);
|
||||||
detailsLandlord.Append(str);
|
detailsLandlord.Append(str);
|
||||||
|
|
||||||
return new TenantCalculationResult(tenant, costResults, totalAmount, details.ToString(),
|
return new TenantCalculationResult(tenant, costResults, subTotalAmount, totalAmount, details.ToString(),
|
||||||
detailsLandlord.ToString());
|
detailsLandlord.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ namespace UCalc.Pages
|
|||||||
|
|
||||||
private void OnAboutClick(object sender, RoutedEventArgs e)
|
private void OnAboutClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
MessageBox.Show("MietRechner Version 2.0\n\nCopyright © 2020 by Tobias Erbshäußer", "Über MietRechner",
|
||||||
|
MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
<Window x:Class="UCalc.PrintWindow"
|
||||||
|
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"
|
||||||
|
xmlns:drawing="clr-namespace:System.Drawing;assembly=System.Drawing.Primitives"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Title="Druckvorschau"
|
||||||
|
Width="500"
|
||||||
|
Height="600"
|
||||||
|
MinWidth="400"
|
||||||
|
MinHeight="300"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
ShowInTaskbar="False"
|
||||||
|
Icon="logo.ico">
|
||||||
|
|
||||||
|
<DockPanel>
|
||||||
|
<FlowDocumentScrollViewer x:Name="ScrollViewer"
|
||||||
|
Visibility="Collapsed">
|
||||||
|
<FlowDocument x:Name="Document"
|
||||||
|
PageWidth="{x:Static local:Constants.DinA4Width}"
|
||||||
|
PageHeight="{x:Static local:Constants.DinA4Height}"
|
||||||
|
PagePadding="{x:Static local:Constants.DinA4Padding}"
|
||||||
|
ColumnWidth="{x:Static local:Constants.DinA4ContentWidth}" />
|
||||||
|
</FlowDocumentScrollViewer>
|
||||||
|
|
||||||
|
<DocumentViewer x:Name="Viewer">
|
||||||
|
<DocumentViewer.Resources>
|
||||||
|
<Style TargetType="{x:Type DocumentViewer}">
|
||||||
|
<Setter Property="Foreground"
|
||||||
|
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
|
||||||
|
<Setter Property="Background"
|
||||||
|
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
|
||||||
|
<Setter Property="FocusVisualStyle"
|
||||||
|
Value="{x:Null}" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="{x:Type DocumentViewer}">
|
||||||
|
<Border BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
Focusable="False">
|
||||||
|
<Grid KeyboardNavigation.TabNavigation="Local">
|
||||||
|
<Grid.Background>
|
||||||
|
<SolidColorBrush Color="{DynamicResource ControlLightColor}" />
|
||||||
|
</Grid.Background>
|
||||||
|
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<ToolBar ToolBarTray.IsLocked="True"
|
||||||
|
KeyboardNavigation.TabNavigation="Continue">
|
||||||
|
<Button PreviewMouseUp="OnPrintClick">
|
||||||
|
<DockPanel>
|
||||||
|
<Viewbox Stretch="Uniform"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
Margin="4, 4, 0, 4">
|
||||||
|
<Canvas Width="512" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M448 192V77.25c0-8.49-3.37-16.62-9.37-22.63L393.37 9.37c-6-6-14.14-9.37-22.63-9.37H96C78.33 0 64 14.33 64 32v160c-35.35 0-64 28.65-64 64v112c0 8.84 7.16 16 16 16h48v96c0 17.67 14.33 32 32 32h320c17.67 0 32-14.33 32-32v-96h48c8.84 0 16-7.16 16-16V256c0-35.35-28.65-64-64-64zm-64 256H128v-96h256v96zm0-224H128V64h192v48c0 8.84 7.16 16 16 16h48v96zm48 72c-13.25 0-24-10.75-24-24 0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Drucken"
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Separator Background="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<Button Click="OnTenantSelectorClick"
|
||||||
|
Tag="{Binding Path=TenantMenuItems, RelativeSource={RelativeSource AncestorType=local:PrintWindow}}">
|
||||||
|
<DockPanel>
|
||||||
|
<Viewbox Stretch="Uniform"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
DockPanel.Dock="Right">
|
||||||
|
<Canvas Width="320" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Mieter auswählen"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<Button.ContextMenu>
|
||||||
|
<ContextMenu
|
||||||
|
ItemsSource="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
|
||||||
|
<ContextMenu.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type MenuItem}">
|
||||||
|
<EventSetter Event="Click" Handler="OnTenantMenuItemClick" />
|
||||||
|
<Setter Property="IsChecked" Value="{Binding Selected}"/>
|
||||||
|
<Setter Property="Header" Value="{Binding Name}" />
|
||||||
|
</Style>
|
||||||
|
</ContextMenu.ItemContainerStyle>
|
||||||
|
</ContextMenu>
|
||||||
|
</Button.ContextMenu>
|
||||||
|
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Separator Background="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<Button Command="NavigationCommands.IncreaseZoom"
|
||||||
|
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
|
||||||
|
<DockPanel>
|
||||||
|
<Viewbox Stretch="Uniform"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
Margin="4, 4, 0, 4">
|
||||||
|
<Canvas Width="512" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M304 192v32c0 6.6-5.4 12-12 12h-56v56c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-56h-56c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h56v-56c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v56h56c6.6 0 12 5.4 12 12zm201 284.7L476.7 505c-9.4 9.4-24.6 9.4-33.9 0L343 405.3c-4.5-4.5-7-10.6-7-17V372c-35.3 27.6-79.7 44-128 44C93.1 416 0 322.9 0 208S93.1 0 208 0s208 93.1 208 208c0 48.3-16.4 92.7-44 128h16.3c6.4 0 12.5 2.5 17 7l99.7 99.7c9.3 9.4 9.3 24.6 0 34zM344 208c0-75.2-60.8-136-136-136S72 132.8 72 208s60.8 136 136 136 136-60.8 136-136z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Vergrößern"
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button Command="NavigationCommands.DecreaseZoom"
|
||||||
|
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
|
||||||
|
<DockPanel>
|
||||||
|
<Viewbox Stretch="Uniform"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
Margin="4, 4, 0, 4">
|
||||||
|
<Canvas Width="512" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M304 192v32c0 6.6-5.4 12-12 12H124c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm201 284.7L476.7 505c-9.4 9.4-24.6 9.4-33.9 0L343 405.3c-4.5-4.5-7-10.6-7-17V372c-35.3 27.6-79.7 44-128 44C93.1 416 0 322.9 0 208S93.1 0 208 0s208 93.1 208 208c0 48.3-16.4 92.7-44 128h16.3c6.4 0 12.5 2.5 17 7l99.7 99.7c9.3 9.4 9.3 24.6 0 34zM344 208c0-75.2-60.8-136-136-136S72 132.8 72 208s60.8 136 136 136 136-60.8 136-136z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Verkleinern"
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Separator Background="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
|
||||||
|
<Button Command="DocumentViewer.FitToWidthCommand"
|
||||||
|
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}">
|
||||||
|
<DockPanel>
|
||||||
|
<Viewbox Stretch="Uniform"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
Margin="4, 4, 0, 4">
|
||||||
|
<Canvas Width="448" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M432 32H16A16 16 0 0 0 0 48v80a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16v-16h120v112h-24a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-24V112h120v16a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zm-68.69 260.69C354 283.36 336 288.36 336 304v48H112v-48c0-14.31-17.31-21.32-27.31-11.31l-80 80a16 16 0 0 0 0 22.62l80 80C94 484.64 112 479.64 112 464v-48h224v48c0 14.31 17.31 21.33 27.31 11.31l80-80a16 16 0 0 0 0-22.62z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Ganze Breite"
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button Command="DocumentViewer.FitToMaxPagesAcrossCommand"
|
||||||
|
CommandTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
|
||||||
|
CommandParameter="1">
|
||||||
|
<DockPanel>
|
||||||
|
<Viewbox Stretch="Uniform"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
Margin="4, 4, 0, 4">
|
||||||
|
<Canvas Width="512" Height="512">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<TranslateTransform X="0" Y="0" />
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Path Fill="{x:Static local:Constants.SubMainColor}">
|
||||||
|
<Path.Data>
|
||||||
|
<PathGeometry
|
||||||
|
Figures="M200 288H88c-21.4 0-32.1 25.8-17 41l32.9 31-99.2 99.3c-6.2 6.2-6.2 16.4 0 22.6l25.4 25.4c6.2 6.2 16.4 6.2 22.6 0L152 408l31.1 33c15.1 15.1 40.9 4.4 40.9-17V312c0-13.3-10.7-24-24-24zm112-64h112c21.4 0 32.1-25.9 17-41l-33-31 99.3-99.3c6.2-6.2 6.2-16.4 0-22.6L481.9 4.7c-6.2-6.2-16.4-6.2-22.6 0L360 104l-31.1-33C313.8 55.9 288 66.6 288 88v112c0 13.3 10.7 24 24 24zm96 136l33-31.1c15.1-15.1 4.4-40.9-17-40.9H312c-13.3 0-24 10.7-24 24v112c0 21.4 25.9 32.1 41 17l31-32.9 99.3 99.3c6.2 6.2 16.4 6.2 22.6 0l25.4-25.4c6.2-6.2 6.2-16.4 0-22.6L408 360zM183 71.1L152 104 52.7 4.7c-6.2-6.2-16.4-6.2-22.6 0L4.7 30.1c-6.2 6.2-6.2 16.4 0 22.6L104 152l-33 31.1C55.9 198.2 66.6 224 88 224h112c13.3 0 24-10.7 24-24V88c0-21.3-25.9-32-41-16.9z"
|
||||||
|
FillRule="NonZero" />
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Viewbox>
|
||||||
|
|
||||||
|
<Label Content="Ganze Seite"
|
||||||
|
Margin="4"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{x:Static local:Constants.SubMainColor}" />
|
||||||
|
</DockPanel>
|
||||||
|
</Button>
|
||||||
|
</ToolBar>
|
||||||
|
|
||||||
|
<ScrollViewer Grid.Row="1"
|
||||||
|
CanContentScroll="true"
|
||||||
|
HorizontalScrollBarVisibility="Auto"
|
||||||
|
x:Name="PART_ContentHost"
|
||||||
|
IsTabStop="true">
|
||||||
|
<ScrollViewer.Background>
|
||||||
|
<LinearGradientBrush EndPoint="0.5,1"
|
||||||
|
StartPoint="0.5,0">
|
||||||
|
<GradientStop Color="{DynamicResource ControlLightColor}"
|
||||||
|
Offset="0" />
|
||||||
|
<GradientStop Color="{DynamicResource ControlMediumColor}"
|
||||||
|
Offset="1" />
|
||||||
|
</LinearGradientBrush>
|
||||||
|
</ScrollViewer.Background>
|
||||||
|
</ScrollViewer>
|
||||||
|
|
||||||
|
<ContentControl Grid.Row="2"
|
||||||
|
x:Name="PART_FindToolBarHost" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</DocumentViewer.Resources>
|
||||||
|
</DocumentViewer>
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,345 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Controls.Primitives;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using UCalc.Annotations;
|
||||||
|
using UCalc.Controls;
|
||||||
|
using UCalc.Data;
|
||||||
|
using UCalc.Models;
|
||||||
|
|
||||||
|
namespace UCalc
|
||||||
|
{
|
||||||
|
public class TenantMenuItem : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public Tenant Tenant { get; }
|
||||||
|
public bool None { get; }
|
||||||
|
private bool _selected;
|
||||||
|
|
||||||
|
public bool Selected
|
||||||
|
{
|
||||||
|
get => _selected;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _selected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_selected = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TenantMenuItem(Tenant tenant, bool none)
|
||||||
|
{
|
||||||
|
Tenant = tenant;
|
||||||
|
None = none;
|
||||||
|
Selected = tenant != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name => Tenant != null ? Tenant.Name : None ? "Kein Mieter" : "Alle Mieter";
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
[NotifyPropertyChangedInvocator]
|
||||||
|
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class PrintWindow
|
||||||
|
{
|
||||||
|
public Billing Billing { get; }
|
||||||
|
public IReadOnlyList<TenantMenuItem> TenantMenuItems { get; }
|
||||||
|
private PrintableDocument _document;
|
||||||
|
|
||||||
|
|
||||||
|
public PrintWindow(Model model)
|
||||||
|
{
|
||||||
|
Billing = model.Dump();
|
||||||
|
TenantMenuItems = new[] {new TenantMenuItem(null, false), new TenantMenuItem(null, true)}.Concat(
|
||||||
|
Billing.Tenants.Select(tenant => new TenantMenuItem(tenant, false))).ToList();
|
||||||
|
|
||||||
|
foreach (var item in TenantMenuItems)
|
||||||
|
{
|
||||||
|
item.PropertyChanged += OnSelectedTenantChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
Preview();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClosed(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnClosed(e);
|
||||||
|
|
||||||
|
_document?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Preview()
|
||||||
|
{
|
||||||
|
Document.Blocks.Clear();
|
||||||
|
|
||||||
|
foreach (var item in TenantMenuItems)
|
||||||
|
{
|
||||||
|
if (!item.Selected)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = BillingCalculator.CalculateForTenant(Billing, item.Tenant);
|
||||||
|
PreviewForSingleTenant(item.Tenant, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
_document?.Dispose();
|
||||||
|
_document = new PrintableDocument(Document);
|
||||||
|
_document.PreviewIn(Viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddLineBreaks(TableRowGroup rowGroup, int count)
|
||||||
|
{
|
||||||
|
var row = new TableRow();
|
||||||
|
rowGroup.Rows.Add(row);
|
||||||
|
|
||||||
|
var cell = new TableCell {ColumnSpan = 2};
|
||||||
|
row.Cells.Add(cell);
|
||||||
|
cell.Blocks.Add(new Paragraph(new Run(new string('\n', count))
|
||||||
|
{FontSize = Constants.PrintNewlineFontSize}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddText(TableRowGroup rowGroup, string text, double? fontSize = null,
|
||||||
|
bool alignRight = false)
|
||||||
|
{
|
||||||
|
var row = new TableRow();
|
||||||
|
rowGroup.Rows.Add(row);
|
||||||
|
|
||||||
|
var cell = new TableCell {ColumnSpan = 2};
|
||||||
|
row.Cells.Add(cell);
|
||||||
|
|
||||||
|
if (alignRight)
|
||||||
|
{
|
||||||
|
cell.TextAlignment = TextAlignment.Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
var paragraph = new Paragraph(new Run(text));
|
||||||
|
cell.Blocks.Add(paragraph);
|
||||||
|
|
||||||
|
if (fontSize != null)
|
||||||
|
{
|
||||||
|
paragraph.FontSize = fontSize.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreviewForSingleTenant(Tenant tenant, TenantCalculationResult result)
|
||||||
|
{
|
||||||
|
var section = new Section {BreakPageBefore = true, FontSize = Constants.PrintDefaultFontSize};
|
||||||
|
Document.Blocks.Add(section);
|
||||||
|
|
||||||
|
var table = new Table {CellSpacing = 0};
|
||||||
|
section.Blocks.Add(table);
|
||||||
|
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||||
|
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||||
|
|
||||||
|
var rowGroup = new TableRowGroup();
|
||||||
|
table.RowGroups.Add(rowGroup);
|
||||||
|
|
||||||
|
void AddLineBreaks(int count)
|
||||||
|
{
|
||||||
|
PrintWindow.AddLineBreaks(rowGroup, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddText(string text, double? fontSize = null, bool alignRight = false)
|
||||||
|
{
|
||||||
|
PrintWindow.AddText(rowGroup, text, fontSize, alignRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCost(string name, decimal amount, bool isLast = false)
|
||||||
|
{
|
||||||
|
var row2 = new TableRow();
|
||||||
|
rowGroup.Rows.Add(row2);
|
||||||
|
|
||||||
|
if (isLast)
|
||||||
|
{
|
||||||
|
row2.Background = Brushes.LightGray;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cell2 = new TableCell
|
||||||
|
{BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1, 1, 0, isLast ? 1 : 0)};
|
||||||
|
row2.Cells.Add(cell2);
|
||||||
|
|
||||||
|
cell2.Blocks.Add(new Paragraph(new Run(name)) {Padding = new Thickness(6)});
|
||||||
|
|
||||||
|
cell2 = new TableCell
|
||||||
|
{
|
||||||
|
BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1, 1, 1, isLast ? 1 : 0),
|
||||||
|
TextAlignment = TextAlignment.Right
|
||||||
|
};
|
||||||
|
row2.Cells.Add(cell2);
|
||||||
|
|
||||||
|
cell2.Blocks.Add(new Paragraph(new Run($"{amount.CeilToString()} €")) {Padding = new Thickness(6)});
|
||||||
|
}
|
||||||
|
|
||||||
|
AddText(
|
||||||
|
$"{Billing.Landlord.Salutation.AsString()} {Billing.Landlord.Name}\n{DateTime.Now.ToString(Constants.DateFormat)}\n\n{Billing.Landlord.Address.Street} {Billing.Landlord.Address.HouseNumber}\n{Billing.Landlord.Address.Postcode} {Billing.Landlord.Address.City}\nTelefon: {Billing.Landlord.Phone}\nEmail: {Billing.Landlord.MailAddress}");
|
||||||
|
|
||||||
|
AddLineBreaks(2);
|
||||||
|
|
||||||
|
AddText(
|
||||||
|
$"{tenant.Salutation.AsString()} {tenant.Name}\n{Billing.House.Address.Street} {Billing.House.Address.HouseNumber}\n{Billing.House.Address.Postcode} {Billing.House.Address.City}",
|
||||||
|
null, true);
|
||||||
|
|
||||||
|
AddLineBreaks(4);
|
||||||
|
|
||||||
|
AddText($"{tenant.Salutation.AsString()} {tenant.Name}");
|
||||||
|
|
||||||
|
AddLineBreaks(1);
|
||||||
|
|
||||||
|
AddText(
|
||||||
|
$"Nebenkostenabrechnung vom {Billing.StartDate.ToString(Constants.DateFormat)} zum {Billing.EndDate.ToString(Constants.DateFormat)}",
|
||||||
|
Constants.PrintSubjectFontSize);
|
||||||
|
|
||||||
|
AddLineBreaks(1);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(tenant.CustomMessage1))
|
||||||
|
{
|
||||||
|
AddText(tenant.CustomMessage1);
|
||||||
|
|
||||||
|
AddLineBreaks(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (cost, costResult) in result.Costs)
|
||||||
|
{
|
||||||
|
AddCost(cost.Name, costResult.TotalAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCost("Zwischensumme", result.SubTotalAmount);
|
||||||
|
AddCost("Bereits gezahlt", tenant.PaidRent);
|
||||||
|
AddCost(result.TotalAmount > 0 ? "Einmalige Nachzahlung" : "Einmalige Rückzahlung", result.TotalAmount,
|
||||||
|
true);
|
||||||
|
|
||||||
|
AddLineBreaks(2);
|
||||||
|
|
||||||
|
if (result.TotalAmount > 0)
|
||||||
|
{
|
||||||
|
AddText(
|
||||||
|
$"Bitte überweisen Sie den einmaligen Betrag von {result.TotalAmount.CeilToString()} € auf das untenstehende Konto.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddText(
|
||||||
|
$"Der einmalige Betrag von {result.TotalAmount.CeilToString()} € wird in den nächsten Tagen auf Ihr Konto überwiesen.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AddLineBreaks(1);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(tenant.CustomMessage2))
|
||||||
|
{
|
||||||
|
AddText(tenant.CustomMessage2);
|
||||||
|
AddLineBreaks(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddText("Kontoverbindung:");
|
||||||
|
AddText($"IBAN: {Billing.Landlord.BankAccount.Iban}");
|
||||||
|
AddText($"BIC: {Billing.Landlord.BankAccount.Bic}");
|
||||||
|
AddText($"Name der Bank: {Billing.Landlord.BankAccount.BankName}");
|
||||||
|
|
||||||
|
AddLineBreaks(2);
|
||||||
|
|
||||||
|
AddText("Mit freundlichen Grüßen");
|
||||||
|
|
||||||
|
if (result.Costs.Any(t => t.Key.DisplayInBill))
|
||||||
|
{
|
||||||
|
PreviewForSingleTenantDetails(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreviewForSingleTenantDetails(TenantCalculationResult result)
|
||||||
|
{
|
||||||
|
var section = new Section {BreakPageBefore = true, FontSize = Constants.PrintDefaultFontSize};
|
||||||
|
Document.Blocks.Add(section);
|
||||||
|
|
||||||
|
var table = new Table {CellSpacing = 0};
|
||||||
|
section.Blocks.Add(table);
|
||||||
|
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||||
|
table.Columns.Add(new TableColumn {Width = new GridLength(1, GridUnitType.Star)});
|
||||||
|
|
||||||
|
var rowGroup = new TableRowGroup();
|
||||||
|
table.RowGroups.Add(rowGroup);
|
||||||
|
|
||||||
|
void AddLineBreaks(int count)
|
||||||
|
{
|
||||||
|
PrintWindow.AddLineBreaks(rowGroup, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddText(string text, double? fontSize = null, bool alignRight = false)
|
||||||
|
{
|
||||||
|
PrintWindow.AddText(rowGroup, text, fontSize, alignRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddText("Details zur Berechnung:");
|
||||||
|
|
||||||
|
AddLineBreaks(1);
|
||||||
|
|
||||||
|
foreach (var (cost, costResult) in result.Costs)
|
||||||
|
{
|
||||||
|
if (!cost.DisplayInBill)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddText(costResult.Details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPrintClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_document.Print(
|
||||||
|
$"MietRechner Abrechnung {Billing.StartDate.ToString(Constants.DateFormat)} - {Billing.EndDate.ToString(Constants.DateFormat)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectedTenantChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
Preview();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTenantSelectorClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var button = (Button) sender;
|
||||||
|
var contextMenu = button.ContextMenu;
|
||||||
|
// ReSharper disable once PossibleNullReferenceException
|
||||||
|
contextMenu.PlacementTarget = button;
|
||||||
|
contextMenu.Placement = PlacementMode.Bottom;
|
||||||
|
contextMenu.IsOpen = true;
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTenantMenuItemClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var item = (TenantMenuItem) ((MenuItem) sender).DataContext;
|
||||||
|
|
||||||
|
if (item.Tenant == null)
|
||||||
|
{
|
||||||
|
foreach (var item2 in TenantMenuItems)
|
||||||
|
{
|
||||||
|
if (item2.Tenant != null)
|
||||||
|
{
|
||||||
|
item2.Selected = !item.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.Selected = !item.Selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,6 +49,9 @@
|
|||||||
<Page Update="CostEntryDetailsWindow.xaml">
|
<Page Update="CostEntryDetailsWindow.xaml">
|
||||||
<Generator></Generator>
|
<Generator></Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Update="PrintWindow.xaml">
|
||||||
|
<Generator></Generator>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -94,6 +97,9 @@
|
|||||||
<Compile Update="CostEntryDetailsWindow.xaml.cs">
|
<Compile Update="CostEntryDetailsWindow.xaml.cs">
|
||||||
<DependentUpon>CostEntryDetailsWindow.xaml</DependentUpon>
|
<DependentUpon>CostEntryDetailsWindow.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Update="PrintWindow.xaml.cs">
|
||||||
|
<DependentUpon>PrintWindow.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Reference in New Issue
Block a user