 <p>See the comment I posted in his website at <a href="http://www.davidpoll.com/2010/04/16/making-printing-easier-in-silverlight-4#comment-7197" rel="nofollow">http://www.davidpoll.com/2010/04/16/making-printing-easier-in-silverlight-4#comment-7197</a> for an explanation of what I did to get it working. I'll put up the code I changed as soon as I have some time.</p> <p>Edit: As promised, here are the changes that I made for grouping to work.</p> <p>First I added two interfaces to the Printing.Controls project</p> <pre><code>public interface IContainsCollectionViewSource { CollectionViewSource PageCollectionSource { get; set; } } </code></pre> <p>and </p> <pre><code>public interface IContainsContext { IContainsCollectionViewSource CollectionContext { get; } } </code></pre> <p>In CollectionPrintContext.cs I added the following property to house the CollectionViewSource</p> <pre><code>private CollectionViewSource displayCollectionViewSource; /// &lt;summary&gt; /// Gets or sets the data grid collection view which can be used to group and sort the display control. /// &lt;/summary&gt; public CollectionViewSource DisplayCollectionViewSource { get { return this.displayCollectionViewSource; } set { if (!object.Equals(this.displayCollectionViewSource, value)) { this.displayCollectionViewSource = value; PropertyChanged.Raise(this, new PropertyChangedEventArgs("DisplayCollectionViewSource")); } } } </code></pre> <p>In CollectionPrinter.cs I then modified CalculateChild. New code has comments marking it</p> <pre><code>private void CalculateChild&lt;T&gt;(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&lt;T&gt;().Skip(this.CurrentPrintContext.FirstItemIndex).ToArray(); ObservableCollection&lt;T&gt; pageItems = new ObservableCollection&lt;T&gt;(); 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(() =&gt; { try { this.CurrentPrintContext.IsLastPage = false; bool reachedEnd = false; int itemsAdded = 0; do { if (itemsAdded &gt;= items.Length || (this.MaximumItemsPerPage != -1 &amp;&amp; itemsAdded &gt;= 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() &amp;&amp; this.CheckHeight()); while (!reachedEnd &amp;&amp; itemsAdded != 1 &amp;&amp; !(this.CheckExpandedWidth() &amp;&amp; this.CheckExpandedHeight() &amp;&amp; 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(() =&gt; { DriveAnimationsToCompletion(popup); this.Dispatcher.BeginInvoke(() =&gt; { popup.IsOpen = false; popup.Child = null; layoutContainer.Children.Clear(); lock (signal) Monitor.Pulse(signal); }); }); } catch (Exception e) { MessageBox.Show(e.ToString()); } }, () =&gt; this._VisualChild != null); popup.IsOpen = true; } </code></pre> <p>In my Printer's cs file I set the sorting and grouping. One thing to note is the way I have it setup, this PageCollectionViewSource serves only as a template for the grouping and sorting. No data will be stored in it.</p> <pre><code>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(); } } </code></pre> <p>That InvReportData class I use to fill in information in the header and footer as well and it looks like this</p> <pre><code>public class InvReportData : IContainsCollectionViewSource { public string BoatName { get; set; } public string ReportTypeLabel { get; set; } public string Date { get; set; } public CollectionViewSource PageCollectionSource { get; set; } } </code></pre> <p>And my xaml code for the templates binds to the DisplayCollectionViewSource.View instead of the CurrentItems property</p> <pre><code> &lt;Printing:CollectionPrinter.FooterTemplate&gt; &lt;DataTemplate&gt; &lt;Grid&gt; &lt;TextBlock HorizontalAlignment="Left" Text="{Binding Host.Context.Date}" /&gt; &lt;StackPanel HorizontalAlignment="Right" Orientation="Horizontal"&gt; &lt;TextBlock Text="{Binding CurrentPage, StringFormat='{}Page {0} '}" /&gt; &lt;TextBlock Text="{Binding PageCount, StringFormat='{}/ {0}'}" /&gt; &lt;/StackPanel&gt; &lt;/Grid&gt; &lt;/DataTemplate&gt; &lt;/Printing:CollectionPrinter.FooterTemplate&gt; &lt;Printing:CollectionPrinter.BodyTemplate&gt; &lt;DataTemplate&gt; &lt;sdk:DataGrid x:Name="ReportDataGrid" ItemsSource="{Binding DisplayCollectionViewSource.View}" AutoGenerateColumns="False" VerticalScrollBarVisibility="Disabled"&gt; &lt;sdk:DataGrid.RowGroupHeaderStyles&gt; &lt;Style TargetType="sdk:DataGridRowGroupHeader"&gt; &lt;Setter Property="PropertyNameVisibility" Value="Collapsed"/&gt; &lt;Setter Property="ItemCountVisibility" Value="Collapsed" /&gt; &lt;Setter Property="SublevelIndent" Value="10" /&gt; &lt;/Style&gt; &lt;/sdk:DataGrid.RowGroupHeaderStyles&gt; &lt;sdk:DataGrid.Columns&gt; &lt;sdk:DataGridTextColumn Binding="{Binding SkU}" Header="SKU" MinWidth="150" /&gt; &lt;sdk:DataGridTextColumn Binding="{Binding ItemDesc}" Header="Product Description" Width="*"/&gt; &lt;sdk:DataGridTextColumn Binding="{Binding CorrectionsDisplay}" Header="Corrections?" /&gt; &lt;sdk:DataGridTextColumn Binding="{Binding QtyLocDisplay}" Header="Qty/Loc"/&gt; &lt;/sdk:DataGrid.Columns&gt; &lt;/sdk:DataGrid&gt; &lt;/DataTemplate&gt; &lt;/Printing:CollectionPrinter.BodyTemplate&gt; </code></pre> <p>And the final piece of code you will need to put in the window/control where the printer will be displayed/printed from. Here you setup the CollectionViewSource with the data and set it to the printer's ItemsSource</p> <pre><code>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; </code></pre> <p>And those should be all the changes you have to make to get the grouping to work with datagrids. Enjoy.</p>