So for the last few days or so I’ve been playing around with WPF/E on the side. Mainly looking at samples, reading through code and setting up some simple examples for myself to get through the conceptual process. The idea of having a rich, and light weight client platform that can run in the browser has always been very enticing and WPF/E sounds like it might address that scenario – or some of that scenario.
WPF/E is a small subset of the full WPF (Windows Presentation Framework) and is shipped as a browser plug in that runs in Internet Explorer, FireFox and Safari and runs both on Windows and Mac currently. The download to install is pretty small – 1.1 megs for Windows and 3.5 megs for Mac – and supposedly in the future WPF/E will automatically download and install instead of a separate install.
What’s it to me?
To me the technology sounds interesting because HTML as a presentation platform is in some ways very limited. There’s very little in the way of graphics support and the functionality of various native UI controls is beyond basic.
I have a couple of customers that I work with that have fairly rich applications that run in Flash and while these apps work well enough, using Flash to build them has been a royal pain in the ass for both companies. The main reason these apps were created in Flash at the time was that Flash for years has had the ability to make remote callbacks to services on the server (ie. AJAX like functionality) in a cross browser environment, plus the fact that you can create some very slick looking user interfaces – even form based interfaces with relative ease. But at the same time the Macromedia/Adobe language stuff and APIs have always been quirky at best and the APIs very limited. Nevertheless the platform provides for a relatively nice client platform to prevent a more interactive user interface.
It’s kind of been in this vein that I was hoping WPF/E would go, but after checking it out it’s clear that currently WPF/E is really not at all geared at that particular scenario. The current version of WPF/E seems to address only the graphical/visual display aspect of Flash. WPF/E basically picks up most of the full WPF’s graphical elements – basic drawing elements, animations, gradients, brushes – as well as media aspects. All of this is great in that these are all things that are missing in a straight browser environment. WPF/E is a subset of the full WPF functionality, and it uses the same XAML schemas that WPF uses.
Using WPF/E
The way that WPF/E is implemented is currently like this:
You create a Web Page and add a WPF/E control to it. You can add it either using an <object> tag or in script code (probably better since it works across browsers without changes). A WPF/E control is hosted inside of an HTML tag that becomes the host container and the actual WPF/E control is then exposed as a named element in the page inside of the host container.
Once loaded in the page, you can interact with the control using JavaScript code, and the control can fire events back into javascript code on the page (or external script files). So load and movement events from within the WPF/E control can essentially trigger events that are handled with JavaScript in the HTML page. Typically the WPF/E control hosts the content of a XAML file which is parsed and ‘executed’ in the control. So in a way you can think of XAML page as the content page and the JavaScript inside the HTML host page as the code behind for handling events of the XAML page.
Here’s an example of an HTML page hosting a WPF/E control:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>WPF/E 101</title>
<script type="text/javascript" src="js/aghost.js"></script>
</head>
<body>
What's your name:
<input id="txtName" value="Rick"/>
<input type="button" onclick="HtmlClick()" value="Show"/>
<hr />
<div id="HostContainer" style="background:brown;padding:20px;Height:800px;">
<div id="wpfeControlHost" style="background:green;height:100%;width:100%;">
<script type="text/javascript">
new agHost("wpfeControlHost", // hostElementID (HTML element to put WPF/E
"wpfeControl", // ID of the WPF/E ActiveX control we create
"100%", // Width
"100%", // Height
"#ffffffff", // Background color
null, // SourceElement (name of script tag containing xaml)
"xaml/TestPage.xaml", // Source file
"false", // IsWindowless
"30", // MaxFrameRate
"OnError", // OnError handler (method name -- no quotes)
0, // Minimum major version required
8, // Minimum minor version required
5 // Minimum build required
);
</script>
</div>
</div>
</body>
</html>
This embeds the control into a <div> tag of the page and loads testpage.xaml into it. If the Xaml file exists and it is valid that Xaml will be rendered into the control.
If you download the WPF/E you can also grab a sample pack which includes a number of sample both simple of complex to give you an idea of what you can do with WPF/E’s XAML support. But to keep things simple here’s just a very basic XAML layout that I used for seeing how things work with a few simple features added (pardon me I’m no graphics designer <s>):
<!-- Root Object with namespaces -->
<Canvas xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="javascript:onLoaded">
<!-- Canvas for 'button -->
<Canvas Name="ContentCanvas" Canvas.Left="20" Canvas.Top="20"
MouseLeftButtonDown="javascript:onButton_Click">
<Rectangle Canvas.Left="25" Canvas.Top="25" Width="220" Height="35"
Stroke="Maroon" StrokeThickness="2" RadiusX="5" RadiusY="5">
<Rectangle.Fill >
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0" Color="Yellow" />
<GradientStop Offset="1" Color="Red" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<TextBlock Name="lblHello" Canvas.Top="35" Canvas.Left="35"
Foreground="Blue" FontFamily="Verdana" >
Hello World from WPF/E
</TextBlock>
</Canvas>
<!-- these elements end up in the main body -->
<!-- Embedded Video that autostarts. can also use streamed MP3 Music! -->
<MediaElement Name="media" Source="fabrikam.wmv"
Canvas.Top="0" Canvas.Left="300"
Width="300" Height="300" AutoPlay="True"
MouseLeftButtonDown="javascript:TogglePlayer" />
<TextBlock Canvas.Left="25" Canvas.Top="280"
Foreground="Maroon" FontFamily="Verdana">
Another bit of Text
</TextBlock>
</Canvas>
Very basic stuff basically not meant to do anything fancy but to demonstrate the interaction between the HTML page and the WPF/E control. There’s a main Canvas object that is the root element which is required. This is the top level control content. Inside of that content other controls can be nested as children including other Canvas elements. Canvas elements act as a group container and you’ll need to use them quite extensively if you want to create any semblance of a ‘control’, because WPF/E includes no controls whatsoever. No input controls, not even buttons are provided – it’s all about design from scratch.
Hence to even simulate a button you have to design it – in this case a rectangle and a text control nested inside of the child canvas object. Most of the elements in XAML can fire events and if I want to simulate a button the event I want to likely trigger is MouseLeftButtonDown which is assigned to the child canvas. I could have used the Rectangle or TextBlock and hooked the event there, but because events bubble back to the parent it’s easier to hook up once at the parent Canvas and be done with it.
As you can see events are fired to javascript:HandlerName, like this:
<Canvas Name="ContentCanvas" Canvas.Left="20" Canvas.Top="20"
MouseLeftButtonDown="javascript:onButton_Click">
which refers to a piece of JavaScript code in the host HTML page. Here’s the HTML script code for the HTML page shown earlier:
<script type="text/javascript">
// Loaded event handler for the Canvas object.
function onLoaded(sender, eventArgs)
{
var Label = sender.findName("lblHello");
Label.Text = "Hello " + document.getElementById("txtName").value + " from WPF/E";
// Retrieve a reference to the Control host
var control = sender.getHost();
// Create a TextBlock using a literal XAML string.
var textblock = control.createFromXaml('<TextBlock Canvas.Top="150" Canvas.Left="25" Foreground="Green">Added dynamically to the Canvas</TextBlock>');
var ContentCanvas = sender.findName("ContentCanvas");
// Append the TextBlock to the sender, or Canvas, object.
ContentCanvas.Children.Add(textblock);
}
function onButton_Click(sender, eventArgs)
{
var Rect = sender.Children.GetItem(0);
// *** Flip the gradient colors
Rect.Fill.GradientStops.GetItem(0).Color = "Red";
Rect.Fill.GradientStops.GetItem(1).Color = "Yellow";
var TextBox = sender.Children.GetItem(1);
TextBox.Text = "Clicked at " + (new Date()).toLocaleTimeString();
}
function HtmlClick()
{
var Wpf = document.getElementById("wpfeControl");
var Label = Wpf.findName("lblHello");
Label.Text = "Hello " + document.getElementById("txtName").value + " from WPF/E";
}
function TogglePlayer(sender, eventArgs)
{
if (sender.CurrentState == "Playing")
sender.Pause();
else if (sender.CurrentState == "Paused" || sender.CurrentState == "Stopped")
sender.Play();
}
function OnError(Line,Col,hr,Message)
{
alert("Error: " + Message + " " + Line + "." + Col) ;
}
</script>
You’ll notice that there are several methods implemented here – one to handle the WPF/E control’s Loaded event (onLoaded), one to handle the click on the WPF/E button simulation and one to handle updating the WPF/E button label from the HTML page (HtmlClick) and finally one that is used on the video on the page to start and stop the video when you click on the video.
The good news is that this process is pretty straight forward. The events fired by the WPF/E control fire directly into JavaScript and they always fire with the same parameter signature which is a sender and an EventArgs object that provides additional information. Let’s look at a few things you can do to have the HTML and the WPF/E control communicate.
First, you can get a reference to the WPF/E control at any time by using document.getElementById(NameOfWpfControl) from the HTML. This gets you the top level Canvas control in the XAML code. From there you can use the highly useful findName() method to get a reference to any named control on the page or you can loop through the Children Collection of the Canvas and drill through each of the containers iteratively. At that point you can assign to the properties of the control.
The WPF/E documentation is actually quite decent for getting information on properties and methods and events available on each of the elements and you can fairly easily figure out what properties to set. You need to install the WPF/E SDK for the documentation to install. Some properties are pretty simple, but most are composite objects like the GradientFill in the button for example which takes a little bit more fiddling to figure out how to address.
You can also add controls dynamically by accessing the Control’s host object creating a new object or using the often useful createFromXaml() method which lets you create a control from XAML markup. This lets you inject new controls into the page dynamically.
When handling events it’s always important to keep track which object initiated the event. For example the onButton_Click above is captured from the child canvas – so that’s the object that gets passed as the sender in the event callback in the JavaScript. You can use findName() to find any child elements, or you can iterate over the Children collection and use GetItem() to retrieve individual items.
Frankly I was surprisingly pleased how easy it is to make the HTML page and the control interact with each other even though my WPF skills are practically nill at this points. Still there’s a lot of looking up of properties involved in the documentation <s> - but that’s to be expected at this point at least for me.
Some things to watch out for
The browser loads the HTML page with the WPF/E control into it. The XAML is loaded dynamically by the page and the XAML is cached. So if you change the XAML and then simply refresh the page in most cases the XAML isn’t reloaded. You can get around this by using View in Browser from VS.NET because of the way VS reloads pages it apparently forces a refresh where the standard Refresh operation inside of IE at least doesn’t. Alternate you can shut the browser down and the View again. You can also change the host page (the HTML page) which also refreshes.
Looks like currently Visual Studio is not aware of the WPF/E XAML schema so you get no Intellisense or designer support. As a workaround I’ve found that you can often get by using the full WPF schema to get the designer and Intellisense to work. The designer will falter though if you use any non-supported WPF properties or elements. For example, the MediaElement AutoStart property isn’t support and that single property mismatch will keep the designer from working.
Using this schema setup:
<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="javascript:onLoaded">
<!-- xmlns="http://schemas.microsoft.com/client/2007" -->
Lets you at least get Intellisense to work. Although you’ll get the full WPF Intellisense (which will show more functionality than you can use) this is still a big improvement over lookup everything in the documentation… Not sure how well this works with more complex content but I noticed that several of the sample controls don’t even define the WPF/E schema and just have the full WPF schema. It appears the WPF/E runs OK with the full WPF schema.
Speaking of samples – there’s also a WPF/E sample pack download that’s quite useful for seeing how to do a number of things. They are interesting samples in that they show off some things that you can do.
Some thoughts on WPF/E
My first impression of WPF/E is a mixed on. The implementation and usage is actually well done. While I’d have to get seriously up to speed on XAML and WPF concepts in general, I can see myself working with this sort of environment.
But I’m having a real hard time placing what WPF/E can do for me in my day to day work building business applications or even community style content.
As nice as WPF/E is it’s really focused ONLY at designers. The only things you can do with WPF/E at this point seems to be create visual content, but not necessarily interactive content. You know video game style content and flashy graphics. Which admittedly is something that’s missing in HTML and so a good complement.
There are UI events like clicks and keypresses etc. but there are no input controls of any kind. There are also many puzzling omissions in WPF/E as opposed to WPF. For example the text elements have no support for any sort of alignment – you’re supposed to do this on your own in code.
You might say, what do you need UI inut for – after all we CAN do that in HTML right? Well, it sure would be nice if you could create a rich experience in one environment, in one place. And the real benefit that I’m hoping for is to get away from the crazy cross browser issues of HTML development in general. With a rich environment that contains a rich control model HTML could become a sideline.
WPF/E is an ActiveX control inside of IE and some sort of browser object in FireFox and as such it’s a top level control meaning you can’t in anyway overlay other content on top of it right now. So if you need to get user input you’d have to put it into HTML and then send the value into the control somehow and not have it part of the actual application.
I mention this because I work with two separate customers who today are using Flash as their main UI for some fairly complex Web UIs. These UIs are very data entry and display heavy. Lots of text input fields and a number of heavy duty lists full of financial data. Part of the allure of Flash at the time was that it’s always had HTTP connectivity in a cross browser format prior to AJAX functioanlity available across browsers. But also the fact that the UI controls provide a richer repertoire than the paltry native HTML controls was a big reason that allowed for the creation of windowed applications that run in the browser.
There’s nothing comparable right now in WPF/E and I was kind of hoping that WPF/E would address this scenario. But it’s not there today.
If you want a kick ass plug-in engine you'd want to have something that works both for designers and developers. What I see in WPF/E right now is something that only a designer could possibly enjoy.
A lot of people get all bent out of shape about the size of a plug-in and while I agree that the size has to be reasonable for the engine to install, I think we shouldn’t lose a nut over a reasonable download size. The current download is 1.1 meg for the Windows version and 3.5 meg for the Mac version.
Does the size really matter all that much? If we’re worried about people accessing our applications with a modem we wouldn’t be talking about WPF/E and AJAX anyway because those people are going to be having a sucky experience any way you look at it. I’ve seen ASP.NET apps with Viewstate that will fill up 10 megs with 10 page hits <s>…
What’s interesting though is that Flash is only a 1.1meg download. But Flash has a lot more functionality than WPF/E has at this point (even though the platform is certainly not developer friendly either).
But I also think it would be a huge mistake for Microsoft to let download size and even Flash as any kind of yardstick become an obstacle to designing a tool that is all that it can be…
Microsoft has hinted that eventually WPF/E will include its own internal .NET micro runtime so that we could presumably write code using a more complete .NET language. I suppose that would mean compiled IL code and an interpreter, but this would probably make the development experience a heck of a lot better.
While the JavaScript approach actually works reasonably well, man would it be nice to get a decent chunk of the .NET runtime available to get the basic type system in place, built-in network support rather than having to go through the browser and AJAX to get that. Currently if you want to interact with the server you’re back to using MS Ajax or other standard HTML post back mechanisms. Network support should be native to the plug-in.
It’s clear that using JavaScript for the language engine is saving Microsoft a ton of baggage – if .NET code execution gets added the size will likely bump pretty noticeably.
How much is too big? Mincing Megs…
The question really is how far is Microsoft really willing to take this technology? Isn’t it kind of ironic that after more than 10 years of HTML browser applications and all the hacks we’re creating we (and other platforms like Flash) are haggling over getting a 10 or even a 20 meg runtime down to the client to get some sanity into the Web platform… 10 megs – fuck. I downloaded 15 gigs yesterday to download Orcas and we’re worried about a lousy 10megs?
Microsoft already has a damn good presentation platform in WPF – while it’s fairly big, you gotta ask yourself if you put WPF and a micro .NET framework onto the client how big would it really be? .NET 2.0 and .NET 3.0 combined are around 30 megs or so I believe. But how much of that could you ditch for a kick ass client layer? All the server stuff: System.Web’s, Web Services, Enterprise Services, Server side networking and so much more – I bet a very full featured client engine with rich client controls, most of WPF could be shoehorned into a 10 meg download. Would that still be too much of a price to pay these days when Broadband reaches more than 75 percent of the Web population???
Wouldn’t you love to see a client platform that:
- Had rich client side functionality a la WPF
- A rich set of controls so you don’t have to hack HTML
- Easy and natural network access (sandboxed of course)
- Use any .NET language with the full .NET type system
- A client side control model so you can build resusable code
- A compilation engine that would let you effectively debug these applications?
Flash actually hits much of these bullets, but Microsoft has the advantage of a developer base that Adobe can only dream of in terms of numbers. Flash’s designer centric focus and lack of decent APIs is also the reason it’s never really taken off as a development platform. Let’s hope Microsoft doesn’t make the same mistake with WPF/E
WPF/E – where are we at?
So what is WPF/E good at as right now? From what I can see WPF/E is a good fit for:
- Anything dealing with Media content (video, audio)
- Flashy, ‘video game style’ UIs (pure point and click UIs)
- Interactive games
- Graphing of any kind
This is not a bad start – it’s certainly areas that Microsoft currently hasn’t addressed. But I’m a little concerned over this focus on design all of a sudden where there seems to be a heavy segratation between design and development. The key to this is that both of these branches can work well together.
*** updated 3/8/07: Windowless WPF/E Controls
After some further review I noticed that you can have WindowLess WPF/E controls which overlay ontop of standard HTML content and let you see the content below. This feature does allow for some interesting possibilities and mitigates to some degree the lack of input controls as you can use HTML contols as part of the content.