2010-09-16 10 views
2

J'ai travaillé avec David Poll's CollectionPrinter Control et j'ai réussi à imprimer des rapports qui utilisent un DataGrid pour afficher la collection. Sans utiliser le regroupement dans le DataGrid, il pagine normalement le document. Cependant, dès que j'active le groupement en suivant ses instructions dans l'un des premiers commentaires du lien ci-dessus, la grille tente d'afficher tous les éléments de la première page et se coupe (plus de pagination).CollectionPrinter de David Poll peut gérer le regroupement dans une grille de données?

Voici le code que je tente d'utiliser pour le DataGrid groupé:

<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> 

Si quelqu'un a eu une chance de regrouper les données et l'impression à l'aide de sa méthode, je serais très heureux si vous pouviez aide moi.

Répondre

0

Voir le commentaire J'ai posté sur son site Web au http://www.davidpoll.com/2010/04/16/making-printing-easier-in-silverlight-4#comment-7197 pour une explication de ce que j'ai fait pour le faire fonctionner. Je vais mettre en place le code que j'ai changé dès que j'ai un peu de temps. Edit: Comme promis, voici les changements que j'ai faits pour que le travail de groupe fonctionne bien.

D'abord, j'ajouté deux interfaces au projet Printing.Controls

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

et

public interface IContainsContext 
{ 
    IContainsCollectionViewSource CollectionContext { get; } 
} 

Dans CollectionPrintContext.cs j'ajouté la propriété suivante pour loger le 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")); 
     } 
    } 
} 

Dans CollectionPrinter.cs, j'ai ensuite modifié CalculateChild. Le nouveau code comporte des commentaires le marquant

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; 
    } 

Dans le fichier cs de mon imprimante, j'ai défini le tri et le regroupement. Une chose à noter est la façon dont je l'ai configuré, cette PageCollectionViewSource sert uniquement de modèle pour le regroupement et le tri. Aucune donnée ne sera stockée dedans.

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(); 
    } 
} 

Cette classe InvReportData-je utiliser pour compléter les informations dans l'en-tête et pied de page ainsi et il semble que ce

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

    public CollectionViewSource PageCollectionSource { get; set; } 
} 

Et mon code XAML pour les modèles se fixe à la DisplayCollectionViewSource.View au lieu de la propriété 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> 

Et le dernier morceau de code que vous aurez besoin de mettre dans la fenêtre/contrôle où l'imprimante sera affiché/imprimé à partir. Ici, vous configurez la CollectionViewSource avec les données et le mettre à 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; 

de l'imprimante et ceux-ci devraient être tous les changements que vous devez faire pour obtenir le regroupement de travailler avec datagrids. Prendre plaisir.

+0

Je suis content que vous l'ayez compris, mais s'il vous plaît postez votre solution plutôt que d'y attacher un lien. –