Wpf how to print ListBox - wpf

I would like to know what is the easiest way to print ListBox's values. I have tried to use FlowDocumentReader but with no success.

If you are trying to print a visual element,you can use
PrintDialog printDlg = new PrintDialog();
printDlg.PrintVisual(ListBox1, "Listbox Printing.");
It can be used to print any visual object(any control, container, Window or user control)
If you are looking to print the items only then you can use the FlowDocument
FlowDocument fd = new FlowDocument();
foreach (object item in items)
{
fd.Blocks.Add(new Paragraph(new Run(item.ToString())));
}
fd.Print();
or
PrintDialog pd = new PrintDialog();
pd.PrintDocument(fd);

Related

trouble displaying flowdocument

I'm having some problems displaying the contents of a flowdocument in a flowdocumentscrollviewer. I create a generic list that holds a class which contains an int, string and a flowdocument.
In a WPF listbox, I am trying to display the flowdocument in the scrollviewer alongside a button. I use the following function called from the WPF window constructor to populate the listbox
private void populateListBox()
{
foreach(Element el in _notesList)
{
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
Button b = new Button();
b.Content = el._theID;
sp.Children.Add(b);
FlowDocumentScrollViewer fdsv = new FlowDocumentScrollViewer();
fdsv.MinWidth = 400;
fdsv.Document = el._theDoc;
sp.Children.Add(fdsv);
ListBoxItem lbi = new ListBoxItem();
lbi.Content = sp;
noteList.Items.Add(lbi);
}
}
But the code does not work. There are no errors but the scrollviewers are just blank in the listbox. I also tried storing the classes in an ObservableList and binding to the Document property but that didn't work either.
Any ideas what is happening?
Nevermind. I figured it out.
Further down in the program execution I was copying the flowdocument blocks to a merged document in a foreach statement. This doesn't work even if you use Blocks.ToList(). I eventually found a way to copy the document contents to another document here.

RichTextBox - how to pass markup codes

I'm using the RichTextBox to display some readonly text that I have to markup on the fly.
How can I pass markup codes in text to have it rendered by the RichTextBox control?
For example, I'd like to pass this is \cf6 sample \cf1 text to the richtextbox for it to render.
Right now, I build a FlowDocument and add the text value to a run object, but the text gets rendered literally.
RichTextBox fieldLabel = new RichTextBox();
FlowDocument flowDoc = new FlowDocument();
Paragraph myPara = new Paragraph();
Run myRun = new Run(content);
myPara.Inlines.Add(myRun);
flowDoc.Blocks.Add(myPara);
fieldLabel.Document = flowDoc;
I want to see the value in red, but I see the markup instead.
Thanks in advance for any input.
You cant assign RTF text just like that. You need to get that text into a stream and then pass that stream to the RichTextBox.Selection.Load() method. e.g.
MemoryStream stream = new MemoryStream(UTF8Encoding.Default.GetBytes(yourRTFText));
fieldLabel.Selection.Load(stream, DataFormats.Rtf);
You have to apply to the paragraph
// Create a FlowDocument to contain content for the RichTextBox.
FlowDocument myFlowDoc = new FlowDocument();
// Add paragraphs to the FlowDocument.
myFlowDoc.Background = Brushes.LightBlue;
myFlowDoc.Foreground = Brushes.DarkRed;
myFlowDoc.Typography.Capitals = FontCapitals.SmallCaps;
myFlowDoc.Blocks.Add(new Paragraph(new Run("Paragraph 1")));
Paragraph p = new Paragraph(new Run("Paragraph 2"));
p.Foreground = Brushes.Black;
myFlowDoc.Blocks.Add(p);
myFlowDoc.Blocks.Add(new Paragraph(new Run("Paragraph 3")));
RichTextBox myRichTextBox = new RichTextBox();
// Add initial content to the RichTextBox.
myRichTextBox.Document = myFlowDoc;

C# String in RichTextBox Wpf

I have the following question:
I have a class Question which has a property BodyString of the type String.
How do I put this String in a Wpf-RichTextBox?
yourRichTextBox.AppendText(BodyString);
From this answer:
The WPF RichTextBox has a Document property for setting the content a la MSDN:
// Create a FlowDocument to contain content for the RichTextBox.
FlowDocument myFlowDoc = new FlowDocument();
// Add paragraphs to the FlowDocument.
myFlowDoc.Blocks.Add(new Paragraph(new Run("Paragraph 1")));
myFlowDoc.Blocks.Add(new Paragraph(new Run("Paragraph 2")));
myFlowDoc.Blocks.Add(new Paragraph(new Run("Paragraph 3")));
RichTextBox myRichTextBox = new RichTextBox();
// Add initial content to the RichTextBox.
myRichTextBox.Document = myFlowDoc;
You can just use the AppendText method though if that's all you're after.
Hope that helps.

Reset control's parent in WPF

If I add a control to a canvas and than removes it, I can not re-add it to the same canvas (or to any other canvas for that matter) any idea how can I reset the parent?
mainCanvas.Children.Add(item);
mainCanvas.Children.Remove(item);
mainCanvas.Children.Add(item); // Will throw an exception that parent was already set.
Thanks,
Eden.
Are you sure there is not something else going on in your code?
I just tried a new wpf application with :
public MainWindow()
{
InitializeComponent();
Button b = new Button();
b.Content = "hello";
Canvas c = new Canvas();
c.Children.Add(b);
c.Children.Remove(b);
c.Children.Add(b);
Content = c;
}
and it worked fine. Have you got any collection changed delegates?

Printing a Collection in WPF

Is there any way to print in memory collection or variable size in WPF?
I am using the following code in which I print the ListView control. But when the content is larger than the vertical scroll bar takes over and cuts the content.
PrintDialog printDialog = new PrintDialog();
printDialog.ShowDialog();
printDialog.PrintVisual(lvDocumentSummary, "testing printing!");
To print multiple pages you just need to use a class that implements DocumentPaginator FixedDocument is one of the more complex implementations, FlowDocument is a simpler one.
FlowDocument fd = new FlowDocument();
foreach(object item in items)
{
fd.Blocks.Add(new Paragraph(new Run(item.ToString())));
}
fd.Print();
or
PrintDialog pd = new PrintDialog();
pd.PrintDocument(fd);
FixedDocument supports DataBinding (other than FlowDocument) like any other xaml document. just host the listview in a fixeddocument and display it in a DocumentViewer (which has built-in print support).
however, if your list is too long for one page, FixedDocument does not automatically generate a new page (like flowdocument does). therefore you have to create a new page maually with code, as this cannot be done in pure xaml.
If you want nice printing from WPF you need to build a FixedDocument and print that, unfortunately it can be very complex depending on what you are trying to print.
There's some example code that creates a FixedDocument here: http://www.ericsink.com/wpf3d/B_Printing.html
Here's a 2019 answer. Some of the old answers don't work anymore, eg. FlowDocumentReader doesn't have a Print method.
private void Button_Click(object sender, RoutedEventArgs e)
{
FlowDocument fd = new FlowDocument();
foreach (var item in COLLECTION) //<- put your collection here
{
fd.Blocks.Add(new Paragraph(new Run(item.ToString())));
}
PrintDialog pd = new PrintDialog();
if (pd.ShowDialog() != true) return;
fd.PageHeight = pd.PrintableAreaHeight;
fd.PageWidth = pd.PrintableAreaWidth;
IDocumentPaginatorSource idocument = fd as IDocumentPaginatorSource;
pd.PrintDocument(idocument.DocumentPaginator, "Printing Flow Document...");
}
}
Interesting, Is the ListView virtualized? If it is, the object are not drawn, that is a possibility. Take a look at the Printing example from Petzold.
Here is my solution to this problem. It is kinda shaky but works for my scenario.
I read my collection and transform it into a string. The whole collection now resides in a StringBuilder object. Next, I saw the text/string into a file on the client's machine and then run the notepad process with /p to print the contents of the file.
It works and it prints the contents successfully.
Finally, there is a timer which is called after 5 seconds and which removes the file. Basically within 5 seconds the request is already sent to the printer queue. But a better solution will be to make sure that the print job has been processed this way you will be 100% sure that the job has been performed.

Resources