WPF XBAPs for Mozilla Firefox in .NET Framework 3.5

27. March 2007

Rich Internet Application columnist for ZDNET Ryan Stewart broke the news today that the WPF team are working on XBAP applications for Mozilla Firefox for the upcoming .NET Framework 3.5 (codename "orcas") release.

XBAPs (Xaml Browser APplications) are a special kind of ClickOnce deployed WPF application that is hosted in the browser inside a security sandbox, and currently only work in IE6/7. XBAPs integrate well into existing web-based applications providing a fairly seamless transition from regular HTML content to WPF application, since they are hosted inside the main browser window. Presumably this hosting is what makes getting XBAPs to work in Firefox more difficult than regular ClickOnce applications, which currently can work. The Firefox support would only be for versions of Firefox capable of running WPF itself (currently XP SP2, Server 2K3 and Vista, but may change for 3.5).

This also raises the question of .NET Framework 3.5 adoption - .NET 3.0 gets a hand-up in the adoption stakes because it is included in Vista, so it can ride the Vista adoption curve. Unless Microsoft make .NET framework 3.5 an automatic update for Vista its adoption will significantly lag .NET 3.0 for some time.

Why is the Width/Height Property for many Elements ‘NaN’ in WPF?

14. March 2007

Developers new to WPF are sometimes a little confused when the Width and Height properties of elements report as ‘NaN’ (Not a Number) in code, when these very same elements are clearly visible and do have a width and height. What’s going on?

The short answer is you can interpret ‘NaN’ to mean “not set”. The Width and Height properties of Buttons, TextBoxes and most other controls are inherited from the FrameworkElement superclass. These normal .NET properties in turn backs on to a DependencyProperty (the WidthProperty in the case of Width) that has been registered for FrameworkElement in the class constructor with a default value of ‘NaN’. Until you set that WidthProperty to something, or set the Width .NET property in code or Xaml the Width will stay as ‘NaN’. If you wish to know what the on-screen size for an object is you should instead consult the ActualWidth and ActualHeight properties, which always reflects the actual width and height of the object on screen. These properties are sometimes a little hard to find given the number of public properties and methods on many objects in WPF.  

How can I pass Querystring parameters to my WPF XBAP Application?

25. February 2007

The query-string portion of the URL in a HTTP request is a useful place for passing state between pages in web applications. It is therefore not unexpected that developers would also want to use this common idiom for passing information to WPF XBAPs (Xaml Browser Applications) that they wish to integrate with their site.

Fortunately this is not too difficult, except there is one trick you need to know. The ActivationUri property of the ApplicationDeployment object gives you the Uri that launched the XBAP. To get access to this you need to add a reference to System.Deployment.dll. To get hold of the current ApplicationDeployment object for your XBAP use the static CurrentDeployment property of the ApplicationDeployment object like so.

Uri launchUri = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.ActivationUri;

If you launch this code from inside Visual Studio to debug it won’t work. The way it is launched means when you press F5 means that the CurrentDeployment property will be null and thus cause a NullReferenceException. You can use the static IsNetworkDeployed property of the ApplicationDeployment ojbect to check if you’ve been deployed over the network (for an XBAP application hosted in the browser this should be true).

if (ApplicationDeployment.IsNetworkDeployed)
{
    Uri launchUri = ApplicationDeployment.CurrentDeployment.ActivationUri;
}

So far so good, and now for the trick. In order for the deployment infrastructure to actually pass anything through to you via this API you need to set a property in your manifest. Fortunately Visual Studio 2005 gives you a convenient way to do this. Select project properties in Visual Studio 2005 and then go to the publish tab, as shown in figure below.
Publish Tab in VS 2005

Now click the Options button and in the options dialog check the box that says “Allow URL parameters to be passed to application”. Click OK and re-build your application.
Publish Options Dialog

Once you’ve verified that the URI is being passed through you can use the Query property of the URI to return the query-string portion, and parse out any information you need from there.

How do I know if I am running on the UI thread in WPF?

20. February 2007
The golden rule of WPF multi-threading is "Thou shalt only update UI using code that runs on the same thread as the UI." If you happen to be running on another thread you use the Dispatcher property of any of your UI elements to get back on to the UI thread. This raises the question - how do I know when I'm on the UI thread? It turns out the Dispatcher has two methods you can use - CheckAccess and VerifyAccess. CheckAccess returns true if you are on the UI thread. VerifyAccess is a more aggressive version of this method and throws an exception if you are not running on the UI thread. Strangely CheckAccess is marked with attributes to prevent it appearing in intellisense in Visual Studio. This CheckAccess method is the WPF equivalent of the InvokeRequired property of the Control object in Windows Forms, which had similar thread-affinity rules to WPF.

On a related note the Arbel Network  Blog has an excellent tip that uses reflection inside of a method to call back in to itself (but on the UI thread) if necessary. They also have a link to Nick Kramer's threading white paper.

What are some of the “gotchas” with using the WPF frame control?

8. February 2007

The WPF frame control is a content control, capable of displaying both WPF and HTML content, and allowing navigation between different pieces of content. While it is un-questionably useful there are some limitations with it that make it more so in some circumstances than others.

Rendering
The WPF Frame control alters the way it renders based on the type of content it is displaying. When it is displaying WPF Pages or loose XAML it uses WPF’s rendering pipeline. When HTML is displayed the Frame uses Internet Explorer for rendering. Internet Explorer uses traditional GDI-based rendering. Thus when displaying HTML content you will experience many of the rendering issues you also encounter when using a HwndHost, such as not being able to apply transformations or transparency and not being able to use the output as a visual brush or texture.
A striking example of this can be seen by placing identical Frame elements on a form side-by-side. One frame is displaying HTML and the other is displaying Xaml content and both have a RotateTransform applied to them. The Frame displaying Xaml content is rotated, but the HTML frame is not.

Xaml Code (.NET 3.0)
<Window x:Class="LearnWPF.FrameTest.Window1"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation "
    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml "
    Title="LearnWPF.FrameTest" Height="300" Width="300"
    >
    <StackPanel>
      <Frame Source="TestPage.xaml">
        <Frame.LayoutTransform>
          <RotateTransform Angle="25" />
        </Frame.LayoutTransform>
      </Frame>
      <Frame Source="E:\TestHTMLPage.htm">
        <Frame.LayoutTransform>
          <RotateTransform Angle="25" />
        </Frame.LayoutTransform>
      </Frame>

    </StackPanel>
</Window>

Frame Rendering - Xaml and HTML
Another example can be seen by setting some properties on the top-level window object. Setting the Window’s AllowTransparency to True (which also necessitates setting the WindowStyle to None) causes the frame displaying HTML to be not shown at all!

Xaml Code (.NET 3.0)
<Window x:Class="LearnWPF.FrameTest.Window1"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation "
    xmlns:x="
http://schemas.microsoft.com/winfx/2006/xaml "
    Title="LearnWPF.FrameTest" Height="300" Width="300"
    AllowsTransparency="True"
    WindowStyle="None"

    >

code changes cause WPF frame not to render

Content
Another issue which can cause problems when trying to use the WPF Frame control is how to assign the content you wish to display. Although the Frame inherits from ContentControl which has a Content property of type object, you can’t use this to property to place “marked up” content in the Frame. Assigning a string to the content property will cause the Frame to display the assigned content as literal text. Instead you need to use the Source property of type Uri which can point to content on the internet or on disk. Thus if you wish to display a fragment of HTML (perhaps extracted from an RSS feed, or dynamically generated) it has to be written to local disk before it can be rendered.

Depending on how you intend to use the Frame these issues could be non-issues or deal breakers. To get around some of these limitations in applications some people have written code to convert from HTML to WPF FlowDocuments, although the complex and layered nature of HTML and the surrounding specifications like CSS and ECMAScript make exact conversion impossible.

Chris Anderson's WPF book available for pre-order from Amazon

5. February 2007

WPF architect Chris Anderson has been working on a book explaining his wonderful creation for quite some time now. The book is just under 500 pages long and should be available at the end of April, but you can pre-order it now on Amazon. I can't wait to read this one to get insights from Chris as to the "why" of certain bits of WPF design. The book also has an accompanying page on Chris' site which contains a link to the first 9 pages of the book in XPS format, and will hopefully include code downloads and such when the book is released.

Essential WPF book cover

.NET 3 available as an optional software update for XP

5. February 2007
As a few others have noted .NET 3 (the delivery vehicle WPF is included in) is now available as an optional update for XP via windows update. This should hopefully increase the adoption of WPF amongs users who are not planning on upgrading to Windows Vista.

Xaml Decompiler from Lutz Roeder

29. January 2007

Lutz Roeder, author of the popular .NET class browser and decompiler reflector has released a Xaml disassembler. Xaml (used for defining UI layout and vector graphics in WPF applications) is typically "compiled" into a more efficient binary representation called Baml and embedded as a resource in WPF applications where it is read at run-time. Lutz' tool reverses this "compilation" process, returning Xaml which is much easier to understand than Baml, but also easier to copy. Lutz Roeder is a Microsoft employee has been a member of the Expression Blend (formerly Expression Interactive Designer, formerly Sparkle) team since 2002.

I performed some tests disassembling/decompiling non-trivial Baml from a few applications (some of which I had the source-code and some which I did not) and was impressed by the accuracy of the output. More details on using the BamlDecompiler utility can be found here. In addition to being able to disassemble Baml from WPF applications it is also useful for looking at the default control styles for the different windows themes. Although there are a number of classes in the System.Windows.Markup namespace (part of WPF and .NET3) that read Baml at run-time (for creating object instances) it seems that Lutz has had to do a fair bit of "heavy lifting" himself inside the BamlDecompiler class in which makes up the vast majority of the tool. No doubt this will become essential for analysing WPF code and 3rd-party libraries.

Minor Issue Rendering Combo Boxes in WPF XBAP Applications

22. January 2007

I recently noticed an issue with the rendering of ComboBox controls when they are hosted in WPF XBAP applications. The nature of this issue is such that it will probably (hopefully?) not cause anyone any problems. As the screen-shot below shows, when a ComboBox has a RotateTransform applied to it (as either a RenderTransform or LayoutTransform) the "drop down" part of the combo is not rotated. For comparison I've included a regular WPF ListBox which is also rotated.

 ComboBox rotated in WPF XBAP application

In contrast the same Xaml code hosted in XamlPad does not have this same "issue".

ComboBox hosted inside XamlPad 

When I add Controls to a WPF RichTextBox They Are Always Disabled. How can I change that?

18. January 2007

WPF FlowDocuments can contain controls like CheckBoxes and Buttons. When the document is displayed statically and is not editable the controls are enabled, however in WPF V1 when they are rendered as the content of a RichTextBox (and the FlowDocument can be edited) the controls are disabled.

This has not always been the case. During the WPF CTP releases around beta 1 it was possible to enable controls inside a FlowDocument contained within a RichTextBox by setting the IsEnabled property on the FlowDocument to true. As WPF V1 approached the WPF team decided to disable this functionality. Although I don’t believe I’ve ever seen a reason for this it would be a difficult feature to fully support.

Fortunately there is a fairly clean work-around, for those prepared to take the risks associated with using a feature that the product team has consciously disabled. By inheriting from FlowDocument and over-riding the protected IsEnabledCore method to return true, and then using this FlowDocument sub-type inside the RichTextBox you can add enabled controls.

C# Code (WPF V1)
class EnabledFlowDocument : FlowDocument
{
    protected override bool IsEnabledCore
    {
        get
        {
            return true;
        }
    }
}

Xaml Code (WPF V1)
<RichTextBox Grid.Column="1">
<!-- sub-class of FlowDocument -->
<my:EnabledFlowDocument FontFamily="Segoe" FontSize="12">
  <Paragraph>
  This is some text inside a sub-type of flowdocument
  </Paragraph>
  <BlockUIContainer>
    <Button Content="Click Me!" Click="ButtonClicked">
    </Button>
  </BlockUIContainer>
  <Paragraph>
    <Hyperlink
     NavigateUri="http://learnwpf.com"   Click="LinkClicked">
     visit LearnWPF.com
    </Hyperlink>
  </Paragraph>
</my:EnabledFlowDocument>
</RichTextBox>


You can download the source code here

Note: I had to explicitly set the FontFamily and FontSize on the instance of the sub-type of FlowDocument that I created to match the “default” appearance of the regular FlowDocument, so a little more work is required to make this a drop-in replacement for the regular FlowDocument.

I first saw this work-around in the MSDN forums but have subsequently discovered it has been documented elsewhere.