C#FlowDocument到HTML转换

基本上,我有一个RichTextBox,我想将它的格式化内容转换为HTML,以便它可以作为电子邮件发送。

我目前使用的方法根本不提供任何格式:

string message = new TextRange(messageTextBox.Document.ContentStart, messageTextBox.Document.ContentEnd).Text; 

所以我四处搜索并发现了这一点 ,然而,它已经超过5年了,在评论中,MSFT用户评论说不再支持 – "This sample has been removed from our sample set and is no longer supported" ,并且它生成的HTML格式比现代HTML格式或XHTML格式要旧,这样做会更好。

任何人都可以告诉我如何将RichTextBox的格式化内容转换为HTML?

(因此,当发送电子邮件时,收件人会看到带有格式的电子邮件)

一般技术是使用XamlWriterFlowDocument内容转换为XML流,然后使用XSLT转换将XML转换为HTML。 这不是一个答案,但那是因为任何给定的FlowDocument都有大量可能的HTML表示。

例如,此转换将每个顶级Section转换为div ,每个Paragraph转换为p ,每个Run为一个span其类别告诉您它是斜体,粗体或下划线,还是任何组合以上。 它对我写的目的很有用,但称之为有损转换是一种轻描淡写:

     

i b u

这是我编写的用于转换的值转换器 – 请注意,为了使用值转换器,您还必须破解并实现将内容公开为依赖项属性的RichTextBox版本。 真的,整个项目都很痛苦。

 public class FlowDocumentToHtmlConverter : IValueConverter { private static XslCompiledTransform ToHtmlTransform; private static XslCompiledTransform ToXamlTransform; public FlowDocumentToHtmlConverter() { if (ToHtmlTransform == null) { ToHtmlTransform = LoadTransformResource("Converters/FlowDocumentToXhtml.xslt"); } if (ToXamlTransform == null) { ToXamlTransform = LoadTransformResource("Converters/XhtmlToFlowDocument.xslt"); } } private static XslCompiledTransform LoadTransformResource(string path) { Uri uri = new Uri(path, UriKind.Relative); XmlReader xr = XmlReader.Create(Application.GetResourceStream(uri).Stream); XslCompiledTransform xslt = new XslCompiledTransform(); xslt.Load(xr); return xslt; } #region IValueConverter Members public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (!(value is FlowDocument)) { return null; } if (targetType == typeof(FlowDocument)) { return value; } if (targetType != typeof(string)) { throw new InvalidOperationException( "FlowDocumentToHtmlConverter can only convert back from a FlowDocument to a string."); } FlowDocument d = (FlowDocument)value; using (MemoryStream ms = new MemoryStream()) { // write XAML out to a MemoryStream TextRange tr = new TextRange( d.ContentStart, d.ContentEnd); tr.Save(ms, DataFormats.Xaml); ms.Seek(0, SeekOrigin.Begin); // transform the contents of the MemoryStream to HTML StringBuilder sb = new StringBuilder(); using (StringWriter sw = new StringWriter(sb)) { XmlWriterSettings xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; XmlReader xr = XmlReader.Create(ms); XmlWriter xw = XmlWriter.Create(sw, xws); ToHtmlTransform.Transform(xr, xw); } return sb.ToString(); } } public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null) { return new FlowDocument(); } if (value is FlowDocument) { return value; } if (targetType != typeof(FlowDocument)) { throw new InvalidOperationException( "FlowDocumentToHtmlConverter can only convert to a FlowDocument."); } if (!(value is string)) { throw new InvalidOperationException( "FlowDocumentToHtmlConverter can only convert from a string or FlowDocument."); } string s = (string)value; FlowDocument d; using (MemoryStream ms = new MemoryStream()) using (StringReader sr = new StringReader(s)) { XmlWriterSettings xws = new XmlWriterSettings(); xws.OmitXmlDeclaration = true; using (XmlReader xr = XmlReader.Create(sr)) using (XmlWriter xw = XmlWriter.Create(ms, xws)) { ToXamlTransform.Transform(xr, xw); } ms.Seek(0, SeekOrigin.Begin); d = XamlReader.Load(ms) as FlowDocument; } XamlWriter.Save(d, Console.Out); return d; } #endregion }