Может ли CollectionPrinter Дэвида Полла обрабатывать группировки в сетке данных? - PullRequest
2 голосов
/ 16 сентября 2010

Я работал с элементом управления CollectionPrinter Дэвида Полла и успешно распечатал отчеты, которые используют DataGrid для отображения коллекции.Без использования группировки в сетке данных он разбивает документ на страницы как обычно.Однако, как только я активирую группировку, следуя его инструкциям в одном из первых комментариев по ссылке выше, сетка пытается отобразить все элементы на первой странице и отключается (больше нет нумерации страниц).

Вот код, который я пытаюсь использовать для сгруппированной DataGrid:

<Printing:CollectionPrinter.BodyTemplate>
    <DataTemplate>
        <Grid Height="Auto">
            <Grid.Resources>
                <CollectionViewSource x:Key="groupedCollection" Source="{Binding CurrentItems}">
                    <CollectionViewSource.GroupDescriptions>
                        <PropertyGroupDescription PropertyName="BaFolioNum" />
                        <PropertyGroupDescription PropertyName="CategoryDesc"/>
                    </CollectionViewSource.GroupDescriptions>
                </CollectionViewSource>
            </Grid.Resources>
            <sdk:DataGrid  ItemsSource="{Binding Source={StaticResource groupedCollection}}" AutoGenerateColumns="False" 
                          VerticalScrollBarVisibility="Disabled">
                <sdk:DataGrid.Resources>

                </sdk:DataGrid.Resources>
                <sdk:DataGrid.RowGroupHeaderStyles>
                    <Style TargetType="sdk:DataGridRowGroupHeader">
                        <Setter Property="PropertyNameVisibility" Value="Collapsed"/>
                        <Setter Property="SublevelIndent" Value="10" />
                    </Style>
                </sdk:DataGrid.RowGroupHeaderStyles>

                <sdk:DataGrid.Columns>
                    <sdk:DataGridTextColumn Binding="{Binding SkU}"  Header="SKU" MinWidth="150" />
                    <sdk:DataGridTextColumn Binding="{Binding ItemDesc}" Header="Product Description" Width="*"/>
                    <sdk:DataGridTextColumn Binding="{Binding CorrectionsDisplay}" Header="Corrections?" />
                    <sdk:DataGridTextColumn Binding="{Binding QtyLocDisplay}" Header="Qty/Loc"/>
                </sdk:DataGrid.Columns>
            </sdk:DataGrid>
        </Grid>
    </DataTemplate>
</Printing:CollectionPrinter.BodyTemplate>

Если кому-то повезло, сгруппировав данные и распечатав их, используя его метод, я был бы очень признателен, если бы вы могли мне помочьвне.

1 Ответ

0 голосов
/ 04 ноября 2010

См. Комментарий, который я разместил на его сайте по адресу http://www.davidpoll.com/2010/04/16/making-printing-easier-in-silverlight-4#comment-7197, для объяснения того, что я сделал, чтобы заставить его работать.Я добавлю код, который я изменил, как только у меня будет время.

Редактировать: Как и было обещано, вот изменения, которые я сделал для работы группировки.

Сначала я добавил дваинтерфейсы к проекту Printing.Controls

public interface IContainsCollectionViewSource
{
    CollectionViewSource PageCollectionSource { get; set; }
}

и

public interface IContainsContext
{
    IContainsCollectionViewSource CollectionContext { get; }
}

В CollectionPrintContext.cs я добавил следующее свойство для размещения CollectionViewSource

private CollectionViewSource displayCollectionViewSource;
/// <summary>
/// Gets or sets the data grid collection view which can be used to group and sort the display control.
/// </summary>
public CollectionViewSource DisplayCollectionViewSource
{
    get
    {
        return this.displayCollectionViewSource;
    }
    set
    {
        if (!object.Equals(this.displayCollectionViewSource, value))
        {
            this.displayCollectionViewSource = value;
            PropertyChanged.Raise(this, new PropertyChangedEventArgs("DisplayCollectionViewSource"));
        }
    }
}

в CollectionPrinterЗатем я изменил CalculateChild.Новый код имеет комментарии, помечающие его

private void CalculateChild<T>(object signal)
    {
        Debug.Assert(!this._IsRoot);
        Popup popup = new Popup();
        Grid layoutContainer;
        popup.Child = layoutContainer = new Grid();
        layoutContainer.Children.Add(this);
        popup.Opacity = 0;
        layoutContainer.Opacity = 0;
        layoutContainer.IsHitTestVisible = false;
        popup.IsHitTestVisible = false;
        this.Width = popup.Width = this.CurrentPrintContext.PrintableArea.Width;
        this.Height = popup.Height = this.CurrentPrintContext.PrintableArea.Height;
        var items = (this.ItemsSource ?? new T[0]).Cast<T>().Skip(this.CurrentPrintContext.FirstItemIndex).ToArray();
        ObservableCollection<T> pageItems = new ObservableCollection<T>();
        this.CurrentPrintContext.CurrentItems = pageItems;
        //New Code Block Starts Here
        if (this.CurrentPrintContext.Host as IContainsContext != null)
        {
            if (((IContainsContext)this.CurrentPrintContext.Host).CollectionContext != null)
            {
                this.CurrentPrintContext.DisplayCollectionViewSource = new CollectionViewSource();
                foreach (GroupDescription groupDescription in ((IContainsContext)this.CurrentPrintContext.Host).CollectionContext.PageCollectionSource.GroupDescriptions)
                {
                    this.CurrentPrintContext.DisplayCollectionViewSource.GroupDescriptions.Add(groupDescription);
                }
                foreach (SortDescription  sortDescription in ((IContainsContext)this.CurrentPrintContext.Host).CollectionContext.PageCollectionSource.SortDescriptions)
                {
                    this.CurrentPrintContext.DisplayCollectionViewSource.SortDescriptions.Add(sortDescription);
                }

                this.CurrentPrintContext.DisplayCollectionViewSource.Source = pageItems;
            }
        }
        //New Code Block Ends Here
        this.Dispatcher.DelayUntil(() =>
            {
                try
                {
                    this.CurrentPrintContext.IsLastPage = false;
                    bool reachedEnd = false;
                    int itemsAdded = 0;
                    do
                    {
                        if (itemsAdded >= items.Length ||
                            (this.MaximumItemsPerPage != -1 && itemsAdded >= this.MaximumItemsPerPage))
                        {
                            reachedEnd = true;
                            break;
                        }
                        pageItems.Add(items[itemsAdded++]);
                        this.CurrentPrintContext.LastItemIndex = this.CurrentPrintContext.FirstItemIndex +
                                                                 itemsAdded - 1;
                        if (itemsAdded == items.Length)
                            this.CurrentPrintContext.IsLastPage = true;
                        this.CurrentPrintContext.NotifyPropertiesChanged();
                        //New Code Block Starts Here
                        if (this.CurrentPrintContext.DisplayCollectionViewSource != null) this.CurrentPrintContext.DisplayCollectionViewSource.View.Refresh();
                        //New Code Block Ends Here
                        //popup.UpdateLayout();
                        this._VisualChild.Measure(this.CurrentPrintContext.PrintableArea);
                    } while (this.CheckWidth() && this.CheckHeight());
                    while (!reachedEnd && itemsAdded != 1 &&
                           !(this.CheckExpandedWidth() && this.CheckExpandedHeight() &&
                             this.CheckExpandedWidthHeight()))
                    {
                        pageItems.RemoveAt(pageItems.Count - 1);
                        itemsAdded--;
                        this.CurrentPrintContext.LastItemIndex = this.CurrentPrintContext.FirstItemIndex +
                                                                 itemsAdded - 1;
                        this.CurrentPrintContext.IsLastPage = false;
                        this.CurrentPrintContext.NotifyPropertiesChanged();
                    }
                    this.Dispatcher.BeginInvoke(() =>
                        {
                            DriveAnimationsToCompletion(popup);
                            this.Dispatcher.BeginInvoke(() =>
                                {
                                    popup.IsOpen = false;
                                    popup.Child = null;
                                    layoutContainer.Children.Clear();
                                    lock (signal)
                                        Monitor.Pulse(signal);
                                });
                        });
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }
            },
                                   () => this._VisualChild != null);
        popup.IsOpen = true;
    }

В файле cs моего принтера я установил сортировку и группировку.Одна вещь, на которую стоит обратить внимание, это то, как я ее настроил, этот PageCollectionViewSource служит только шаблоном для группировки и сортировки.В нем не будет храниться никаких данных.

public partial class InventoryPrinter : CollectionPrinter, IContainsContext
{
    private InvReportData context;
    public InvReportData Context
    {
        get
        {
            return context;
        }
        set
        {
            context = value;
            try
            {


                context.PageCollectionSource = new CollectionViewSource() ;
                //context.PageCollectionSource.SortDescriptions.Add(new SortDescription("SkuP1nBr", ListSortDirection.Ascending));
                //context.PageCollectionSource.SortDescriptions.Add(new SortDescription("SkuP2tXt", ListSortDirection.Ascending));
                //context.PageCollectionSource.SortDescriptions.Add(new SortDescription("SkuP3nBr", ListSortDirection.Ascending));
                //context.PageCollectionSource.SortDescriptions.Add(new SortDescription("SkuP4tXt", ListSortDirection.Ascending));
                //context.PageCollectionSource.SortDescriptions.Add(new SortDescription("SkuP5", ListSortDirection.Ascending));
                //context.PageCollectionSource.SortDescriptions.Add(new SortDescription("BaFolioNum", ListSortDirection.Ascending));
                //context.PageCollectionSource.GroupDescriptions.Add(new PropertyGroupDescription("BaFolioNum"));
                context.PageCollectionSource.GroupDescriptions.Add(new PropertyGroupDescription("BaFolioDisplay"));
                context.PageCollectionSource.GroupDescriptions.Add(new PropertyGroupDescription("CategoryDesc"));
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

    public IContainsCollectionViewSource CollectionContext
    {
        get
        {
            return context;
        }
    }

    public InventoryPrinter()
    {
        InitializeComponent();  
    }
}

Этот класс InvReportData, который я использую для заполнения информации в верхнем и нижнем колонтитулах, также выглядит так:

public class InvReportData : IContainsCollectionViewSource
{
    public string BoatName { get; set; }
    public string ReportTypeLabel { get; set; }
    public string Date { get; set; }

    public CollectionViewSource PageCollectionSource { get; set; }
}

И мой xamlкод для шаблонов привязывается к DisplayCollectionViewSource.View вместо свойства CurrentItems

    <Printing:CollectionPrinter.FooterTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock HorizontalAlignment="Left" Text="{Binding Host.Context.Date}" />
            <StackPanel HorizontalAlignment="Right"
                        Orientation="Horizontal">
                <TextBlock Text="{Binding CurrentPage, StringFormat='{}Page {0} '}" />
                <TextBlock Text="{Binding PageCount, StringFormat='{}/ {0}'}" />
            </StackPanel>
        </Grid>
    </DataTemplate>
</Printing:CollectionPrinter.FooterTemplate>
<Printing:CollectionPrinter.BodyTemplate>
    <DataTemplate>
        <sdk:DataGrid x:Name="ReportDataGrid"  ItemsSource="{Binding DisplayCollectionViewSource.View}" AutoGenerateColumns="False" 
                          VerticalScrollBarVisibility="Disabled">
            <sdk:DataGrid.RowGroupHeaderStyles>
                <Style TargetType="sdk:DataGridRowGroupHeader">
                    <Setter Property="PropertyNameVisibility" Value="Collapsed"/>
                    <Setter Property="ItemCountVisibility" Value="Collapsed" />
                    <Setter Property="SublevelIndent" Value="10" />
                </Style>
            </sdk:DataGrid.RowGroupHeaderStyles>

            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Binding="{Binding SkU}"  Header="SKU" MinWidth="150" />
                <sdk:DataGridTextColumn Binding="{Binding ItemDesc}" Header="Product Description" Width="*"/>
                <sdk:DataGridTextColumn Binding="{Binding CorrectionsDisplay}" Header="Corrections?" />
                <sdk:DataGridTextColumn Binding="{Binding QtyLocDisplay}" Header="Qty/Loc"/>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
    </DataTemplate>
</Printing:CollectionPrinter.BodyTemplate>

И последний фрагмент кода, который вам нужно будет поместить в окно / элемент управления, откуда будет отображаться / распечатываться принтер.Здесь вы настраиваете CollectionViewSource с данными и устанавливаете его для ItemsSource принтера

InvReportData headerFooterData = new InvReportData();
headerFooterData.BoatName = boatName;
headerFooterData.Date = DateTime.Today.ToString("dddd, dd MMMM yyyy");
CollectionSource = new CollectionViewSource { Source = reportData }.View;
        CollectionSource.SortDescriptions.Add(new SortDescription("BaFolioNum", ListSortDirection.Ascending));
        CollectionSource.SortDescriptions.Add(new SortDescription("SkuP1nBr", ListSortDirection.Ascending));
        CollectionSource.SortDescriptions.Add(new SortDescription("SkuP2tXt", ListSortDirection.Ascending));
        CollectionSource.SortDescriptions.Add(new SortDescription("SkuP3nBr", ListSortDirection.Ascending));
        CollectionSource.SortDescriptions.Add(new SortDescription("SkuP4tXt", ListSortDirection.Ascending));
        CollectionSource.SortDescriptions.Add(new SortDescription("SkuP5", ListSortDirection.Ascending));
        //CollectionSource.GroupDescriptions.Add(new PropertyGroupDescription("BaFolioNum"));
        CollectionSource.GroupDescriptions.Add(new PropertyGroupDescription("BaFolioDisplay"));
        CollectionSource.GroupDescriptions.Add(new PropertyGroupDescription("CategoryDesc"));

        printer.ItemsSource = CollectionSource;
        printer.Context = headerFooterData;

И это должны быть все изменения, которые вы должны сделать, чтобы заставить группу работать с сетями данных.Наслаждайтесь.

...