WPF RichTexBox printing is creating unexpected line breaks - c#

In RichTextBox of my WPF app, following print method is creating unexpected line breaks. Question: What I may be missing here, and how can we fix the issue?
For example, when I enter the following text in the RichTextBox (RTB), the RTB looks like as shown in image 1. But when I call the following two print methods the first one does not create the unexpected line breaks, but the second method does create unexpected line breaks:
MainWindow.xaml
<StackPanel>
<RichTextBox Name="richTB" />
<Button Click="PrintCommand1">Print RTB Content</Button>
<Button Click="PrintCommand2">Print RTB Content</Button>
</StackPanel>
Method 1
private void PrintCommand1(Object sender, RoutedEventArgs args)
{
PrintDialog pd = new PrintDialog();
if ((pd.ShowDialog() == true))
{
pd.PrintVisual(richTB as Visual, "printing as visual");
}
}
Method 2
private void PrintCommand2(Object sender, RoutedEventArgs args)
{
PrintDialog pd = new PrintDialog();
if ((pd.ShowDialog() == true))
{
pd.PrintDocument((((IDocumentPaginatorSource)richTB.Document).DocumentPaginator), "printing as paginator");
}
}
The text I enter [Note: There is only one line break]
This is a test for testing purpose only. Another test: x6. Let us do some background and foreground colors.
This is a new line with formatting, as well.
Snapshot of the RichTexBox with above text
Snapshot of "Print to PDF" (on Windows 10) using Method 1 [Printed correctly with one real line break]
Snapshot of "Print to PDF" (on Windows 10) using Method 2 [Printed incorrectly with unexpected line breaks]

Because of the DocumentPaginator class takes context of the FlowDocument and split in into multiple pages to get desired result some of FlowDocument parameters should be configured before printing:
private void PrintCommand2(Object sender, RoutedEventArgs args)
{
var pd = new PrintDialog();
if (pd.ShowDialog() == true)
{
FlowDocument doc = richTB.Document;
// Save all settings that will be configured for printing.
double pageHeight = doc.PageHeight;
double pageWidth = doc.PageWidth;
double columnGap = doc.ColumnGap;
double columnWidth = doc.ColumnWidth;
// Make the FlowDocument page match the printed page.
doc.PageHeight = pd.PrintableAreaHeight;
doc.PageWidth = pd.PrintableAreaWidth;
doc.ColumnGap = 5;
// Set the minimum desired width of the column in the System.Windows.Documents.FlowDocument.
doc.ColumnWidth = doc.PageWidth - doc.ColumnGap - doc.PagePadding.Left - doc.PagePadding.Right;
pd.PrintDocument(((IDocumentPaginatorSource)doc).DocumentPaginator, "A Flow Document");
// Reapply the old settings.
doc.PageHeight = pageHeight;
doc.PageWidth = pageWidth;
doc.ColumnGap = columnGap;
doc.ColumnWidth = columnWidth;
}
}
With respect to Matthew MacDonald this way of the flow document content printing and more advanced techniques described in his book Pro WPF 4.5 in C# Windows Presentation Foundation in .NET 4.5 (Chapter 29).

Related

Windows Presentation Foundation Print Label (Zebra Printer)

I am trying to print text to display vertical in Windows Forms Host. The label is printing with report viewer in WPF. Here is my code:
// boolean is based on true or false, when printing labels
private bool _isReportViewerLoaded;
// method to display data in .rdlc
private void ReportViewer_Load(object sender, EventArgs e)
{
// if equal false run this code isReportViewerLoaded
if (!_isReportViewerLoaded)
{
// get the lot based on the parameter Id
Lot lot = BottleLotRespository.GetLotById(this.Parameter);
// settings the page settings
PageSettings pg = new PageSettings();
pg.PrinterSettings
.DefaultPageSettings
.Margins = new Margins(0, 0, 0, 0);
pg.Landscape = false;
PaperSize size = new PaperSize("110.0 x 74.0", 433, 100);
BottleLotDataSet bottleLotDataSet = new BottleLotDataSet();
DataTable reportDataTable = bottleLotDataSet.LotDataTable;
DataRow lotRow = reportDataTable.NewRow();
lotRow["Id"] = lot.Id;
lotRow["Number"] = lot.Number.ToString();
reportDataTable.Rows
.Add(lotRow);
bottleLotDataSet.BeginInit();
this._reportViewer.SetPageSettings(pg);
this.reportDataSource.Name = "DataSet1";
this.reportDataSource.Value = reportDataTable;
this._reportViewer
.LocalReport
.DataSources
.Add(this.reportDataSource);
this._reportViewer
.LocalReport
.ReportEmbeddedResource = "BottleLotWPF.View.Report1.rdlc";
bottleLotDataSet.EndInit();
_reportViewer.RefreshReport();
_isReportViewerLoaded = true;
}
}
My problem is that the Report1.rdlc is not allowing me to rotate the text and there is no settings for it. Is there away of adding a setting to it to rotate the text?
In RDLC we have the option to print vertically it seems.
please take look at the existing thread here and see if it helps.
display-text-vertically-start-

Returning more than one variable in a C# 'get' statement

In my Excel Add-In, I have created two task panes - with each ones visibility being from two different values, requiring both to be in a return statement, however it will only allow me to return one of the values. These are 'taskPaneValue' and 'taskPaneValue2'.
How do I go about having both returned in the 'get' statement.
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
taskPaneControl2 = new FileChooser();
taskPaneValue2 = this.CustomTaskPanes.Add(taskPaneControl2, "File Chooser");
taskPaneValue2.VisibleChanged += new EventHandler(taskPaneValue_VisibleChanged);
taskPaneValue2.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionFloating;
taskPaneValue2.Height = 600;
taskPaneValue2.Width = 600;
taskPaneValue2.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
//These three lines of code start by initiating the TaskPane control (namely aLaCarteMenu())
//It then goes on to set the name of the menu "A La Carte Menu" which appears on the top left of the window before stating its visibility.
taskPaneControl1 = new aLaCarteMenu();
taskPaneValue = this.CustomTaskPanes.Add(taskPaneControl1, "A La Carte Menu");
taskPaneValue.VisibleChanged +=
//The following four lines of code are used to display the visiblity of the AddIn.
//The docking position is set to float, with a resolution of 980x1920. This is designed for a 1080p screen, however still working on changing it to fit screens dynamically.
new EventHandler(taskPaneValue_VisibleChanged);
taskPaneValue.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionFloating;
taskPaneValue.Height = 980;
taskPaneValue.Width = 1920;
//This line of code sets the position to be restricted to what has been set above (floating). This allows for the pane to be moved around the screen, as well as to be resized.
//This stops the pane from locking on to the right, left, top or bottom sections of the Excel Window.
taskPaneValue.DockPositionRestrict = Office.MsoCTPDockPositionRestrict.msoCTPDockPositionRestrictNoChange;
}
private void taskPaneValue_VisibleChanged(object sender, System.EventArgs e)
{
Globals.Ribbons.ManageTaskPaneRibbon.toggleButton1.Checked = taskPaneValue.Visible;
Globals.Ribbons.ManageTaskPaneRibbon.toggleButton2.Checked = taskPaneValue2.Visible;
}
public Microsoft.Office.Tools.CustomTaskPane TaskPane
{
get
{
return taskPaneValue2;
}
}
The final 'get' statement is the one I wish to return both variables.
Use a Tuple or create a class that has all the properties you are looking for and make that the return type of the function.
You can also create a method with out parameter modifier, if it'still possible to you. Please, check the following link: https://msdn.microsoft.com/en-us/library/ee332485.aspx

WPF Printing from a TextBox

I am having trouble printing from a TextBox in WPF
My Textbox will only contain a number between 1 and 999
I wanted to print font size 72 and the text enclosed within a 4" box (so they can cut around the edges)
private void InvokePrint(String contentToPrint)
{
// Create the print dialog object and set options
PrintDialog pDialog = new PrintDialog();
pDialog.PageRangeSelection = PageRangeSelection.AllPages;
pDialog.UserPageRangeEnabled = true;
// Display the dialog. This returns true if the user presses the Print button.
Nullable<Boolean> print = pDialog.ShowDialog();
if (print == true)
{
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
pDialog.PrintDocument(fixedDocSeq.DocumentPaginator, "Printing Label");
}
}
I got the code from Microsoft's site but they are using an XPS printer. I want to use the default selected printer (usually an HP).
Any help would greatly be appreciated

WPF Printing prints on 1 system and not on other

I have a WPF application in which I have 3 forms of prints. In 2 ways, I use directly a window's visual and use PrintVisual(myPanel, "Title") to print it. And in 3rd, I got to print multiple pages so I am using FlowDocument, StackPanel and finally IDocumentPaginatorSource and call PrintDocument to print.
All the code is working perfectly on my system. I can perform Print on OneNote and XPS and it works as expected. But the same app, when I try to run on other system it shows blank page for all 3 prints. PrintVisual is supported on .NET 3.0, 3.5, 4.0, 4.5, so I can't find a reason for it not to work.
I will also share my some code, for better clarity :
// 1 PRINT
public void PrintRegister()
{
PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() == true)
pd.PrintVisual(this, "Register Window");
return;
}
// 2 PRINT
public static void PrintAttendanceOf(System.Data.DataRow r1) {
PrintLayoutWindowPORT plw = PrintUtility.CreatePrintLayoutWindowPORTObject(r1); // PORTRAIT
Canvas p1 = PrintUtility.CloneCanvas(plw._PrintCanvas, 5);
Grid myPanel = new Grid();
myPanel.Margin = new Thickness(10);
myPanel.Children.Add(p1);
PrintDialog pd = new PrintDialog();
pd.PageRangeSelection = PageRangeSelection.AllPages;
PrintQueue pq = pd.PrintQueue;
pq.DefaultPrintTicket.PageOrientation = PageOrientation.Portrait;
pd.PrintTicket = pq.DefaultPrintTicket;
double pageWidth = pd.PrintableAreaWidth;
double pageHeight = pd.PrintableAreaHeight;
myPanel.Measure(new Size(pageWidth, pageHeight));
//myPanel.Arrange(new Rect(new Point(1, 1), myPanel.DesiredSize));
myPanel.UpdateLayout();
if (pd.ShowDialog().GetValueOrDefault(false))
{
pd.PrintVisual(myPanel, "Attendance Chart");
}
pd = null;
plw.Close();
plw = null;
myPanel = null;
p1 = null;
return;
}
Code for the 3rd Print i.e. Multiple Pages is quiet long, hence have not added it now here. If required, can post it.
Can anyone help me know the reason for printing blank page and no contents on other system. I feel some sort of compatibility or system or resource may be required or what else?
Any help is highly appreciated.
Thanks

Printing in WPF similar to Winforms

Below is the process I worked in Windows forms for printing.
I used PrintDocument class. It contains PrintPage event and I used that to draw the graphics of what I need to print and obtained the result successfully as I expected.
Below is the code:
public PrintDocument Printing
{
m_printDocument = new PrintDocument();
m_printDocument.PrintPage += new PrintPageEventHandler(OnPrintPage);
}
The code for OnPrintPage as follows:
protected virtual void OnPrintPage(object sender, PrintPageEventArgs e)
{
//Image img = I have the things to be printing in the form of image.
e.Graphics.DrawImage(img, new Point(0,0));
}
In WPF:
I am working with Fixed document and by using the below code I can print
PrintDialog print = new PrintDialog();
print.PrintDocument(FixedDocument.DocumentPaginator, "Print") //Where Fixed document contains the data to be printed.
This results is insufficient memory to continue the execution of the program.
But I got Fixed document without any problem.
Any solutions ...?
I hope the similar thing as like Windows form would be there in WPF too...
I used to get this when my pages contained lots of visual elements (drawings/images/ complex diagrams). Instead of printing the complete document at once (which can lead to out of memory)
print.PrintDocument(FixedDocument.DocumentPaginator, "Print")
I printed one of its page.
PrintQueue selectedPrntQueue = printDialog.PrintQueue;
XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(selectedPrntQueue);
SerializerWriterCollator collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
var paginator = FixedDocument.DocumentPaginator;
FixedPage fixedPage = paginator.GetFixedPage(printedPageCount)
ContainerVisual newPage = new ContainerVisual();
Size sz = new Size(pageSize.Height.Value, pageSize.Width.Value);
fixedPage.Measure(sz);
fixedPage.Arrange(new Rect(new Point(), sz));
fixedPage.UpdateLayout();
newPage.Children.Add(fixedPage);
collator.Write(newPage);
I had to do GC after printing few pages (my magic number was 10).
You may need to tweak the this up to your requirement.

Categories

Resources