【发布时间】:2016-11-24 16:38:13
【问题描述】:
我正在使用 Windows phone 8.1 UWP。我需要在 windows phone 组件中绑定一个可能具有图像和视频标签的字符串。我使用富文本框控件绑定字符串
下面是带有 img 标签的示例字符串
கொழும்பு:<br /><br />
தஞ்சம் அடைந்துள்ளனர்.<br /><br /><br /><img alt="" src="/uploads/0F05D1DA-EFC1-4242-B313-C56CD0857B6E_L_styvpf.gif" height="350" width="615" /><br /><br />
இந்நிலையில், இலங்கையின் மத்தியப் பகுதியில்
下面是我绑定字符串的 XAML 代码
xmlns:local="using:NameSpace"
<RichTextBlock local:Properties.Html="{Binding ArticleDetail}" />
我在我的项目中安装了来自 Nuget 的 RichTextBlock.Html2Xaml。我还在我的项目中添加了 RichTextBlockHtml2Xaml.xslt 和 RichTextBlockProperties.cs 文件项目
RichTextBlockHtml2Xaml.xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<!-- The html root element must be div, it translates to a xaml richtextblock.-->
<xsl:template match="/div" priority="9">
<RichTextBlock>
<RichTextBlock.Resources>
<Style x:Key="Bullet" TargetType="Ellipse">
<Setter Property="Fill" Value="Black" />
<Setter Property="Width" Value="6" />
<Setter Property="Height" Value="6" />
<Setter Property="Margin" Value="-30,0,0,1" />
</Style>
<Style x:Key="Link" TargetType="HyperlinkButton">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="FontSize" Value="11" />
<Setter Property="Margin" Value="-15,-11" />
</Style>
</RichTextBlock.Resources>
<xsl:if test="normalize-space(text()) != ''">
<Paragraph><xsl:value-of select="normalize-space(text())" /></Paragraph>
</xsl:if>
<xsl:apply-templates select="/div/*" />
</RichTextBlock>
</xsl:template>
<xsl:template match="div" priority="0">
<Span><xsl:apply-templates /></Span>
</xsl:template>
<!-- XAML Paragraphs cannot contain paragraphs, so we convert top-level html paragraphs to xaml paragraphs and convert nested html paragraphs to xaml spans with linebreaks -->
<xsl:template match="/div/P | /div/p" priority="9">
<Paragraph><xsl:apply-templates /></Paragraph>
</xsl:template>
<xsl:template match="P | p" priority="0">
<Span><LineBreak /><xsl:apply-templates /><LineBreak /></Span>
</xsl:template>
<!-- The RichTextBlock XAML element can contain only paragraph child elements, so any unknown html child elements of the root element will become XAML paragraphs -->
<xsl:template match="/div/*">
<Paragraph><xsl:apply-templates /></Paragraph>
</xsl:template>
<!-- Lists can only occur outside paragraphs, at the top level -->
<xsl:template match="/div/UL | /div/ul"><xsl:apply-templates /></xsl:template>
<xsl:template match="/div/UL/LI | /div/ul/LI | /div/UL/li | /div/ul/li" priority="9" >
<Paragraph Margin="20,0,0,0"><Span><InlineUIContainer><Ellipse Style="{{StaticResource Bullet}}"/></InlineUIContainer><xsl:apply-templates /><LineBreak /></Span></Paragraph>
</xsl:template>
<!-- An UL can only contain LI, so ignore all other elements within an UL -->
<xsl:template match="/div/UL/* | /div/ul/*" priority="8" />
<xsl:template match="B | b | STRONG | strong">
<Bold><xsl:apply-templates /></Bold>
</xsl:template>
<xsl:template match="I | i">
<Italic><xsl:apply-templates /></Italic>
</xsl:template>
<xsl:template match="U | u">
<Underline><xsl:apply-templates /></Underline>
</xsl:template>
<xsl:template match="BR | br" priority="0" >
<LineBreak />
</xsl:template>
<xsl:template match="A | a">
<Span><InlineUIContainer><HyperlinkButton Style="{{StaticResource Link}}"><xsl:attribute name="NavigateUri"><xsl:value-of select="@href"/></xsl:attribute><xsl:apply-templates /></HyperlinkButton></InlineUIContainer></Span>
</xsl:template>
<xsl:template match="IMG | img">
<Span><InlineUIContainer><Image Stretch="None" ><xsl:attribute name="Source"><xsl:value-of select="@src"/></xsl:attribute><xsl:apply-templates /></Image></InlineUIContainer></Span>
</xsl:template>
<!-- Note that by default, the text content of any unmatched HTML elements will be copied in the XAML. -->
</xsl:stylesheet>
RichTextBlockProperties.cs
public class Properties : DependencyObject
{
public static readonly DependencyProperty HtmlProperty =
DependencyProperty.RegisterAttached("Html", typeof(string), typeof(Properties), new PropertyMetadata(null, HtmlChanged));
public static void SetHtml(DependencyObject obj, string value)
{
obj.SetValue(HtmlProperty, value);
}
public static string GetHtml(DependencyObject obj)
{
return (string)obj.GetValue(HtmlProperty);
}
private static async void HtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Get the target RichTextBlock
RichTextBlock richText = d as RichTextBlock;
if (richText == null) return;
// Wrap the value of the Html property in a div and convert it to a new RichTextBlock
string xhtml = string.Format("<div>{0}</div>", e.NewValue as string);
xhtml = xhtml.Replace("\r", "").Replace("\n", "<br />");
RichTextBlock newRichText = null;
if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
{
// In design mode we swallow all exceptions to make editing more friendly
string xaml = "";
try
{
xaml = await ConvertHtmlToXamlRichTextBlock(xhtml);
newRichText = (RichTextBlock)XamlReader.Load(xaml);
}
catch (Exception ex)
{
string errorxaml = string.Format(@"
<RichTextBlock
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
>
<Paragraph>An exception occurred while converting HTML to XAML: {0}</Paragraph>
<Paragraph />
<Paragraph>HTML:</Paragraph>
<Paragraph>{1}</Paragraph>
<Paragraph />
<Paragraph>XAML:</Paragraph>
<Paragraph>{2}</Paragraph>
</RichTextBlock>",
ex.Message,
EncodeXml(xhtml),
EncodeXml(xaml)
);
newRichText = (RichTextBlock)XamlReader.Load(errorxaml);
} // Display a friendly error in design mode.
}
else
{
// When not in design mode, we let the application handle any exceptions
string xaml = "";
try
{
xaml = await ConvertHtmlToXamlRichTextBlock(xhtml);
newRichText = (RichTextBlock)XamlReader.Load(xaml);
}
catch (Exception ex)
{
string errorxaml = string.Format(@"
<RichTextBlock
xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
>
<Paragraph>Cannot convert HTML to XAML. Please ensure that the HTML content is valid.</Paragraph>
<Paragraph />
<Paragraph>HTML:</Paragraph>
<Paragraph>{0}</Paragraph>
</RichTextBlock>",
EncodeXml(xhtml)
);
newRichText = (RichTextBlock)XamlReader.Load(errorxaml);
} // Display a friendly error in design mode.
}
// Move the blocks in the new RichTextBlock to the target RichTextBlock
richText.Blocks.Clear();
if (newRichText != null)
{
for (int i = newRichText.Blocks.Count - 1; i >= 0; i--)
{
Block b = newRichText.Blocks[i];
newRichText.Blocks.RemoveAt(i);
richText.Blocks.Insert(0, b);
}
}
}
private static string EncodeXml(string xml)
{
string encodedXml = xml.Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("\"", """).Replace("'", "'");
return encodedXml;
}
private static XsltProcessor Html2XamlProcessor;
private static async Task<string> ConvertHtmlToXamlRichTextBlock(string xhtml)
{
// Load XHTML fragment as XML document
XmlDocument xhtmlDoc = new XmlDocument();
xhtmlDoc.LoadXml(xhtml);
if (Html2XamlProcessor == null)
{
// Read XSLT. In design mode we cannot access the xslt from the file system (with Build Action = Content),
// so we use it as an embedded resource instead:
Assembly assembly = typeof(Properties).GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("NameSpace.RichTextBlockHtml2Xaml.xslt"))
{
StreamReader reader = new StreamReader(stream);
string content = await reader.ReadToEndAsync();
XmlDocument html2XamlXslDoc = new XmlDocument();
html2XamlXslDoc.LoadXml(content);
Html2XamlProcessor = new XsltProcessor(html2XamlXslDoc);
}
}
// Apply XSLT to XML
string xaml = Html2XamlProcessor.TransformToString(xhtmlDoc.FirstChild);
return xaml;
}
}
这个கொழும்பு:单词单独绑定在富文本中不剩余
谁能指导我犯了什么错误。克服我面临的问题会很有帮助。
注意:字符串也可能包含视频标签,请指导我也绑定视频
提前致谢
【问题讨论】:
标签: c# xaml xslt windows-phone-8.1