I have a richtextbox, which I plan to save in a database, which can be loaded back into the same richtextbox. This works for me, so I can save the flowdocument as DataFormats.XamlPackage, which saves images, but the problem is that the text is not searchable. With DataFormats.Xaml, I have text, of course, but no images. Images will be inserted by the end user, not images included in the application.
I tried using XamlWriter to get the text in XML and then capture the images from the document separately and paste them as binary in XML, but I can not find a way to get the images in binary format ..
Does anyone have any ideas on how to get images to binary files separately from text?
Thanks in advance!
GetImageByteArray () is the problem.
the code:
private void SaveXML() { TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); FlowDocument flowDocument = richTextBox.Document; using (StringWriter stringwriter = new StringWriter()) { using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter)) { XamlWriter.Save(flowDocument, writer ); } testRTF t = new testRTF(); t.RtfText = new byte[0]; t.RtfXML = GetImagesXML(flowDocument); t.RtfFullText = stringwriter.ToString(); //save t to database } richTextBox.Document.Blocks.Clear(); } private string GetImagesXML(FlowDocument flowDocument) { using (StringWriter stringwriter = new StringWriter()) { using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter)) { Type inlineType; InlineUIContainer uic; System.Windows.Controls.Image replacementImage; byte[] bytes; System.Text.ASCIIEncoding enc; //loop through replacing images in the flowdoc with the byte versions foreach (Block b in flowDocument.Blocks) { foreach (Inline i in ((Paragraph)b).Inlines) { inlineType = i.GetType(); if (inlineType == typeof(Run)) { //The inline is TEXT!!! } else if (inlineType == typeof(InlineUIContainer)) { //The inline has an object, likely an IMAGE!!! uic = ((InlineUIContainer)i); //if it is an image if (uic.Child.GetType() == typeof(System.Windows.Controls.Image)) { //grab the image replacementImage = (System.Windows.Controls.Image)uic.Child; //get its byte array bytes = GetImageByteArray((BitmapImage)replacementImage.Source); //write the element writer.WriteStartElement("Image"); //put the bytes into the tag enc = new System.Text.ASCIIEncoding(); writer.WriteString(enc.GetString(bytes)); //close the element writer.WriteEndElement(); } } } } } return stringwriter.ToString(); } } //This function is where the problem is, i need a way to get the byte array private byte[] GetImageByteArray(BitmapImage bi) { byte[] result = new byte[0]; using (MemoryStream ms = new MemoryStream()) { XamlWriter.Save(bi, ms); //result = new byte[ms.Length]; result = ms.ToArray(); } return result; }
UPDATE
I think that maybe I found a solution that I will post below. It uses BmpBitmapEncoder and BmpBitmapDecoder. This allows me to retrieve the binary from the bitmap, save it to the database and load it back and display it back in the FlowDocument. Initial tests were successful. For testing purposes, I will go around my database step and basically duplicate the image by creating a binary, then taking the binary and turning it into a new image and adding it to the FlowDocument. The only problem is that when I try to use the modified FlowDocument and use the XamlWriter.Save function, these are errors for the newly created image with "Cannot serialize the non-public type" System.Windows.Media.Imaging.BitmapFrameDecode. This will require further study. for the moment I will have to leave him alone.
private void SaveXML() { TextRange documentTextRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd); FlowDocument flowDocument = richTextBox.Document; string s = GetImagesXML(flowDocument);//temp LoadImagesIntoXML(s); using (StringWriter stringwriter = new StringWriter()) { using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stringwriter)) { XamlWriter.Save(flowDocument, writer );//Throws error here } } } private string GetImagesXML(FlowDocument flowDocument) { string s= ""; using (StringWriter stringwriter = new StringWriter()) { Type inlineType; InlineUIContainer uic; System.Windows.Controls.Image replacementImage; byte[] bytes; BitmapImage bi; //loop through replacing images in the flowdoc with the byte versions foreach (Block b in flowDocument.Blocks) { foreach (Inline i in ((Paragraph)b).Inlines) { inlineType = i.GetType(); if (inlineType == typeof(Run)) { //The inline is TEXT!!! } else if (inlineType == typeof(InlineUIContainer)) { //The inline has an object, likely an IMAGE!!! uic = ((InlineUIContainer)i); //if it is an image if (uic.Child.GetType() == typeof(System.Windows.Controls.Image)) { //grab the image replacementImage = (System.Windows.Controls.Image)uic.Child; bi = (BitmapImage)replacementImage.Source; //get its byte array bytes = GetImageByteArray(bi); s = Convert.ToBase64String(bytes);//temp } } } } return s; } } private byte[] GetImageByteArray(BitmapImage src) { MemoryStream stream = new MemoryStream(); BmpBitmapEncoder encoder = new BmpBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create((BitmapSource)src)); encoder.Save(stream); stream.Flush(); return stream.ToArray(); } private void LoadImagesIntoXML(string xml) { byte[] imageArr = Convert.FromBase64String(xml); System.Windows.Controls.Image img = new System.Windows.Controls.Image() MemoryStream stream = new MemoryStream(imageArr); BmpBitmapDecoder decoder = new BmpBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.Default); img.Source = decoder.Frames[0]; img.Stretch = Stretch.None; Paragraph p = new Paragraph(); p.Inlines.Add(img); richTextBox.Document.Blocks.Add(p); }
c # serialization image wpf richtextbox
JoeSharp
source share