Displaying HTML Strings in the Windows Phone 7 WebBrowser

Turns out I shouldn’t code after midnight. As Bill points out below, the WebBrowser control’s slightly poorly named NavigateToString method will do all of this in one call. God do I feel stupid right now.

I have however sorted out getting links to open a proper BrowserTask, and have also got my css formatting changing to match the phone’s theme. I’ll write that up later once I make sure it’s not simplified elsewhere.

I’m building a Windows Phone 7 application, and I have a need to show nicely formatted HTML from a dynamic source, but not a web server. I hacked around with Silverlight’s TextBlock with its Inlines property for a while, but the lack of anything other than a plain Run object leaves me short. I can’t easily render links and lists.

My hint came from this MSDN article, describing how to display resource files by first writing them to Isolated Storage. My solution assumes you have an object (hopefully a ViewModel) with one or more properties that hold raw HTML. Mine is hardcoded below, but let’s assume you’re getting it from some sort of data store or API.
[csharp]
public string Description
{
get
{
return
@"<body style=""font-family:’Segoe WP’;font-size:46px"">
<p>Sample Readme Content</p>
<p>Here’s another paragraph
<a href=""http://ben.geek.nz"">with a link</a> and
<b>some bold, <u>underlined</u> text</b></p>
<ul><li>And a list</li><li>With two items</li></ul>
</body>";
}
set { }
}
[/csharp]

You might already see where I’m going with this. We co-opt the SaveToIsoStore method from Microsoft’s example, and use it for our own nefarious purposes. I write our HTML out to a file, then return a Uri pointing to that file:
[csharp]
private const string CurrentDescriptionFileName = "CurrDesc.html";

public Uri DescriptionUri
{
get
{
IsoStore.SaveToIsoStore(
CurrentDescriptionFileName,
new System.Text.UTF8Encoding().GetBytes(Description));

return new Uri(CurrentDescriptionFileName, UriKind.Relative);
}
}
[/csharp]

Then we can set our WebBrowser control to point to this Uri. Unfortunately in the current build there is no bindable Uri property on the control, so we have to resort to ugly old code-behind to tell the WebBrowser to load our page. The code below assumes you’ve already set a DataContext, so we just grab a reference to it and call the DescriptionUri we created above:
[csharp]
private void webBrowser1_Loaded(object sender, RoutedEventArgs e)
{
var dc = (MyViewModel) this.DataContext;
webBrowser1.Navigate(dc.DescriptionUri);
}
[/csharp]

WP7 Html HackEt voila! Our dynamic HTML string appears all lovely and formatted in the browser control. The main issue I have at the moment is that I can’t seem to force links to open in the external browser. I guess I’ll have to catch the click event in script, and send it out to the host control.

So there you have it. I never said it was pretty, and it does seem a bit heavyweight to go hammering on isolated storage, but it does work!

3 Comments

  1. This is clever, and I can think of some uses for it, but for just displaying generated HTML why not use NavigateToString on the WebBrowser control?

    • OMFG. It’s obviously far too late at night. I’m in a total MVVM mindset so was seeking a way to provide a bindable property. I simply presumed that NavigateToString was a helper for NavigateToUri.

      I’m a total idiot.

      Ah well, I’ve also got the control rendering perfectly with all the same colours as the host control now.

Leave a Reply

Your email address will not be published.

*

© 2017 Ben

Theme by Anders NorenUp ↑