C# WPF Печать шаблонных этикеток

234
23 марта 2019, 19:30

По работе, необходимо отправлять в печать на принтер этикетки нескольких видов, по выбору пользователя. (Транспортные этикетки на груз)

Например такие (шаблон 1):

И такое приложение написано и оно даже работает уже больше года. Проблема в том, что появилась потребность на ходу менять шаблон. (Например для особого клиента нужна доп инфа т.е. другой шаблон с другим количеством строк, колонок и т.д.)

Итак, как это работает в данный момент (файл PrintWindow.xaml.cs):

    namespace PrintTest
{
    /// <summary>
    /// Логика взаимодействия для PrintWindow.xaml
    /// </summary>
    public partial class PrintWindow
    {
        private const int LabelsPerPage = 10;
        public PrintWindow(string supplier, string counterparty, string address, string invoiceNo, int totalItem)
        {
            InitializeComponent();
            FillLabels(supplier, counterparty, address, invoiceNo, totalItem);
            Print();
            Close();
        }
        public void FillLabels(string supplier, string counterparty, string address, string invoiceNo, int totalItem)
        {
            var pages = new List<Page>();
            List<Label> labels = new List<Label>();
            string stItemNo = "";
            for (int l = 1, lp=1; l < totalItem + 1; l++, lp++)
            {
                if (lp > LabelsPerPage)
                {
                    lp = 1;
                    pages.Add(new Page() { LebelList = labels });
                    labels = new List<Label>();
                }
                stItemNo = l.ToString();
                if (stItemNo.Length < 2) stItemNo += " ";
                stItemNo += $" из {totalItem}";

                labels.Add(new Label()
                {
                    Supplier = supplier,
                    Counterparty = counterparty,
                    Address = address,
                    InvoiceNo = invoiceNo,
                    ItemNo = stItemNo
                });
            }
            pages.Add(new Page() { LebelList = labels });
            IcBook.DataContext = pages;
        }
        public void Print()
        {
            var dialog = new PrintDialog();
            if (dialog.ShowDialog() == true)
            {
                IcBook.Measure(new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight));
                IcBook.Arrange(new Rect(0, 0, 0, 0));
                var page = new List<Visual>();
                for (int i = 0; i < IcBook.Items.Count; i++)
                {
                    page.Add((Visual)IcBook.ItemContainerGenerator.ContainerFromIndex(i));
                }
                dialog.PrintDocument(new Paginator(page.ToArray()), "Этикетка");
            }
        }
    }
    public class Label
    {
        public string Supplier { get; set; }
        public string Counterparty { get; set; }
        public string Address { get; set; }
        public string InvoiceNo { get; set; }
        public string ItemNo { get; set; }
    }
    public class Page
    {
        public List<Label> LebelList { get; set; }
    }
    public class Paginator : DocumentPaginator
    {
        Visual[] _pages;
        public Paginator(params Visual[] pages)
        {
            _pages = pages;
            Source = new S() { DocumentPaginator = this };
        }
        public override bool IsPageCountValid => true;
        public override int PageCount => _pages.Length;
        public override Size PageSize { get; set; }
        class S : IDocumentPaginatorSource
        {
            public DocumentPaginator DocumentPaginator { get; set; }
        }
        public override IDocumentPaginatorSource Source { get; }
        public override DocumentPage GetPage(int pageNumber) => new DocumentPage(_pages[pageNumber]);
    }
}

И собственно сам файл PrintWindow.xaml:

<ItemsControl Name="IcBook" ItemsSource="{Binding}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Grid/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ItemsControl ItemsSource="{Binding LebelList}" Padding="20">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <WrapPanel/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Border Width="376.5" BorderBrush="Black" BorderThickness="3">
                                    <Grid>
                                        <Grid.Resources>
                                            <Style TargetType="TextBlock">
                                                <Setter Property="FontFamily" Value="Courier New"/>
                                                <Setter Property="VerticalAlignment" Value="Bottom"/>
                                            </Style>
                                        </Grid.Resources>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition/>
                                            <ColumnDefinition/>
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="37.944"/>
                                            <RowDefinition Height="40.376"/>
                                            <RowDefinition Height="42.376"/>
                                            <RowDefinition Height="41.052"/>
                                            <RowDefinition Height="40.052"/>
                                        </Grid.RowDefinitions>
                                        <TextBlock FontSize="25" Text="{Binding Supplier}" Grid.Row="0" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
                                        <TextBlock FontSize="35" Text="{Binding Counterparty}" Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
                                        <TextBlock FontSize="30" FontWeight="Bold" Text="{Binding Address}" Grid.Row="2" Grid.ColumnSpan="2" HorizontalAlignment="Center"/>
                                        <TextBlock FontSize="25" FontStyle="Italic" Text="Накладная:  " Grid.Row="3" Grid.Column="0" HorizontalAlignment="Right"/>
                                        <TextBlock FontSize="25" FontWeight="Bold" Text="{Binding InvoiceNo}" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left"/>
                                        <TextBlock FontSize="30" FontStyle="Italic" Text="Место:  " Grid.Row="4" Grid.Column="0" HorizontalAlignment="Right"/>
                                        <TextBlock FontSize="30" FontWeight="Bold" Text="{Binding ItemNo}" Grid.Row="4" Grid.Column="1" HorizontalAlignment="Left"/>
                                    </Grid>
                                </Border>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

Итак. Сам вопрос: Как можно использовать вместо фиксированного ItemsControl несколько или как в ItemsControl можно заменить DataTemplate на какой то из заготовленных.

P.S. Извиняюсь за возможно излишний код. Не знаю что нужно для понимания ситуации

READ ALSO
Исправить ошибки в коде [закрыт]

Исправить ошибки в коде [закрыт]

Помогите, пожалуйста, исправить ошибки

121
Как изменить опцию в dll

Как изменить опцию в dll

Пишу учебный проект совсем скоро сдача, и как всегда проблемы у библиотеки EMGU CV(open cv) отобрали патент на SURF методИ он был отключен в сборке

150
Создание и запись файлов через потоки

Создание и запись файлов через потоки

Есть класс генерации строки определенного форамата:

160
C# System.Diagnostics.Process.GetProcessesByName ест много памяти

C# System.Diagnostics.Process.GetProcessesByName ест много памяти

У меня есть две программы которые просто проверяют наличие процессов друг-друга методом SystemDiagnostics

137