Porting WPF and Microsoft Silverlight to WinRT
[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]
If you're familiar with other XAML-based platforms such as Windows Presentation Foundation (WPF), "desktop" Microsoft Silverlight, or Windows Phone Silverlight, then you can re-use these skills to create Windows Store apps. This topic lists high-level differences you should be aware of when migrating the code and the XAML from your original WPF or Silverlight app.
Note If you are migrating a Windows Phone app that uses XAML, see Resources for Windows Phone developers.
Roadmap: How does this topic relate to others? See: Roadmap for Windows Runtime apps using C# or Visual Basic
General techniques for porting XAML and code
When you are migrating code and XAML that was previously written for another UI framework such as WPF or Silverlight, the migration steps involved are more substantial than updating between versions of the same framework, for example. Still, by using this topic to identify areas where there are API and programming model differences, you can re-use parts of your code and XAML. The best way to do this is to integrate these parts into the code and XAML structure that you get from a Microsoft Visual Studio new project template for a Windows Store app using C++, C#, or Visual Basic. That way you'll get an appropriate navigation structure for your XAML pages and the Windows Runtime namespaces included for your code-behind. If you need more XAML pages or more code, use the Add new options to start with a Windows Store app page or codefile, copy your original XAML or code as segments into the new page/file, and then do the line-level conversions as necessary.
The remaining sections of this topic cover various feature areas that are common to both the initial UI frameworks and to Windows Store apps. Read through each of these sections so that you have an overview of the differences involved and what you might do to get your migrated XAML and code working for a Windows Store app.
New design and behavior
Windows Store apps have a unique look and behavior (personality) that sets them apart from other apps, including those apps you have created using other XAML-based platforms. Be sure to take some time to learn the best practices for creating a great Windows Store app. Addressing the design aspects of creating a Windows Store app often mean that you should recompose substantial parts of your UI. In particular, how you handle dialogs, menus, input commands, lists may have to be recomposed so that you're following the design guidelines. See Make great Windows Store apps and the UX guidelines for Windows Store apps.
Application object and app model
- The application model for activation and app lifetime is different, because apps can be suspended and resumed. For more info, see Launching, resuming, and multitasking.
- The Application tag in app.xaml cannot be used to attach app lifetime events; event wiring for events such as Suspending must be done as part of startup logic in the app.xaml code-behind file.
- The Window object is less directly equivalent to a running application HWND from a Microsoft Win32 programming perspective. Some of the advanced windowing features are surfaced on a separate object, which you can get using the value of the Window.CoreWindow property.
- On the other hand, if you are coming from a Silverlight app perspective, you no longer have the browser host as an intermediate programming boundary: your Windows Store app is running directly in the Windows Runtime. This simplifies things by taking away browser hosting issues that Silverlight had to work within, such as input handling going through a program access layer, limited storage access, and an Internet-centric security and caching model.
- Silverlight apps could either package application parts into the deployment package, as external parts, or download components on demand. A Windows Store app has these choices too, but the APIs used to access the package parts are different. Where Silverlight uses Application.GetResourceStream, a Windows Store app uses a more generalized model, where the installed package is just a storage folder. For example, you can get the Package.InstalledLocation property value and then call a variety of StorageFolder APIs (most of which are asynchronous) in order to get any other packaged components. For more info, see Creating and retrieving resources in Windows Store apps.
- The Windows Runtime app model uses a capability concept. You must declare a capability as part of your development and deployment process, and a user can see in the Windows Store UI that your app has requested a particular capability. You might need to request capabilities to access library storage for a user, to use webcam APIs, and so on. For certain code that worked before in Silverlight and WPF, even if you have the code converted correctly at a syntax level, you might still need to request a Windows Runtime capability in order to access that code. For more info, see App capability declarations.
- Launching an app directly from a tile is not the only way a Windows Store app might be activated. For example your app might support being launched by file associations, by a Play To contract, and so on. You should plan for this by persisting app state as app data, and making sure that your app has all the data it needs for startup in all possible activation scenarios. For more info see How to activate an app and other topics in Launching, resuming, and multitasking.
.NET programming and type projection
The architecture of the Windows Runtime is based on the principle that developers can use different languages to access the same underlying Windows Runtime functionality and concepts. One aspect of how different languages can each program against Windows Runtime and still preserve characteristics or patterns of the language is type projection. In the case of Microsoft .NET languages, developers for those languages are familiar with the .NET type system and with the primitives, types and concepts implemented by the .NET mscorlib assembly.
There is a list of types that are specifically projected for .NET when programming for the Windows Runtime. These types exist either in the mscorlib assembly and System namespace, or are specifically added to one of the WindowsRuntime assemblies that are included as .NET reference assemblies for Windows Runtime programming.
Common collection interfaces project as the collection interfaces that are familiar to .NET programmers. IVector<T> projects as IList<T>. IMap<K,V> projects as IDictionary<TKey,TValue>. Enumerable types support foreach syntax and related extension methods through System.Linq. Related view classes and read-only variants have similar projections. Through these projections, any Windows Runtime class that implements a collection interface can support the API of the projected .NET collection interface.
Common "primitives" project as the mscorlib/System type that developers are familiar with from .NET programming. For example any app code involving a double value can use the API supplied for System.Double when programming with a .NET language.
.NET APIs that interact with the type system can reference the .NET System.Type, and you can use the typeof operator in Windows Runtime code. (Note: If you're doing interop or otherwise using C++ for some of your code, C++ has a typeid operator, but it's limited in comparison to typeof.)
HResult projects as System.Exception for .NET. There is also support for extracting the message info from a Windows Runtime error on per-API basis, and providing a .NET developer with an appropriate typed exception that is based on System.Exception. You can use try-catch and similar techniques for your exception handling, and can handle many of the standard .NET exceptions you're familiar with already. For more info, see Exception handling for Windows Runtime apps in C# or Visual Basic.
ICommand patterns use the .NET definition (System.Windows.Input.ICommand).
The interfaces that you used for binding-aware business objects written in .NET translate across when you use the object as a Windows Runtime data source. For example, a binding can respond to PropertyChanged or CollectionChanged as implemented on a business object class that was originally written for WPF or Silverlight.
Many of the structures that are commonly used as value types for XAML UI programming are projected as structures that have utility methods available. These structures have the same name and namespace location, but reference into a WindowsRuntime assembly so that the utility methods are supported for .NET. For example, .NET programmers can use utility API of Matrix3D such as HasInverse, or the built-in operators. (C++/CX also has some utility support for its structures, also implemented as a projection, but that support is more limited.)
A related concept is that once a type is projected as a .NET type, it can support .NET extension methods. This enables .NET extension methods that are specifically intended for Windows Store app programming. For example, an existing .NET type such as StreamReader can support methods that use async patterns similar to those in Windows.Storage APIs.
The base type for all runtime objects appears as System.Object, and has the expected System.Object API such as ToString. However, there are some slight differences in the implementations of those methods when they run in the Windows Runtime. These differences are often called out in the .NET reference documentation, in a Notes for the Windows Runtime section.
Note Type projections are intended to aid with your XAML and code migration scenarios, particularly when you are migrating the code-behind for XAML pages, business objects, or self-contained logic classes. For the most part you won't have to investigate whether a type from your original code is really a projected type in the Windows Runtime. The compilers and project templates will do the right thing for you.
When you use types that are projected, you still might need namespace references for cases where the projections are there for runtime support, but are not part of the .NET core framework libraries and not defined in existing .NET namespaces like System.Collections.Generic. For example, if you have C# code that uses the Point structure, you'll still need a using statement that references the Windows.Foundation namespace, because that's how the projected Point is defined too.
For more info on .NET and Windows Store app using C++, C#, or Visual Basic programming, see .NET for Windows Store apps overview.
General programming model
- If you are not programming with a .NET language, and are instead programming using Visual C++ component extensions (C++/CX), many structures have a basic C-style definition that doesn't support non-data members.
- The programming model has integrated syntax for asynchronous operations. Asynchronous operations are more prevalent in the programming model than they were for WPF or Silverlight. The intent of the async APIs is to reinforce patterns that make it harder to inadvertently block the UI thread in an event handler or callback. For more info, see Quickstart: Calling asynchronous APIs in C# or Visual Basic.
- Because of async patterns or other background tasks that aren't on the UI thread, you might have a need to make calls from other threads that eventually update the UI thread, asynchronously. The API you use to get across threads (usually from a background thread to the UI thread) is the same as in Silverlight, DependencyObject.Dispatcher.
- File and storage access that might have been done with mscorlib and system assembly APIs are now done with dedicated system API such as StorageFile.
- If you are programming using a .NET language, then you can also use existing System.IO.Stream-based logic. You can access extension methods that return a stream from similar Windows Runtime types, such as calling the AsStream extension method on a IRandomAccessStream instance. In a code editor, the System.IO.Stream API will appear as options in the Microsoft IntelliSense dropdowns whenever you have Stream instances as obtained from related stream/buffer types.
The Silverlight navigation model used XAML pages, either loose or in the package, as the basis for targeting the content to navigate to. Windows Store apps use types, and in particular the type that is indicated as the x:Class for a XAML page. A good plan would be to use the Add New functionality from Solution Explorer to create new XAML pages within the Windows Store app project template of your choosing. Import the elements below the root level of the original Silverlight page, and work through any further conversion issues that may exist. Then build up your navigation structure using a Frame on the main page. Alternatively, create a new project using the Grid App or Split App templates; these include pages that already have a navigation framework, plus view state templates and suspend/resume logic. You could also use the Hub App template and navigation strategy. For more info, see Part 3: Navigation, layout, and views or Adding a Page control.
The Windows Runtime has Page and Frame classes in the default control set, whereas in Silverlight these came from the SDK libraries and had to be distributed. If you're migrating XAML that contains a Page or a Frame, you can remove the "sdk:" prefix from elements and the xmlns mapping for the "sdk:" prefix. Pages can override OnNavigatedTo or OnNavigatedFrom if pages need to do any cleanup during a navigation action. But there are also events and overrides available on the Frame class, for example Navigated, so you might consider putting your navigation logic into the Frame rather that individual pages. Also, where the Silverlight Frame had simple navigation buttons in its control template, the Windows Runtime navigation features are integrated with the page templates and use dedicated styles and templates for the buttons themselves. For more info see Quickstart: Navigating between pages.
Tiles and notifications
Tile and notification features had varying levels of support in previous XAML frameworks, so there's no general recipe for how to convert these. For more info on how these features work in a Windows Store app, see Working with tiles, badges, and toast notifications. If your app uses Windows Phone push notifications, see Resources for Windows Phone developers.
Using the .NET Framework
For Windows Store apps that use .NET languages (C# or Microsoft Visual Basic), the .NET Framework APIs that you call are part of a particular .NET Framework profile. This relationship is explained in detail in the topic .NET for Windows Store apps overview.
XAML language capabilities
XAML for Windows Runtime is a very close match to XAML for Silverlight as far as the capabilities that are part of the XAML language itself, and also a close match to XAML for WPF. But there are a few differences.
- Instead of using a clr-namespace:/assembly= qualifier set for code-to-XAML namespace references, you use the using: qualifier. XAML namespaces no longer reference specific assemblies; all assembly qualification and inclusion is handled by the application model and how you compose your app package.
- Because you cannot map specific assemblies, some of the references that were made to mscorlib to support common language runtime (CLR) primitives will no longer work. Instead, you can use the XAML language intrinsic types such as x:String. For more info, see XAML intrinsic data types. Also, consider that many of the strings that you stored before as x:String in a ResourceDictionary might better be stored as a string in a resources file for the project. For more info see Globalizing your app.
- XAML for Windows Runtime doesn't support custom markup extensions.
- In rare cases, XAML where a non-prefixed Name attribute was acceptable in Silverlight may require an x:Name attribute instead.
- Some cases where an overqualified Setter.Property worked for Silverlight XAML won't work with Windows Runtime XAML. Most Setter.Property values should just be the simple name of the dependency property, and not attempt to qualify its owner (attached properties are the exception, you should still owner-qualify those.)
- If you're migrating XAML from WPF, there are constructs that XAML for the Windows Runtime doesn't support in addition to the Silverlight XAML differences already listed. These include: DynamicResource markup extension (and the underlying resource lookup behavior), x:ClassModifier and x:Subclass, x:Array and related XAML 2009 generics support, x:Code, x:Static, x:Type used explicitly (there is implicit x:Type evaluation for properties that need it), VisualTree nodes in templates, and some other minor differences. You should be able to trap any XAML compatibility issues in the design phase, based on XAML parse exceptions.
Touch and input
- There are no mouse-specific input events such as MouseLeftButtonDown. These events along with touch-input specific events are unified under Pointer events. In most cases you can convert the relevant mouse event to PointerPressed, PointerReleased, PointerEntered or PointerExited. For more info, see Responding to user interaction. For MouseWheel, use the PointerWheelChanged event. The wheel delta can be found in the PointerPointProperties on the primary PointerPoint from event data.
- If you were handling raw manipulations to enable actions in controls, and you created visual states for your manipulation handling, you should verify that the controls you're using don't already have built-in manipulation or gesture support. For example the Windows Runtime ListBox has several interactions enabled already as theme transitions.
- For interactions in general, consider handling the gesture events rather than the pointer events, because it's usually easier. For example Tapped is often a better event under the Windows Runtime event model for interactions that would have been handled by a mouse-specific event in Silverlight.
- Specific touch interactions can be enabled or disabled on a per-element basis, using properties. For example, you can set IsRightTapEnabled to false, and that element will not originate a RightTapped event. This is intended to avoid possible problems with gesture and manipulation recognition when events bubble through a control composition visual tree.
- Keys for key events do not have a PlatformKeyCode / Key separation. The reported key from event data uses a different enumeration, VirtualKey, and other key event data is available as KeyStatus.
- Pointer capture from UIElement can capture multiple pointers, to support touch manipulations that initiate capture. To get the correct pointer reference, use a pointer-related event data class such as PointerRoutedEventArgs.
- Calls to Control.Focus should specify an enumeration value that states that the focus action was programmatic. The Windows Runtime separates the focus calls because its visual states use different behavior for programmatic focus calls. You may have to add new custom visual states for non-keyboard focus to your templates.
- Certain Windows Runtime controls have built-in manipulation handling. For example a ScrollViewer handles scroll, pan and zoom interactions internally so that the control gives the appropriate action response. The control's handling might prevent lower-level pointer events from being fired. You can call CancelDirectManipulations to override this behavior. But you might also want to review the input handling on your controls overall. A built-in behavior might already cover your scenario, in which case a pointer-level handler isn't needed anymore.
Graphics and element layout/composition
- In order to best optimize the element set for the capabilities of the new graphics stack, we cut some APIs/concepts that would slow down rendering. Examples include OpacityMask, non-rectangular clips, custom easing functions, and bitmap effects.
- VideoBrush is not supported in the Windows Runtime, nor is RadialGradientBrush.
- The Windows Runtime imaging API has a different and more capable underlying imaging component, the Windows Imaging Component (WIC). The good news for you is that this component supports more image source formats than did Silverlight or even WPF. You also have easy-to-use encoder and decoder types available, and some additional API for image manipulation that's already built-in to the WIC. For more info, see the Windows.Graphics.Imaging namespace.
- BitmapCache has different underlying logic than it did in Silverlight, Silverlight for Windows Phone, or WPF. Also, bitmap caching can have an interrelationship with animations and might cause some animations to be considered dependent. If you're using UIElement.CacheMode at all, you should re-profile your app and revisit whether using a UIElement.CacheMode setting for some of your UI is a performance gain for a Windows Store app. For more info, see UIElement.CacheMode and DebugSettings.IsOverdrawHeatMapEnabled.
- For some scenarios where you used a WriteableBitmap, you might want to use RenderTargetBitmap instead.
- Windows Store apps and other frameworks that use XAML for UI definition have the same basic controls such as Button and ListBox, and basic layout containers such as Border, Grid and StackPanel. The Windows Runtime also has many collection-ready controls such as SemanticZoom and FlipView. Additionally, the GridView is a stand-alone control instead of a component that is used in a ListView, with the only real difference between GridView andListView being the dominant orientation of presented items that each uses. For more info, see Controls by function.
- Although you can often use the same control you used in your original Silverlight or WPF app and perhaps even an entire UI can be migrated over to equivalent components, that's not always the best approach. It's particularly when defining your app's UI where you may want to stop and review the Windows Store app design guidance again. For example, your original app and the controls in its UI might not have been designed for touch first, whereas your Windows Store app should be designed for touch first. The overall UI experience is also going to be different because you're no longer browser-hosted. For more info on design, see Designing UX for apps. For more info on UX guidelines for controls, see the Index of UX guidelines.
Animations, transitions, visual states, styles
- The Windows Runtime adds the concept of a personality animations. These can be used in XAML as transition animations and theme animations applied directly to UI elements without needing to target multiple properties of that element. Storyboarded animations work nearly identically. However, not all storyboarded animations are enabled by default. Disabling dependent animations by default is intended to make developers more aware of the performance costs of animations that would significantly impact the main UI thread. If your animation isn't running as expected, try setting EnableDependentAnimations to true. However, do this judiciously, because running dependent animations has a performance cost. For more info, see Animating your UI, Storyboarded animations, and Make animations smooth.
- If you have any "vsm:" prefixes in your visual state XAML definitions, remove the prefix usages and the prefix definition. You no longer need to map visual state prefixes and namespaces separately.
- If you are converting visual states, make sure to convert the "Mouse" concepts over to "Pointer" concepts, like you changed over item-level event handling. You may want to rename the visual state names themselves as well as adjusting which properties are changed by the state. Have a look at the existing XAML resource dictionaries such as generic.xaml in the include/winrt/xaml/design subfolder of a Windows SDK installation. These might suggest some patterns you can follow for visual states and the related events.
- If you already have an existing high-contrast theme for a custom control that you've converted, make sure to follow the ThemeDictionaries model for how you connect the themes to the control definition. In particular, you probably want to support the named themes identified in the HighContrastScheme enumeration. For more info see XAML high contrast style sample.
- You should support both a light and dark theme template for your controls if your app enables theme switching. The default templates have these, but you may need to add a theme to any custom templates you imported.
- WPF and Silverlight supported the ability to use a Binding expression to supply the Value for a Setter in a Style. The Windows Runtime doesn't support a Binding usage for Setter.Value (the Binding won't evaluate and the Setter has no effect, you won't get errors, but you won't get the desired result either). When you convert XAML styles from WPF or Silverlight XAML, replace any Binding expression usages with strings or objects that set values, or refactor the values as shared StaticResource values rather than Binding-obtained values.
The media APIs are similar, but how Digital Rights Management (DRM) integrates with the media APIs is different. Unlike in Silverlight, Windows has a pluggable DRM model and PlayReady is one of possibly several that would be supported, so the APIs are different to account for a content protection manager.
MediaElement is largely the same, although you probably want to define a new XAML template for any previous MediaElement transport control templates, to make the UI touch-aware. Or you can use AreTransportControlsEnabled to get some default transport controls. Notable Windows Runtime additions to the MediaElement API are that you can have a "poster" for loading, detect and use stereo video packing modes, and add video effects.
Camera capture is conceptually different between the platforms, you'll be rewriting code rather than converting code if you have this feature. For more info see How to preview video from a webcam and Media capture using capture device sample. You'll probably be using a CaptureElement as the display surface, because VideoBrush isn't available.
Uniform Resource Identifier (URI) handling for file references works a little differently in Windows Runtime. Relative URIs are not supported, at least not at the level of the pure URI types. The .NET System.Uri might appear to give you a RelativeOrAbsolute choice in certain API calls, but in practice all such URIs are absolute, and are evaluated against concepts and locations such as the app package, user-selected locations, app data, and so on.
Any property value that takes a URI may have to be examined. You can't use file: scheme URIs. It's possible that you can bring across XAML with URI references to values such as Image.Source files without worrying about URI issues at all, and have it work as new Windows UI. But this depends on how your original app was structured. When specified in XAML, a URI often appears to be a relative URI, but these strings are processed and completed by the XAML parser before setting any properties at run time. To reproduce this same behavior in code-behind, use the FrameworkElement.BaseUri return as the baseUri parameter value in the Uri constructor that combines a base URI with a relative URI. For more info, see Defining app resources.
File and storage APIs
The techniques you use to access files and storage in the Windows Runtime are quite different than those in .NET, particularly since many of these APIs use an asynchronous pattern and async/await keywords. For more info, see Accessing data and files.
XML and XMLDOM
The area of .NET available to a Windows Store app using C++, C#, or Visual Basic doesn't include some of the XML DOM API from the framework, or forwards some of the base types to the Linq namespace. Look for similar APIs in Windows.Data.Xml.Dom and System.Xml.Linq.
Hosted and side-by-side HTML
Generally speaking, converting an entire project is best done by starting with one of the existing project templates for a Windows Store app. Then, use existing Add functionality in Solution Explorer to introduce either new or existing XAML pages and code-behind files. Finally, migrate specific blocks of code into the XAML and code files. If you do it this way, you can avoid the previous framework's implementation details and infrastructure for projects and builds that might be there accidentally. You can use the using/Imports statements with the correct "Windows" namespaces, reference the current build types, and access the .resw resources system, because all of these will be available from newly templated projects and pages.
If your Silverlight project used the Binding-based localization system as documented in the topic How to: Make XAML Content Localizable, you should consider changing the localization technique over to using strings that are declared in the package resource index (PRI) system. Binding-based localization system will still work, but it doesn't have nearly the tooling support that's possible with PRI and .resw files both within Visual Studio and for any dedicated localization processes or tools that are based on the Visual Studio localization methodology.
If you choose to attempt to bring over whole code files, you can often search and replace either using/Imports statements or fully qualified references. For example "System.Windows" should be replaced with "Windows.UI.Xaml". There are a few outliers to this general rule of how Silverlight/WPF types relate to the Windows Runtime types and namespaces, and we'll note these cases in the API documentation (in Remarks).
For more info on project templates, see C#, VB, and C++ project templates for Windows Store apps.
More resources for migrating apps
- If you have specific .NET code calls that you aren't sure will work in Windows Runtime, see .NET for Windows Store apps - supported APIs
- For more info on other migration scenarios specifically for Silverlight for Windows Phone, see Resources for Windows Phone developers.
- As a top-level document view for creating Windows Store apps using C++, C#, or Visual Basic in general, see Roadmap for Windows Store apps using C# or Visual Basic.
Resources for Windows Phone developers