goodbye, battleship grey


Why does the OpenFileDialog in WPF look so “1999” and how can I fix it?

Just Because Prince Wanted to Party Like it was 1999 Doesn’t Mean Your App Should

If you’ve ever used WPF’s OpenFileDialog control you have probably noticed that its appearance leaves a great deal to be desired. In particular the blocky, low res icons in the toolbar to the upper right, and the chiselled “classic” looking Open and Cancel buttons and File Name and File Type combo boxes at the bottom of the screen look out of place, especially on Windows Vista.

WPF OpenFileDialog on Vista

In contrast here is the appearance of the OpenFileDialog in Windows Forms 2.0 on Vista (shown below). The blocky icons have been replaced with something much nicer, and the buttons and dropdown combo boxes are displayed using the correct windows theme:

WinForms OpenFileDialog on Vista

The default Windows Forms project template in Visual Studio 2005 includes a call to Application.EnableVisualStyles() which causes controls to adopt the “visual style” of the OS. Removing this call makes windows forms OpenFileDialog look the same as the WPF one – in short, it seems like this is a theme-related issue in a “pure” WPF application!

Microsoftie Bombay Boy (probably not his real name) explains how to work around this in WPF Clickonce applications by including an entry in the application manifest file. This was the way of creating “theme aware” Windows Forms applications for XP in .NET Framework 1.0. In framework 1.1 the EnableVisualStyles method mentioned above was added to the Windows Forms Application object. Although this entry suggests calling EnableVisualStyles as a way of getting around theme-related issues in WPF/WinForms composite apps it does not seem to fix the themeing issues with the OpenFileDialog. EnableVisualStyles seems to have been implicated in a number of subtle bugs also, so the manifest route may be the most robust approach regardless.

What about XBAP applications?

Fortunately since they are hosted inside IE (which essentially has something equivalent to what is in the manifest file, requiring the theme-aware MS Common Controls v6 instead of v5) there is nothing that needs to be done for them to get a more modern-looking OpenFileDialog.

What About Vista?

Although being able to change the appearance of the OpenFileDialog to give it a more modern appearance is a step in the right direction the current OpenFileDialog for both Windows Forms and WPF leave a great deal to be desired on Vista. For Vista, Microsoft made a number of improvements to this “common” dialog control to make it more like a miniature version of Windows Explorer (which also received numerous improvements). Compare and contrast the WPF and WinForms dialogs above to the following OpenFileDialog from none other than Notepad which uses the "system" OpenFileDialog on Vista.

Vista System OpenFileDialog

The easiest way to get this open file dialog for your WPF applications running on Vista is to use the sample code provided with the windows SDK as part of the “Vista Bridge” sample – which is in the Cross Technology Samples zip file, which is installed by default to here: C:\Program Files\Microsoft SDKs\Windows\v6.0\Samples\. The VistaBridgeLibrary project includes a CommonOpenFileDialog control which has an API similar to WPF’s built-in Microsoft.Win32.OpenFileDialog, it’s not quite a drop-in replacement but is fairly easy to use and also exposes some of the newer features of this dialog. The catch is that since this is a wrapper around un-managed API calls it will only be available to programs running with full trust (so NOT XBAPs).The Vista Bridge also contains a number of other interesting wrappers around un-managed parts of Vista and should be the first port of call for managed code developers looking to gain access to features of Vista if they are having difficulty.

I think it is a great shame that WPF, a platform that was developed primarily for Vista, could not provide built-in access to the system file dialogs. I hope the WPF team consider addressing this issue in the next release.

WPF & Composite Application Block (CAB)

Although the patterns and practices team talked vaguely about porting the Composite UI Application Block (CAB) to WPF, and about CAB being the correct architectural choice to leverage WPF in the future they are yet to release any working code. Fortunately there now seems to be a project on CodePlex devoted to just this - nice work Kent. In addition, it seems the open-source WPF media player Crescendo also includes a WPF CAB implementation.

Expression Blend Beta 1 and Design Dec CTP Released

New versions of Microsoft's two forthcoming WPF-centric "designer" producst from the expression range were relesed yesterday. Expression Blend (formerly known as Expression Interactive Designer, formerly known as Sparkle) is a Xaml design tool focused towards graphic and interaction designers. Yesterday's release is the first beta version of this product. Expression Design (formerly known as Acrylic) is a graphic design tool for creating vector and bitmap assets. It is primarily of interest to WPF aficionados due to its Xaml export capabilities. This is the December CTP of Expression Design.

First WPF/E CTP Released

The December 2006 CTP of WPF/E, a subset of WPF that can be downloaded as a ~1MB browser plug-in and will run in the browser was released yesterday for Windows and Mac OSX. Also released was an accompanying SDK. WPF/E (codenamed Jolt) was announced at the Mix06 conference and was scheduled for a first public release late this year. Kudos to the team for getting it out. Scott Guthrie has more details here, or you can visit the WPF/E developer center. Shawn Burke of atlas toolkit fame has a toolkit extender to simplify the inclusion of the right WPF/E client-side stuff. One notable omission from this release seems to be CLR support. One of the ambitious features touted for inclusion with WPF/E was a subset of the CLR, but as Doug notes it seems to be missing from this release.

.NET Framework 3.0 RTM

.NET Framework 3.0 (the delivery vehicle for WPF) has been officially released. Congratulations to all the designers, developers, testers, program managers and technical writers who worked on this release. It is now up to the development community to build something cool with it. You can download the installer and the associated SDK and visual studio extensions. Note: although WPF and .NET Framework 3.0 has been officially released this is the November CTP of the Visual Studio designer and project templates for WPF not the final release.

Getting WPF applications to display appropriately under the new XP Zune Theme

Microsoft recently released a new theme for Windows XP to promote the new Zune media player. Unfortunately the WPF team did not create a suite of control styles for this theme. As a result WPF controls running under the Zune theme are rendered using the Windows-9x era "classic" style. Fortunately controls under the Zune theme are quite similar to the "metallic" windows XP theme. Using reflection as shown in this sample application it is possible to fake out WPF to make them think they are running under a different theme.

WPF application running under Zune theme, with metallic control styles

[disclaimer] This code needs to run while the application is loading. It uses reflection and native inter-op, and thus is unsuited to XBAP applications or other lower-trust environments. Handling theme changes while the application is running is left as an exercise for the reader.

A nice introduction to WPF styles from Gill Cleeren and MS Belgium

WPF enthusiast Gill Cleeren emailed me recently to let me know about his article on WPF Styles and Triggers that recently went live on the MSDN Belgium site. It provides an excellent starting point for those starting out with styles, and shows enough code to be useful without being overwhelming.

Also noteworthy from MSDN Belgium last year was Jelle Druyts' article on WPF Commands.

New icon for Xaml files in Sept 2006 CTP

Xaml files in the latest (Sept 2006) CTP have a new icon - a kind of 3-D blue cube between a pair of angle brackets, which replaces the old avalon shield.

New Xaml Icon

When I set a property in code after it has been animated it doesn’t work. What is going on?

WPF’s animation system is used for changing properties such as width, position or color of an element over time. When animations finish they can either return the property being animated to its original value, or “hold” their final value. This behavior is controlled by the FillBehavior property of the animation. After animating properties where the animation holds the final value developers can run into problems when they try to change those very same properties via code. The changes seem to have no effect!

This strange behavior is a side-effect of the WPF dependency property system.  The dependency property system is a special property system built by the WPF team. It allows element properties to be inherited from their container element, animated, data bound and set via regular .NET code. One side-effect of this kind of property system is that a single property on an element could get its value from a number of potential sources.  In the regular .NET property system property changes are fairly transparent, with more recent changes over-writing previous ones. The more declarative nature of WPF makes this temporal-based property system less useful. Instead the value an element property has is based on a precedence system which is detailed here. Animations have a higher precedence than everything else, so changes made by them always over-ride other possible property values. While this seems sensible and in most cases gives us the outcome we would expect it can be a little confusing for animations that hold their value after they complete. When the animation ends it holds the property at a certain value, and because animations takes precedence over other ways properties can be set it prevents the property being changed through normal .NET code.

It is possible to change this using a little code to remove the animation when it completes, however a better approach is to not use the HoldEnd fill behavior if you need to subsequently change a value in code. Instead you should use the Stop FillBehavior and “fake” the HoldEnd by handling the completed event for the animation and setting the property value to the value you wish to finish at.

The following code shows a text block that has its FontSize animated to 35 pixels when it loads.

<TextBlock Grid.Row="0" Text="WPF is great" FontFamily="Lucida Sans" Foreground="#feca00" HorizontalAlignment="Center" Name="windowHeading">
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Name="windowHeadingStoryboard">
          <DoubleAnimation To="35" Storyboard.TargetName="windowHeading"
         Storyboard.TargetProperty="FontSize" Duration="0:0:5"
         Completed="FinishedAnimation" FillBehavior="Stop" />


The very simple C# code to simulate the HoldEnd behavior is shown here in the Completed event handler for the animation.

void FinishedAnimation(object sender, EventArgs e)
    windowHeading.FontSize = 35;

The obvious drawback with this approach is the fairly tight coupling between the markup and application code that is required for it to work.

How can I create a “wipe” effect to transition between two images in WPF?

In film editing a “wipe” is a technique for transitioning from one scene to another. We can create a similar effect in WPF by overlapping two items (for instance by placing them both in a single-cell grid) and specifying a LinearGradientBrush as the OpacityMask on the top-most item.  Then by animating the Offset property of the GradientStops of the brush we can create the wipe effect. By modifying the start time of the second DoubleAnimation you can modify the width of the “in-between” area.  An earlier start-time will give a narrower region that shows pieces of both items.

Xaml Code (RC1)
<Window x:Class="LearnWPF.WipeEffect.Window1"
    Title="LearnWPF.WipeEffect" Height="500" Width="700" Name="mainWindow"
      <Image Source="Images/UFO.jpg" />
      <Image Source="Images/ladder.jpg">
          <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
              <GradientStop Offset="0" Color="Black" x:Name="BlackStop"/>
              <GradientStop Offset="0" Color="Transparent" x:Name="TransparentStop"/>
    <EventTrigger RoutedEvent="Window.Loaded">
            <DoubleAnimation Storyboard.TargetName="TransparentStop"
                             Storyboard.TargetProperty="Offset" By="1"  Duration="0:0:2"   />
            <DoubleAnimation Storyboard.TargetName="BlackStop"
                             Storyboard.TargetProperty="Offset" By="1" Duration="0:0:2"
                             BeginTime="0:0:0.05" />


A BeginTime of 50ms for the second animation produces a "tighter" wipe A BeginTime of 1 second for the second animation produces a more gradual transition
earlier start time on second animation Longer begin time