I am trying to print a grid control with multiple elements in it.
I am doing this,
PrintDialog printDialog = new PrintDialog();
if (printDialog.ShowDialog() == true)
{
printDialog.PrintVisual(gridReport, "Visit Report");
}
gridReport is my grid name.
As my grid contains a lot of child elements, only a part of it is getting printed and rest is getting chopped.
How should i solve this ?
I had the same problem a month ago. As far as i know .Net print dialog only prints one page and cuts everything beyond that page. If you want to print multi pages you have to write some logic yourself.
I created a bmp file and cut it to multiple pages, added the pages to a list and at the end printed the list of pages.
I found this article very helpful (it has a solution that cuts the bmpwhenever the height of one page is exceeded, so you will also have to implement a similar logic to cut your bmp when the width of a page is exceeded)
http://www.codeproject.com/Articles/339416/Printing-large-WPF-UserControls
i hope this will help.
Related
I'm exploring different options for .NET PDF libraries. One of my requirements is to place a box at the bottom of the first page and if any of the content reaches the box, it should overflow onto the next page.
For example:
Shown above, paragraph 7 would normally take up some of the space that's occupied by the "reserved" area. Instead, the part that would have taken up that space is shifted to the next page.
That image was achieved using Gembox.Document by adding the box as a footer element that only renders on the first page. However, in iText7, the examples I've seen for adding a footer (such as this one), places the content as a floating element that renders over the existing content and does not affect the layout/flow of the rest of the document.
I also tried adding a paragraph on the PageEnd event handler without the canvas (snippet below), but instead of adding it to the specified page, it's added to the end of the entire document.
public void HandleEvent(Event evt)
{
var docEvent = (PdfDocumentEvent)evt;
var page = docEvent.GetPage();
int pageNum = docEvent.GetDocument().GetPageNumber(page);
if (pageNum == 1)
{
doc.Add(new Paragraph("Testing a thing"));
}
}
Is the type of effect I'm looking for something that I can replicate using iText7?
I believe you can combine the concepts of https://github.com/itext/i7ns-samples/blob/develop/itext/itext.samples/itext/samples/sandbox/acroforms/AddExtraTable.cs and https://github.com/itext/i7ns-samples/blob/develop/itext/itext.samples/itext/samples/sandbox/events/TextFooter.cs to achieve what you need.
The idea is as follows:
reserve place for your box by making iText give the document's renderer less space for the first page
fill this box with a help of iText's end page events
Another option was suggested in How can I insert an element to the bottom of a specific page in iText7? : you can temporary call Document#setBottomMargin , since elements added via Document#add will not be placed on margins. Then, once the first page is layouted, you can set the initial margins again. This option, however, requires understanding of you layout flow, since the margins should be set only after the content of the first page is layouted.
One more suggestion: althouth event functionality is rather flexible and useful, it seems like using a sledgehammer to crack a nut. You need to call Canvas#ShowTextAligned, which could be done without any event handling. So ideally I would prefer to do the following:
handle page's layout area via an extension of DocumentRenderer
Calling Canvas#ShowTextAligned to fill the reserved box.
As you said, you are exploring different .NET PDF libraries. So I would advise PDFFlow library, which does exactly what you need.
If you have a footer, main document flow will take the rest of page area and will be automatically continued at the next page without overlaying footer.
DocumentBuilder.New()
.AddSection()
.AddParagraph("long text")
.ToSection()
.AddFooterToBothPages(40)
.AddParagraph("this a footer set for each page of this section")
.ToDocument()
.Build("result.pdf");
Here is a tutorial with code examples of using headers, footers, left/right repeating areas: AddingRepeatingArea tutorial.
Hope, this will help you :)
I have a C# WPF application (.NET 4.6) that needs to print a number of Page objects.
Each Page is setup in the XAML editor to be exactly 1 page of A4 in size and the content is build from a number of label, border and image components placed on the Page.
I added a method to my Page class that adds some dynamic data at run-time to the Page and then prints it using PrintVisual().
In fact: Its a loop that fills a Page object with the dynamic content and then calls PrintVisual() to print it. For each iteration, some new content is placed in the Page. (See sample code.)
// Print method of the Page object.
public void PrintIt(int totalpages)
{
PrintDialog pDialog = new PrintDialog();
// If not cancelled then print
if (pDialog.ShowDialog() == false) return; // User cancelled. Don't bother
for(int pagenum=1; i<=totalpages; i++)
{
// Omitted several dozen statements that fill/update the content of various
// label components based on the pagenumber.
this.UpdateLayout(); // Required to re-render new page properly before printing.
pDialog.PrintVisual(this, "My PrintJob");
}
}
This works well, expect for the fact that each PrintVisual() creates a separate print-job, which makes it impossible to print double-sided (and when printing to PDF each page ends up in a new file).
I need to tie all pages (PrintVisual() calls) in a single print-job. I'm fairly sure that I need to use a PrintDocument(), but I can't seem to figure out how to construct the required FlowDocument and populate it with my actual prints.
I'm quite new to WPF programming so I'm probably missing something obvious, but as far as I can't tell there isn't any simple way to do this.
Can anyone give me a push in the right direction ?
I wanted to implement itemsControl printing with page breaks like it's described in the following blog: http://blogs.u2u.be/diederik/post/2013/05/21/Printing-a-XAML-ItemsControl-from-a-Windows-8-Store-app.aspx
The problem is that in Windows 10 it works incorrectly (I added background to show items in itemsControl for debugging):
While 8.1 version works as expected:
Is there any idea what can be wrong? All it does is just adds paragraphs to richtext, measures each item content and then splits it by pages.
Windows 10 sample is here.
Windows 8.1 sample is here.
UPDATE:
More info:
I changed textblock to textbox (wanted to add background to text). It turns out that it works better, but text is cut at the end of the page. It started working on all pages except for the first page in preview (text is single line and not wrapping on the first page for some unknown reasons). It works correctly in printed document. Weird thing is that it works correctly if I close preview and click print again (even though last line on page is still cut).
I have tried your sample code: The problem is that the system default templates for your two applications are not all the same, so that there is a little difference in the display mode for the item. To fix the problem in the win10 app, you'd better define a proper layout style for the control. There are various ways to achieve this: adding a proper template in resources, or defining in code.
Please try following code in the "PreparePrintContent" function. Please notice that I adjust the layout by setting margin of the UIElement. This is a very simple approach just for your reference:
var x = itemsControl.ContainerFromItem(item) as ContentPresenter;
Paragraph p = new Paragraph();
InlineUIContainer c = new InlineUIContainer();
var o = x.ContentTemplate.LoadContent() as UIElement;
(o as FrameworkElement).DataContext = item;
(o as FrameworkElement).Margin = new Thickness(40);
I have an application that I want to display multiple PDF documents. If I define the control at design time I can load a document and display it, but when I dynamically create the control during run time I cannot get it to display. The document is being displayed in a tab.
Here is my code...
AxAcroPDF newPDF = new AxAcroPDF();
newPDF.CreateControl();
newPDF.Width = selectedTab.Width;
newPDF.Height = selectedTab.Height;
newPDF.LoadFile(filePath);
selectedTab.Controls.Add(newPDF);
newPDF.Show();
newPDF.Visible = true;
How do I get the PDF to display?
This is what worked for me...
AxAcroPDF newPDF = new AxAcroPDF();
selectedTab.Controls.Add(newPDF);
newPDF.CreateControl();
newPDF.Width = selectedTab.Width;
newPDF.Height = selectedTab.Height;
newPDF.LoadFile(filePath);
newPDF.Show();
For some reason it doesn't like the PDF control being added to the tab after the CreateControl() method is executed.
Don't use Width and Height but ActualWidth and ActualHeight from the SelectedTab. Under certain circumstances the non actuals may report zero sizes.
Otherwise hard code height and width to see if that provides an insight as to whether it is showing up, but hidden.
I Have Created a Simple form in which i have added Adobe Reader from toolbox using steps
right click in toolbox - Choose Items
choose COM Components tab and there "Adobe PDF Reader"
Now Drag&Drop the Adobe PDF Reader Control into an UserControl
I have successfully added this, opened up a pdf file also. Now it automatically provides with vertical scrollbars for scrolling through the pdf document.
What i want to achieve is instead of using the given scrollbars or mouse to scroll, i want to use a button to scroll scroll the pdf, So there will be two buttons, One for Scroll Up And the other for scroll down.
I have gone through many forums, pages, etc. Havnt found anythn that i could use.
I have Tried Simulating key presses with
SendKeys.Send("{DOWN}");
But as i press the button, the focus is lost on the adobe reader so it doesnt work
Pls help me... I have spent almost half a day searchin for a solution
given that you have provided only a simple piece of code you have tried, i am going to try offer you a generic solution - where you will need to replace the specified variables:
button names
your web app name
as for first of the focus you need to specify where it will be, something along the lines of:
var pFocus = webapplication.formname.pdf_document.focus();
// or webapplication.focus(pdf_document);
again i am just writing this as an ideal layout as i have said you will need to replace the listed variables for this to work and possibly tweak the focus code as i haven't tested that - the buttons however provided you insert your variable names will work as i have tested these:
var buttonAction = ((IJavaScriptExecutor)webapplication).ExecuteScript("window.scrollTo(0, document.body.scrollHeight - 5)");
var buttonAction_2 = ((IJavaScriptExecutor)webapplication).ExecuteScript("window.scrollTo(0, document.body.scrollHeight 0)");
//button action will scroll to x co-ordinate 0(far left), y co-ordinate( 5px from bottom)
//buttonAction_2 will return you to the very top left of page, you can edit these values to mess around and try different settings.
so altogether it should look somewhat similar to (if you are using a method for the click just insert the code under there:
var pFocus = webapplication.formname.pdf_document.focus();
if (button.click = true)
webapplication = pFocus;
var buttonAction = ((IJavaScriptExecutor)webapplication).ExecuteScript("window.scrollTo(0, document.body.scrollHeight - 5)");
pFocus.execute(buttonAction);
then for button 2
var pFocus = webapplication.formname.pdf_document.focus();
if (button_2.click = true)
webapplication = pFocus;
var buttonAction_2 = ((IJavaScriptExecutor)webapplication).ExecuteScript("window.scrollTo(0, document.body.scrollHeight 0)");
pFocus.execute(buttonAction_2);
hope this helps to some extent.