Windows Presentation Foundation or WPF is one of the few things of the Windows Vista era that has survived, or that people actually use and enjoy. It was originally called Avalon and was the first step away from GDI32 WinForms based developing which was becoming more and more difficult to create rich engaging applications.

WPF used a XML based UI markup called XAML, with a C# code behind.

Roll on 2015 and the Microsoft Build Conference, with Windows 10 and Microsoft hopes to evolve WPF. Microsoft’s long term plan is to unify Silverlight, WPF to Big Windows, Windows Phone development and all XAML based development under the banner of Windows Universal Apps (WUA).

This means one app could potentially run on Windows 10 Phone, Windows 10 IoT and full Windows 10. The notes below were taken while I was porting a WPF application running on an Intel Core I7 to a Raspberry Pi 2 running the Windows 10 IoT stack. Yep that’s right, having an app previously needing an i7 running on a £30 Raspberry Pi.

This is all great news, apart from the glaring problem. Not all devices are created equal, different devices have different performance characteristics and different accessories e.g. Your PC may not have a GSM module, and your phone doesn’t have a mouse.

So Microsoft had to comprise and refactor most of the System .NET library and the core Xaml libraries.

This post goes through some of the issues and challenges I have encountered while porting a Windows desktop based WPF application to a Universal App. Not all the changes here are solely related to WUA but in general changes to the Windows Universal libraries.

Reference, Library and Using Changes

The refactoring of the core libraries has pushed most of the XAML and UI libraries to the Windows.UI namespace.

Note: What would have been System.Windows.Forms is now Windows.UI.Xaml.Controls

XAML and Graphics differences

The Visual Class is stored under Windows.UI.Composition

The Visibility Enum Windows.UI.Xaml.Visibility no longer has a Hidden property, replace with Collapsed.

Note: that this removes it from the render tree and so can cause lag when re-rendering.

Can’t set a FrameRate via DesiredFrameRateProperty on a TimeLine.

Note: Manual control of timeline and animation properties may be required, apps may use more CPU as they could run at a default FPS of the platform (usually 60 FPS.)

Pre-cached SolidColorBrushes (Brushes) doesn’t exist for each colour, they have to be created manually through the SolidColorBrush constructor with a Colour.

StreamGeometry is not supported, the closest variant is PathGeometry or just Path. <StreamGeometry>…</StreamGeometry> becomes <PathGeometry Figures=”…” /> Another way is to convert it to a Path object with the figures being the Path.Data. This could be stored as a Static resource and then referenced via a ContentControl binding {Binding Source={StaticResource=…}}

OpacityMask does not exist. Thus semi transparent controls could be achieved via use of transparent imagebrush, layering shapes or background image (PNG) with transparencies

EnableClearType is not supported as an attribute to BitmapCache User Control CacheModes. Text may not appear correctly if cache resolution is too small.

Assets can not be frozen in graphics memory.

Note: This is due to memory constraints on mobile devices. This is now all done dynamically. Developers will need to make sure that assets are still responsive.

VisualBrush is not supported, you can clone an image via ImageBrush however it is undetermined yet whether this can render video.

The Media.Effects namespace has been removed, DropShadows could be achieved via shadow image, interoping to Direct2D or clever use of brushes.

Note: Pixel Shader effects can not be used in their current form unless using DirectX.

UIElement.Clip in the Windows Runtime API must be a RectangleGeometry. WPF and Silverlight allowed complex non-rectangular shapes via PathGeometry.

FindResource(…) Resource Dictionary Helper function has been removed, either use This.Resources[…] or App.Current.Resources[…]

Animation Differences

DiscreteBooleanKeyFrame has been removed, it is now replaced with a more generic DiscreteObjectKeyFrame to allow users to set object values at discrete points during an animation.

SetTargetPropertyPath now uses a direct string path for the property rather than a PropertyPath Class

Threading Differences

Windows.Thread does not exist, you have to use the ThreadPool or Tasks. This can cause issues with the Dispatcher or accessing the current thread.

As Threading and as such WaitCallBack is not supported, you can use WorkItemHandler to queue items for invocation.

.Net has shifted over to the async and await concept with a lot of the new refactored libraries taking advantage of this new technique, this can cause issues with old code (e.g. file access). Below is an example of how to (crudely) wrap a dispatcher call into a new task to allow UI updates.

Note: Now they normally are EventHandler<object> rather than having an EventArgs

Routed Event Handlers can also now handle already handled events. The default behaviour for porting would be AddHandler(, , false)

Note: Custom Routed Event Handlers aren’t in general supported in Windows.UI.Xaml and should be carefully thought about before implementation

Compilation Issues ( MakePRI warning 0xdef00520 )

During the development of the original application we found that the built in multiple language support didn’t work how we wanted it so we stored resource dictionaries for each supported language with the language prefix on the end. e.g. StringResources.ar-AR.xaml

Your email address will not be published. Required fields are marked *

Search

Search for:

Software Engineer. Tea Drinker.

To those that say you can not change the world with source code, I say you are not trying hard enough.

My name is Kevin Pfister, I am currently employed as a Software Engineer specializing in Embedded Solutions after finishing my Software Engineering degree at York. I was an Academic Developer Evanglist at Microsoft, World renowned author and a world-wide finalist in the Imagine Cup developer competition in both 2010 and 2011