Click here to Skip to main content
Click here to Skip to main content

WinRT : How to Communicate with WebView JavaScript from C# and Vice Versa

, 4 Mar 2014
Rate this:
Please Sign up or sign in to vote.
WinRT : How to communicate with WebView Javascript from C# and vice versa

The other day, I was contacted by one of the fellow XAML Disciples (who has been dormant for a long time, but hey ho), who was asking how he might determine if some audio within a web site was playing or not. I thought the problem could be solved using the WebView available in WinRT. Turns out I didn’t get what his actual problem was, and this did not help him. I did however try something out before I answered him, which was how to communicate with the WebView hosted HTML/JavaScript from C# and vice versa.

I thought that may make a semi-useful blog post. So I have provided a dead simple example, the C# code will try and change the FontSize of a DIV within the hosted HTML content by calling a JavaScript function in the hosted HTML content. The JavaScript will then double the incoming FontSize and use it for the DIV, and at the same time tell the C# what the doubled size is via a callback into the C# code. Simple requirement really.

It all starts with the markup which is shown in its entirety below:

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Border Background="{StaticResource ApplicationPageBackgroundThemeBrush}" BorderBrush="White"
        BorderThickness="4" Height="400" Width="640" Padding="10">
        <StackPanel>
            <StackPanel.Resources>
                <Style x:Key="RefreshAppBarButtonStyle" TargetType="ButtonBase"
            BasedOn="{StaticResource AppBarButtonStyle}">
                    <Setter Property="AutomationProperties.AutomationId" Value="RefreshAppBarButton"/>
                    <Setter Property="AutomationProperties.Name" Value="Refresh"/>
                    <Setter Property="Content" Value="?"/>
                </Style>
            </StackPanel.Resources>
            <WebView x:Name="webView" Height="300" Width="600"/>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10">
                <Button x:Name="font25" Content="25px" Click="Change25_Click"/>
                <Button x:Name="font40" Content="40px" Click="Change40_Click"/>
                <Button x:Name="font60" Content="60px" Click="Change60_Click"/>
                <Button x:Name="reset" Content="Reset" Click="Reset_Click"/>
            </StackPanel>
        </StackPanel>
    </Border>
</Page>

Nothing fancy there, just a WebView control and a few buttons to change the FontSize of the DIV.

So let's have a look at the C# side of things. Here it is in its entirety:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            webView.ScriptNotify += webView_ScriptNotify;
        }

        async void webView_ScriptNotify(object sender, NotifyEventArgs e)
        {
            var jsScriptValue = e.Value;
            MessageDialog msg = new MessageDialog(jsScriptValue);
            var res =  await msg.ShowAsync();

        }

        private const string htmlFragment =
                    "<html><head><script type='text/javascript'>" +
                    "function doubleIt(incoming){ " +
                    "  var intIncoming = parseInt(incoming, 10);" +
                    "  var doubled = intIncoming * 2;" +
                    "  document.body.style.fontSize= doubled.toString() + 'px';" +
                    "  window.external.notify('The script says the doubled value is ' + doubled.toString());" +
                    "};" +
                    "</script></head><body>
                    <div id='myDiv'>I AM CONTENT</div></body></html>";

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            webView.NavigateToString(htmlFragment);
        }

        private void Reset_Click(object sender, RoutedEventArgs e)
        {
            webView.NavigateToString(htmlFragment);
        }

        private void Change25_Click(object sender, RoutedEventArgs e)
        {
            webView.InvokeScript("doubleIt", new string[] { "25" });
        }

        private void Change40_Click(object sender, RoutedEventArgs e)
        {
            webView.InvokeScript("doubleIt", new string[] { "40" });
        }

        private void Change60_Click(object sender, RoutedEventArgs e)
        {
            webView.InvokeScript("doubleIt", new string[] { "60" });
        }

    }
}

Calling JavaScript from C#

This is done using the WebView.InvokeScript() method, where it expects a name of a function, and a string[] for the arguments.

Calling C# from JavaScript

This is slightly trickier as you need to carry out the following 3 steps:

Step 1: Hook up the WebView.ScriptNotify event

Step 2: Use the result of the NotifyEventArgs.Value from Step 1

Step 3: Get the WebView to actually call the ScriptNotify c# event, which is done via this bit of code:

window.external.notify(..)

NOTE

WinRT makes a big point out of the fact that the WebView control is a regular WinRT control that can be treated as any other element such as applying Transforms, etc., while this is true (I have seen the demos/videos/screenshots). However it seems one area has been missed (at least in Windows 8.0 that
I am currently using), which is that the WebView seems to be the top most element. Try the XAML below and see what you think:

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid Background="Black" Grid.Row="0">
            <StackPanel Orientation="Horizontal"  Margin="20">
                <ComboBox Width="150">
            <ComboBoxItem Content="hello1"/>
            <ComboBoxItem Content="hello2"/>
            <ComboBoxItem Content="hello3"/>
            <ComboBoxItem Content="hello4"/>
            <ComboBoxItem Content="hello5"/>
            <ComboBoxItem Content="hello6"/>
            <ComboBoxItem Content="hello7"/>
            <ComboBoxItem Content="hello8"/>
            <ComboBoxItem Content="hello9"/>
            <ComboBoxItem Content="hello10"/>
            <ComboBoxItem Content="hello11"/>
            <ComboBoxItem Content="hello12"/>
            <ComboBoxItem Content="hello13"/>
            <ComboBoxItem Content="hello14"/>
        </ComboxBox>
                <Button Content="Reset" Margin="10,0,0,0" Height="45" />
            </StackPanel>
        </Grid>
        <WebView Grid.Row="1" HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch" Margin="10,0,10,10" />

    </Grid>

</Page>

For me, the ComboBox popup goes behind the WebView, a tad annoying, and for me makes the WebView pretty unworkable.

As always here is a small demo project: Demo project.zip.


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sacha Barber
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
 
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
 
Both of these at Sussex University UK.
 
Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 4 Mar 2014
Article Copyright 2014 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid