Binding WebView directly to Html Content using C++ /CX

This post is inspired by Tim Heuer’s Html Source extension property that uses the WebView’s NavigateToString method to bind webview directly to Html Content. Tim’s code is written using C#. I wanted a C++ version of the same for one of my sample projects and here it is. Feel free to use it in your projects and let me know when you use it. That would make me happy!

Typical Usage scenarios for this extension:

1. You use the SyndicationClient API from the Windows.Web.Syndication namespace and parse a RSS feed of interest.

2. Your UI is a GridView and each GridViewItem displays one article from the RSS feed parsed above.

3. You want to display formatted HTML content instead of unformatted HTML content as string.

For more information, look at this blog post by Soma.

http://blogs.msdn.com/b/somasegar/archive/2012/08/26/building-an-end-to-end-windows-store-app-part-1.aspx

WebViewExtension.h

#pragma once
#include "pch.h"

using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Interop;
using namespace Platform;

namespace Callisto
{	
	[Windows::Foundation::Metadata::WebHostHidden]
	public ref class WebViewExtension sealed
	{
	public:

		static String^ GetHtmlSource(WebView^ view)
		{
			if (nullptr == view)
				throw ref new Platform::InvalidArgumentException("view");

			return view->GetValue(HtmlSourceProperty)->ToString();
		}

		static void SetHtmlSource(WebView^ view, Platform::String^ value)
		{
			if (nullptr == view)
				throw ref new Platform::InvalidArgumentException("view");

			view->SetValue(HtmlSourceProperty, value);
		}
		
		
	private:
		static void OnHtmlSourcePropertyChanged(DependencyObject^ o, DependencyPropertyChangedEventArgs^ e)
		{
			auto view = dynamic_cast<WebView^>(o);
			if (nullptr == o)
			{
				throw ref new Platform::NotImplementedException("The HtmlSource attached dependency property is only valid for WebView instances.");
			}
			// Determine new HTML content
            auto newString = dynamic_cast<Platform::String^>(e->NewValue);
			auto newHtml = newString->IsEmpty() ? "<html></html>" : newString;				

            view->NavigateToString(newHtml);
		}

		static Windows::UI::Xaml::DependencyProperty^ HtmlSourceProperty;
	};
}

WebViewExtension.cpp

//
// Copyright (c) 2012 Sridhar Poduri
// Based on Tim Heuer's C-Sharp version available at
// https://github.com/timheuer/callisto/blob/master/src/Callisto/Extensions/WebViewExtension.cs
//
// Licensed under the Microsoft Public License (Ms-PL) (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://opensource.org/licenses/Ms-PL.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Derived from http://blogs.msdn.com/b/delay/archive/2011/04/14/quot-those-who-cannot-remember-the-past-are-condemned-to-repeat-it-quot-webbrowserextensions-stringsource-attached-dependency-property-makes-silverlight-windows-phone-wpf-s-webbrowser-control-more-xaml-and-binding-friendly.aspx
#include "pch.h"
#include "WebViewExtension.h"

using namespace Callisto;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Interop;
using namespace Platform;



Windows::UI::Xaml::DependencyProperty^ Callisto::WebViewExtension::HtmlSourceProperty = 
	DependencyProperty::RegisterAttached(ref new String(L"HtmlSource"),  TypeName(String::typeid), TypeName(WebViewExtension::typeid), 
	ref new PropertyMetadata(nullptr, ref new PropertyChangedCallback(OnHtmlSourcePropertyChanged)));


 

 

Once you have this header and cpp file in your solution, using them from XAML markup is pretty easy, such as the simple example below.

<WebView local:WebViewExtension.HtmlSource=”{Binding Content}” Grid.Row=”1″/>

Enjoy!

-Sridhar

5 Comments

  1. Andrew Webb

    Can you point me towards some more documentation? I don’t understand the purpose of this code, or exactly how the interaction between the XAML and C++ works. I will explain my sources of confusion as follows:

    Let me guess what each word in the XAML means. Perhaps you can correct the guesses.

    WebView: This is something which can take HTML code and display it. You can Navigate( URI ) to other HTML too.

    local: A wild guess is that means that the following token is located in the project, as opposed to being reserved.

    WebViewExtension: Ah, the name of the class which you just provided.

    .HtmlSource Hmm. I see GetHtmlSource and SetHtmlSource. Perhaps HtmlSource is a property?

    =”{Binding Content}” Not understanding binding too well, I at least understand that Content is fetched from somewhere and assigned to WebView.HtmlSource. Hmm that might make sense. This Content thing is being assigned to the one WebViewExtension::HtmlSourceProperty present in the project. How to set Content, I don’t know. Why you want to set this Platform::String, I don’t know.

    I can see that if the property changes, magic (unknown science) makes OnHtmlSourcePropertyChanged get called which eventually does a Navigate( to new html ) Of course I could have called Navigate( new HTMl ) myself rather than assigning it to the property.

    So now I’m still confused about why this code exists. Could it be because WebView lacks a way to return the actual HTML currently displayed in the WebView? So you jump through hoops to link a String along with the WebView in order to be able to retrieve the actual HTML? Perhaps not, as you already had the HTML.

    Anyhow, I’m confused. I would be curious if there were other readers who understood the intent.

  2. Hi Andrew,
    I have updated the post to reflect typical usage scenarios. Yes, HtmlSourceProperty is a dependency property. When you parse, say a RSS feed, you get content back as String. This content is raw HTML and you do not want to present the user with it. What you need is a mechanism to render this response String as Html. That is what this extension enables you to do.
    The WebView is a XAML control (not the typical control but sort of a miniature IE) that allows you to display web content.
    I am writing a simple app that demonstrates the end to end scenario and will post the same this weekend.

    -Sridhar

  3. Andrew Webb

    I believe I understand the intent now. Soma wants to use XAML to feed the WebView, and so the existence of the Navigate() method callable in C# of C++/CX does not help him. As he says:

    “The WebView control itself doesn’t have a property that allows me to bind the WebView directly to the HTML string contentI already have, but I found code from Tim Heuer for an HtmlSource extension property that uses WebView’s NavigateToString method to achieve the same thing. ”

    I come to this without a background in C# and XAML, and it is slow going. Thanks.

  4. Lakshmi N. Mummidi

    Hi,

    Something went wrong with the code block in the blogpost, the code is coming in one single line and adding horizontal scrollbar. Could you please check that.

    Thanks,
    Lakshmi

Comments are closed