2010-08-03 6 views
10

Sto tentando di stampare un documento wpf. Sto usando documentpaginator per l'impaginazione e un controllo utente per creare un'immagine visuale da stampare. Il mio controllo utente ha poche caselle di testo e un datagrid associato agli oggetti dati che vengono passati al controllo utente in fase di runtime.Stampa di Dynamic Usercontrol tramite cercapersone del documento in WPF: Datagrid viene stampato vuoto

Ora il codice funziona benissimo quando si stampa su un documento XPS ma quando si stampa su una stampante fisica, il mio datagrid viene stampato vuoto anche se altre caselle di testo stanno stampando perfettamente.

Di seguito è il codice per la classe paginator getPage Metodo:

SaleOrderPage page = new SaleOrderPage(order, pageNumber, controlSize); 
     page.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); 
     page.Arrange(new Rect(new Point(0, 0), PageSize)); 
     page.InitPrint(); 
     page.UpdateLayout(); 

     return new DocumentPage(page); 

metodo InitPrint inizializzazione mio datagrid e vincolante per l'origine dati. Ecco il codice per il metodo InitPrint.

public void InitPrint() { 
     var sales = ctx.SalesOrders.Where(so => so.Id.Equals(order.Id)).First().Sales.Skip(pageNumber * PageRows).Take(PageRows); 
     var printData = sales.Select(x => new { 
      Particulars = string.Format("{0} - {1}", x.Item.Brand.Name, x.Item.Shade.Name), 
      Quantity = string.Format("{0} {1}", x.Quantity, x.Item.Brand.Unit.Symbol) 
     }).ToList(); 

     dgSales.ItemsSource = printData; 
     dgSalesCopy.ItemsSource = printData; 
    } 

credo che mi manca qualche passaggio durante la stampa allo stampatore reale perché funziona come ci si aspetta da una stampante XPS, ma non a una stampante fisica.

Grazie per la domanda di lettura,

Naveen

risposta

2

Date un'occhiata a questo tutorial. Sepolto nei commenti è un DocumentPaginator che è stato creato esplicitamente per la stampa di un DataGrid.

public class DocPaginator : DocumentPaginator 
{ 
    #region Fields 

    private int _rows; 
    private int _columns; 
    private int _rowsPerPage; 
    private int _columnsPerPage; 
    private int _firstColumnWidth; 
    private int _horizontalPageCount; 
    private int _verticalPageCount; 
    private System.Windows.Size _pageSize;   
    private DataGrid _dataGrid; 
    private List<string> _columnsList; 
    private bool _isFirstColumnLarger; 
    private List<Dictionary<int, Pair<int, int>>> _columnSlotsList; 
    private string _strTitle; 
    private string _strComment; 

    #endregion Fields 

    #region Constructor 

    public DocPaginator(DataGrid dataGrid, System.Windows.Size pageSize, List<string> columnsList, 
          bool isFirstColumnLarger = false, string strTitle = null, string strComment = null) 
    { 
     _rows = dataGrid.Items.Count; 
     _columns = dataGrid.Columns.Count;    
     _dataGrid = dataGrid; 
     _columnsList = columnsList; 
     _isFirstColumnLarger = isFirstColumnLarger; 
     _strTitle = strTitle; 
     _strComment = strComment; 

     CalculateFirstColumnWidth(); 

     PageSize = pageSize; 

     _horizontalPageCount = HorizontalPageCount; 
     _verticalPageCount = VerticalPageCount; 

     GenerateColumnSlots(); 
    } 

    #endregion Constructor 

    #region Public Methods 

    public override DocumentPage GetPage(int pageNumber) 
    { 
     double pgNumber = Math.IEEERemainder(pageNumber, _verticalPageCount) >= 0 ? 
          Math.IEEERemainder(pageNumber, _verticalPageCount) : 
           Math.IEEERemainder(pageNumber, _verticalPageCount) + _verticalPageCount; 

     int currentRow = Convert.ToInt32(_rowsPerPage * pgNumber); 

     var page = new PageElement(currentRow, Math.Min(_rowsPerPage, _rows - currentRow), _dataGrid, 
             _columnsList, _firstColumnWidth, _isFirstColumnLarger, 
              GetColumnSlot(pageNumber), _strTitle, _strComment, GetPageNumber(pageNumber)) 
     { 
      Width = PageSize.Width, 
      Height = PageSize.Height, 
     }; 

     page.Measure(PageSize); 
     page.Arrange(new Rect(new System.Windows.Point(0, 0), PageSize)); 

     return new DocumentPage(page); 
    } 



    #endregion Public Methods 

    #region Public Properties 

    public override bool IsPageCountValid 
    { get { return true; } } 

    public override int PageCount 
    { get { return _horizontalPageCount * _verticalPageCount; } } 

    public override System.Windows.Size PageSize 
    { 
     get { return _pageSize; } 
     set 
     { 
      _pageSize = value; 
      _rowsPerPage = PageElement.RowsPerPage(PageSize.Height); 
      _columnsPerPage = PageElement.ColumnsPerPage(PageSize.Width, _firstColumnWidth); 

      //Can't print anything if you can't fit a row on a page 
      Debug.Assert(_rowsPerPage > 0); 
     } 
    } 

    public override IDocumentPaginatorSource Source 
    { get { return null; } } 

    public int HorizontalPageCount 
    { 
     get { return (int)Math.Ceiling((_columns - 1)/(double)_columnsPerPage); } 
    } 

    public int VerticalPageCount 
    { 
     get { return (int)Math.Ceiling(_rows/(double)_rowsPerPage); } 
    } 

    #endregion Public Properties 

    #region Private Methods 

    private void CalculateFirstColumnWidth() 
    { 
     int maxDataLen = 0; 

     for (int i = 0; i < _dataGrid.Items.Count; i++) 
     { 
      List<Object> icol = (List<Object>)_dataGrid.Items[i]; 
      var largestDataItem = (from d in icol 
            select d != null ? d.ToString().Length : 0).Max(); 
      maxDataLen = maxDataLen < largestDataItem ? largestDataItem : maxDataLen; 
     } 

     string strDataLen = string.Join("a", new string[maxDataLen + 1]); 

     _firstColumnWidth = PageElement.CalculateBitLength(strDataLen, 
              new Font("Tahoma", 8, System.Drawing.FontStyle.Regular, GraphicsUnit.Point)); 
    } 

    private void GenerateColumnSlots() 
    { 
     _columnSlotsList = new List<Dictionary<int, Pair<int, int>>>(); 

     for (int i = 0; i < _horizontalPageCount; i++) 
     { 
      Dictionary<int, Pair<int, int>> columnSlot = new Dictionary<int, Pair<int, int>>(); 
      columnSlot.Add(1, new Pair<int, int>((_columnsPerPage * i) + 1, 
                Math.Min(_columnsPerPage * (i + 1), _columns - 1))); 

      _columnSlotsList.Add(columnSlot); 
     } 
    } 

    private Dictionary<int, Pair<int, int>> GetColumnSlot(int pageNumber) 
    { 
     for (int i = 0; i <= _columnSlotsList.Count; i++) 
     { 
      if (i == Math.Ceiling(Convert.ToDouble(pageNumber/_verticalPageCount))) 
       return _columnSlotsList[i]; 
     } 
     return new Dictionary<int, Pair<int, int>>(); 
    } 

    private string GetPageNumber(int intPageNumber) 
    { 
     string strPageNumber = String.Empty; 

     if (_horizontalPageCount == 1) 
      strPageNumber = (intPageNumber + 1).ToString(); 
     else 
     { } 

     return strPageNumber; 
    } 

    #endregion Private Methods 
} 

#region Pair Class 

public class Pair<TStart, TEnd> 
{ 
    public Pair(TStart start, TEnd end) 
    { 
     Start = start; 
     End = end; 
    } 

    public TStart Start { get; set; } 
    public TEnd End { get; set; } 
} 

#endregion 
And this is the enhanced version of PageElement: 

public class PageElement : UserControl 
{ 
    #region Constants 

    private const int PAGE_MARGIN = 40; 
    private const int HEADER_HEIGHT = 50; 
    private const int LINE_HEIGHT = 20; 
    private const int COLUMN_WIDTH = 60; 
    private const int HEADER_CHR_WIDTH = 9; 
    private const int HEADER_LINE_HEIGHT = 12; 
    private const string EXCAPE_CHAR = "\r\n"; 
    private const string NOT_APPLICAPLE = "N/A"; 

    #endregion Constants 

    #region Fields 

    private int _currentRow; 
    private int _rows; 
    private DataGrid _dataGrid; 
    private List<string> _columns; 
    private int _firstColumnWidth;   
    private bool _isFirstColumnLarger; 
    private static int _columnsPerPage; 
    private Dictionary<int, Pair<int, int>> _columnSlot; 
    private string _strTitle; 
    private string _strComment; 
    private string _strPageNumber;   

    #endregion Fields 

    #region Constructor 

    public PageElement(int currentRow, int rows, DataGrid dataGrid, List<string> columns, 
         int firstColumnWidth, bool isFirstColumnLarger, Dictionary<int, 
          Pair<int, int>> columnSlot, string strTitle, string strComment, 
          string strPageNumber) 
    { 
     Margin = new Thickness(PAGE_MARGIN); 
     _currentRow = currentRow; 
     _rows = rows; 
     _dataGrid = dataGrid; 
     _columns = columns; 
     _firstColumnWidth = firstColumnWidth; 
     _isFirstColumnLarger = isFirstColumnLarger; 
     _columnSlot = columnSlot; 
     _strTitle = strTitle; 
     _strComment = strComment; 
     _strPageNumber = strPageNumber; 
    } 

    #endregion Constructor 

    #region Public Static Functions 

    public static int RowsPerPage(double height) 
    { 
     //5 times Line Height deducted for: 1 for Title and Comments each; 2 for Page Number and 1 for Date 
     return (int)Math.Floor((height - (2 * PAGE_MARGIN) - HEADER_HEIGHT - (5 * LINE_HEIGHT))/LINE_HEIGHT); 
    } 

    public static int ColumnsPerPage(double width, int firstColumnWidth) 
    { 
     _columnsPerPage = (int)Math.Floor((width - (2 * PAGE_MARGIN) - firstColumnWidth)/COLUMN_WIDTH); 
     return _columnsPerPage; 
    } 

    public static int CalculateBitLength(string strData, d.Font font) 
    { 
     using (d.Graphics graphics = d.Graphics.FromImage(new d.Bitmap(1, 1))) 
     { 
      d.SizeF dtsize = graphics.MeasureString(strData, font); 

      return Convert.ToInt32(dtsize.Width); 
     } 
    } 

    #endregion Public Static Functions 

    #region Private Functions 

    private static FormattedText MakeText(string text, int fontSize) 
    { 
     return new FormattedText(text, CultureInfo.CurrentCulture, 
      FlowDirection.LeftToRight, new Typeface("Tahoma"), fontSize, Brushes.Black); 
    } 

    #endregion Private Functions 

    #region Protected Functions 

    protected override void OnRender(DrawingContext dc) 
    { 
     Point curPoint = new Point(0, 0); 
     int beginCounter = 0; 
     double intYAxisTracker = 0; 
     double TitleHeight = 0; 

     //Print Title. 
     if (_strTitle != null) 
     { 
      int intTitleLength = CalculateBitLength(_strTitle, new d.Font("Tahoma", 9, d.FontStyle.Regular)); 
      curPoint.X = ((Width - (2 * PAGE_MARGIN))/2) - (intTitleLength/2); 
      dc.DrawText(MakeText(_strTitle, 9), curPoint); 
      curPoint.Y += LINE_HEIGHT; 
      curPoint.X = 0; 
     } 

     //Print Comment. 
     if (_strTitle != null) 
     { 
      int intCommentLength = CalculateBitLength(_strComment, new d.Font("Tahoma", 9, d.FontStyle.Regular)); 
      curPoint.X = ((Width - (2 * PAGE_MARGIN))/2) - (intCommentLength/2); 
      dc.DrawText(MakeText(_strComment, 9), curPoint); 
      curPoint.Y += LINE_HEIGHT; 
      curPoint.X = 0; 
     } 

     //Print current Date. 
     int intDatLength = CalculateBitLength(String.Format("{0:MMMM dd, yyyy}", DateTime.Now), new d.Font("Tahoma", 9, d.FontStyle.Regular)); 
     curPoint.X = ((Width - (2 * PAGE_MARGIN))/2) - (intDatLength/2); 
     dc.DrawText(MakeText(String.Format("{0:MMMM dd, yyyy}", DateTime.Now), 9), curPoint); 
     curPoint.Y += LINE_HEIGHT; 
     curPoint.X = 0; 

     TitleHeight = curPoint.Y; 

     //Print First column of header row. 
     dc.DrawText(MakeText(_columns[0], 9), curPoint); 
     curPoint.X += _firstColumnWidth; 
     beginCounter = _columnSlot[1].Start; 

     //Print other columns of header row 
     for (int i = beginCounter; i <= _columnSlot[1].End; i++) 
     { 
      //Remove unwanted characters 
      _columns[i] = _columns[i].Replace(EXCAPE_CHAR, " "); 

      if (_columns[i].Length > HEADER_CHR_WIDTH) 
      { 
       //Loop through to wrap the header text 
       for (int k = 0; k < _columns[i].Length; k += HEADER_CHR_WIDTH) 
       { 
        int subsLength = k > _columns[i].Length - HEADER_CHR_WIDTH ? _columns[i].Length - k : HEADER_CHR_WIDTH; 
        dc.DrawText(MakeText(_columns[i].Substring(k, subsLength), 9), curPoint); 
        curPoint.Y += HEADER_LINE_HEIGHT; 
       } 
      } 
      else 
       dc.DrawText(MakeText(_columns[i], 9), curPoint); 

      //YAxisTracker keeps track of maximum lines used to print the headers. 
      intYAxisTracker = intYAxisTracker < curPoint.Y ? curPoint.Y : intYAxisTracker; 
      curPoint.X += COLUMN_WIDTH; 
      curPoint.Y = TitleHeight; 
     } 

     //Reset X and Y pointers 
     curPoint.X = 0; 
     curPoint.Y += intYAxisTracker - TitleHeight; 

     //Draw a solid line 
     dc.DrawRectangle(Brushes.Black, null, new Rect(curPoint, new Size(Width, 2))); 
     curPoint.Y += HEADER_HEIGHT - (2 * LINE_HEIGHT); 

     //Loop through each collection in dataGrid to print the data 
     for (int i = _currentRow; i < _currentRow + _rows; i++) 
     { 
      List<Object> icol = (List<Object>)_dataGrid.Items[i]; 

      //Print first column data 
      dc.DrawText(MakeText(icol[0].ToString(), 10), curPoint); 
      curPoint.X += _firstColumnWidth; 
      beginCounter = _columnSlot[1].Start; 

      //Loop through items in the collection; Loop only the items for currect column slot. 
      for (int j = beginCounter; j <= _columnSlot[1].End; j++) 
      { 
       dc.DrawText(MakeText(icol[j] == null ? NOT_APPLICAPLE : icol[j].ToString(), 10), curPoint); 
       curPoint.X += COLUMN_WIDTH; 
      } 
      curPoint.Y += LINE_HEIGHT; 
      curPoint.X = 0; 
     } 

     //Print Page numbers 
     curPoint.Y = Height - (2 * PAGE_MARGIN) - LINE_HEIGHT; 
     curPoint.X = Width - (2 * PAGE_MARGIN) - COLUMN_WIDTH; 

     dc.DrawText(MakeText(_strPageNumber, 9), curPoint); 

    } 

    #endregion Protected Functions 
} 
Problemi correlati