David Poll的CollectionPrinter可以处理数据网格中的分组吗?

时间:2010-09-16 19:15:14

标签: silverlight printing reporting

我一直在使用David Poll's CollectionPrinter Control并已成功打印使用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 :(得分:0)

请参阅我在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.cs中,我修改了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;

这些应该是您必须进行的所有更改才能使分组与datagrids一起使用。享受。