Import XAML into WPF RichTextBox - c#

I have a WPF RichTextBox that is dynamically built in a WPF web service. This web service accepts a xaml string that is extracted from the contents of a third-party silverlight RichTextBox control.
<Paragraph TextAlignment=\"Left\"><Run FontFamily=\"Comic Sans MS\" FontSize=\"16\" Foreground=\"#FF0000FF\" FontWeight=\"Bold\" >This text is blue and bold.</Run></Paragraph>
How do I insert this xaml into my WPF RichTextBox? I somewhat understand the concepts of the FlowDocument and Paragraph and Run so I can populate the WPF RichTextBox with text using the code below,
FlowDocument flowDocument = new FlowDocument();
Paragraph par = new Paragraph();
par.FontSize = 16;
par.FontWeight = FontWeights.Bold;
par.Inlines.Add(new Run("Paragraph text"));
flowDocument.Blocks.Add(par);
rtb.Document = flowDocument;
But what I really don't want to have to parse through the xaml myself to build a paragraph as it can get very complicated. Is there a way to just have the control know how to parse the passed in xaml?

You can use XamlReader to read your Xaml string and convert it to a control:
string templateString = "<Paragraph xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" TextAlignment=\"Left\"><Run FontFamily=\"Comic Sans MS\" FontSize=\"16\" Foreground=\"#FF0000FF\" FontWeight=\"Bold\" >This text is blue and bold.</Run></Paragraph>";
StringReader stringReader = new StringReader(templateString);
XmlReader xmlReader = XmlReader.Create(stringReader);
Paragraph template = (Paragraph)XamlReader.Load(xmlReader);
Just make sure you include the following tag in your template:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
HTH

Related

richtext to byte[] and byte[] to richtext in WPF [duplicate]

How do I get the text in RTF of a RichTextBox? I'm trying to get like this, but the property does not exist.
RichTextBox rtb = new RichTextBox();
string s = rtb.Rtf;
To get the actual XAML created by the user inside of the RichTextBox:
TextRange tr = new TextRange(myRichTextBox.Document.ContentStart,
myRichTextBox.Document.ContentEnd);
MemoryStream ms = new MemoryStream();
tr.Save(ms, DataFormats.Xaml);
string xamlText = ASCIIEncoding.Default.GetString(ms.ToArray());
EDIT: I don't have code in front of me to test, but an instance of the TextRange type has a Save (to stream) method that takes a DataFormats parameter, which can be DataFormats.Rtf
There are 2 RichTextBox classes, one from the winforms framework and one from the WPF framework:
System.Windows.Controls.RichTextBox wpfBox;
System.Windows.Forms.RichTextBox winformsBox;
Only the Winforms RichTextBox has an Rtf property, the other has a Document property which contains a FlowDocument.

Bold Part of TextBox/RichTextBox in C# Code

There are many examples of how to format the text in a TextBox via xaml code, but I am trying to figure out how to change the code in my .cs file.
//TextBox tb initialized in .xaml code
tb.Text = "<bold>Bold</bold> and normal and <italic>Italic</italic>";
is along the lines of what I am looking for. Is this possible?
The end result would look like:
Bold and normal and Italic
You can do that for RichTextBox by adding Inlines like this:
Paragraph paragraph = new Paragraph();
paragraph.Inlines.Add(new Bold(new Run("Bold")));
paragraph.Inlines.Add(new Run(" and normal"));
paragraph.Inlines.Add(new Italic(new Run(" and Italic")));
richTextBox.Document = new FlowDocument(paragraph);
If you decide to use TextBlock you can use the following:
this.myTextBlock.Inlines.Add(new Bold(new Run("Bold")));
this.myTextBlock.Inlines.Add(" and normal and ");
this.myTextBlock.Inlines.Add(new Italic(new Run("italic")));
Otherwise, if you have to use TextBox you can only apply style to whole text, for example using myTextBox.FontWeight.

Problem with Printing Content Of RichTextBox with Adorner Layers

I am trying to print the content of RichTextBox including the Adorner Layers inside.
I am using this code to print
double w = Editor.ExtentWidth; // Editor is the RichTextBox
double h = Editor.ExtentHeight;
LocalPrintServer ps = new LocalPrintServer();
PrintQueue pq = ps.DefaultPrintQueue;
XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
PrintTicket pt = pq.UserPrintTicket;
if (xpsdw != null)
{
pt.PageOrientation = PageOrientation.Portrait;
PageMediaSize pageMediaSize = new PageMediaSize(w, h);
pt.PageMediaSize = pageMediaSize;
xpsdw.Write(Editor);
}
The problem I'm facing is that this code only prints the content that is visible on the screen, not the whole content of the Editor.
EDIT
The pictures are adorner layers, If I print using the method above, it only prints the visible part on the screen not the whole document.
Edit
I'm trying to print each page separately but I cant force Editor.InvalidateVisual(); after doing a Editor.PageDown(); Is there a way I can do that in my method ?
When controls draw on the adorner layer, they search up the tree until they find an adorner layer. Often times this is a the window level. In some cases, you'll want an adorner layer closer to the control, or directly around the control. In this case, wrap the control with an <AdornerDecorator><RichTextBox /></AdornerDecorator>
In your case, you'd probably want to pass a parent element of adorner decorator, or the decorator itself to the print logic. This way the print logic would include the adorner layer as part of the visual. Maybe something like this:
<Grid Name="EditorWrapper">
<AdornerDecorator>
<RichTextBox />
</AdornerDecorator>
</Grid>
Then, pass "EditorWrapper" to the print logic.
EDIT
If you just want to print the contents of the RichTextBox, then you might be best to use the built-in pagination capabilities of the FlowDocument. FlowDocument implements IDocumentPaginatorSource, which will return a paginator that can print the document. Pass that paginator to the XpsDocumentWriter and it should dump the content properly.
var doc = Editor.Document;
var src = doc as IDocumentPaginatorSource;
var pag = src.DocumentPaginator;
xpsdw.Write(pag);
I found this code here:
// Serialize RichTextBox content into a stream in Xaml or XamlPackage format. (Note: XamlPackage format isn't supported in partial trust.)
TextRange sourceDocument = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
MemoryStream stream = new MemoryStream();
sourceDocument.Save(stream, DataFormats.Xaml);
// Clone the source document's content into a new FlowDocument.
FlowDocument flowDocumentCopy = new FlowDocument();
TextRange copyDocumentRange = new TextRange(flowDocumentCopy.ContentStart, flowDocumentCopy.ContentEnd);
copyDocumentRange.Load(stream, DataFormats.Xaml);
// Create a XpsDocumentWriter object, open a Windows common print dialog.
// This methods returns a ref parameter that represents information about the dimensions of the printer media.
PrintDocumentImageableArea ia = null;
XpsDocumentWriter docWriter = PrintQueue.CreateXpsDocumentWriter(ref ia);
if (docWriter != null && ia != null)
{
DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocumentCopy).DocumentPaginator;
// Change the PageSize and PagePadding for the document to match the CanvasSize for the printer device.
paginator.PageSize = new Size(ia.MediaSizeWidth, ia.MediaSizeHeight);
Thickness pagePadding = flowDocumentCopy.PagePadding;
flowDocumentCopy.PagePadding = new Thickness(
Math.Max(ia.OriginWidth, pagePadding.Left),
Math.Max(ia.OriginHeight, pagePadding.Top),
Math.Max(ia.MediaSizeWidth - (ia.OriginWidth + ia.ExtentWidth), pagePadding.Right),
Math.Max(ia.MediaSizeHeight - (ia.OriginHeight + ia.ExtentHeight), pagePadding.Bottom));
flowDocumentCopy.ColumnWidth = double.PositiveInfinity;
// Send DocumentPaginator to the printer.
docWriter.Write(paginator);
}
Adorner layers are are drawing oriented. So one option left is to convert the entire RichTextBox into a drawing and print that as an Image in XPS.
Although this poses multiple issues...
It will print the external and internal contents that occupy or occupied by the richtextbox i.e. editor toolbar (if it is part of the control template of the rich text box), internal scroll bars etc.
If there are scrollbars then the content out of the scrollbars are not going to be printed as the image will be the exact "snapshot" of the textbox (with remaining text clipped by srollbars).
Will you be happy with that?
I didn't find any way that works 100% for this problem, so I'm trying to transform all my adorner layers to actual images. I'll update the question once I get a 100% working solution.

How can I create a hyperlink in C# code instead of XAML

How can I create a hyper link in C# code that looks like the following in XAML?:
<TextBlock>
<Hyperlink Click="HyperLinkClick">New Hyperlink</Hyperlink>
</TextBlock>
MSDN usually has very good examples. Combining the examples for TextBlock and Hyperlink:
TextBlock textBlock1 = new TextBlock();
Run run3 = new Run("Link Text.");
Hyperlink hyperl = new Hyperlink(run3);
hyperl.NavigateUri = new Uri("http://search.msn.com");
textBlock1.Inlines.Add(hyperl);

Get path geometry from FlowDocument object

Can someone tell me how to get path geometry from a WPF FlowDocument object? Please note that I do not want to use FormattedText. Thanks.
A FlowDocument can be viewed in any number of ways, but a Path is a fixed shape. I think maybe you really want some simplified, visual-only form of a FlowDocument's contents.
In that case you might try converting the FlowDocument to an XPS FixedDocument - the FixedPages have Canvases containing a bunch of Paths and Glyphs.
Get the Text property of a TextRange object initialized over the entire FlowDocument:
FlowDocument myFlowDocument = new FlowDocument(); //get your FlowDocument
//put in some (or it already has) text
string inText = "Hello, WPF World!";
TextRange tr = new TextRange(FlowDocument.ContentStart, FlowDocument.ContentEnd);
tr.Text = inText;
//get the current text out of the FlowDocument
TextRange trPrime = new TextRange(FlowDocument.ContentStart, FlowDocument.ContentEnd);
string outText = trPrime.Text;
//now outText == "Hello, WPF World!";
//to get formatting, looks like you would use myFlowDocument.TextEffects
Can you use
ChildVisual = VisualTreeHelper.GetChild(Visual yourVisual)
Dunno if you can take a Visual and turn it into a path geometry..

Categories

Resources