WinRT vs. Silverlight - Part 5 - Defining default style template

See intro blogpost here.

Here's something that's actually NOT different in Silverlight (but it's different from WPF as it has always been).
You declare your style using DefaultStyleKey. This means the code looks like this for Silverlight, WPF and Windows Runtime:

public class MyControl : Control
{
    public MyControl()
    {
#if SILVERLIGHT || NETFX_CORE
        this.DefaultStyleKey = typeof(MyControl);
#endif
    }
    static MyControl() {
#if !SILVERLIGHT && !NETFX_CORE
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(HoverControl),
            new FrameworkPropertyMetadata(
            typeof(HoverControl))); 
#endif
    }
}

Here is what IS different though: You need to set the build action of \Themes\Generic.xaml to "Content". It won't work without it.
Also note that when you add Generic.xaml to your project, it will also get added to App.Xaml. I assume this is a bug in the current release, but you will have to go and delete this entry, or it won't work.

WinRT vs. Silverlight - Part 4 - Dispatcher

See intro blogpost here.

In Silverlight and WPF you will often use the Dispatcher to return from a background thread to jump to the UI Thread. This is required when you need to update your UI, because you’re not allowed to touch the UI from anything but the UI Thread. The Dispatcher method has changed slightly in WinRT. It’s also now of type “CoreDispatcher”, instead of just “Dispatcher”.

#if !NETFX_CORE
  Dispatcher.BeginInvoke(
#else
  Dispatcher.Invoke(CoreDispatcherPriority.Normal, 
#endif
           (s, a) => { ... }
#if NETFX_CORE
      , this, null);
#endif
   );

WinRT vs. Silverlight - Part 3 - Dependency Properties

See intro blogpost here.

UPDATE Feb. 29, 2012: As hinted at below that this would happen, this blogpost on dependency properties is now outdated. Since the Consumer Preview of Windows 8 released, dependency properties now work exactly like they do in Silverlight and WPF.

---

Declaration of dependency properties has changed in the WinRT. This is a temporary change and will go away when WinRT hits beta, but still good to know if you start prototyping on WinRT today. If you are a control developer this is probably one of the things you would have to change in the most places.

Here’s what the API looks like for Silverlight and WPF for registering a Dependency Property or an Attached Property:

public static DependencyProperty Register(
      string name, 
      Type propertyType, 
      Type ownerType,
      PropertyMetadata typeMetadata);
public static DependencyProperty RegisterAttached(
      string name, 
      Type propertyType,
      Type ownerType, 
      PropertyMetadata defaultMetadata);

And here’s what this currently looks like in WinRT CTP :

public static DependencyProperty Register(
      string name, 
      string propertyTypeName, 
      string ownerTypeName,
      PropertyMetadata typeMetadata);
public static DependencyProperty RegisterAttached(
      string name, 
      string propertyTypeName,
      string ownerTypeName, 
      PropertyMetadata defaultMetadata);

Notice how the PropertyType and PropertyOwnerType is now strings instead of types!

This means you would have to write your code like this to make it cross-compile:

        public double MyDoubleProperty
        {
            get { return (double)GetValue(MyDoublePropertyProperty); }
            set { SetValue(MyDoublePropertyProperty, value); }
        }

        public static readonly DependencyProperty MyDoublePropertyProperty =
            DependencyProperty.Register("MyDoubleProperty", 
#if NETFX_CORE
             "Double", "MyNamespace.MyControl", 
#else
                typeof(double), typeof(MyNamespace.MyControl), 
#endif
                 new PropertyMetadata(0d));

Also note that you don’t use the full type name for the system types. Ie. here you use “Double” and not “double” or “System.Double”.

You could create a few static methods to replace the Register/RegisterAttached methods that will make your code cross-platform, and switch it out just there when this changes. Here’s one example how this could be accomplished (the ‘ToRTString’ method isn’t fully tested though…):

    public static DependencyProperty RegisterAttached(string name, Type propertyType, Type ownerType, PropertyMetadata metadata)
    {
        return DependencyProperty.RegisterAttached(name, 
#if NETFX_CORE
            propertyType.ToRTString(), ownerType.ToRTString()
#else
            propertyType, ownerType
#endif
            , metadata);
    }
    public static DependencyProperty Register(string name, Type propertyType, Type ownerType, PropertyMetadata metadata)
    {
        return DependencyProperty.Register(name,
#if NETFX_CORE
            propertyType.ToRTString(), ownerType.ToRTString()
#else
            propertyType, ownerType
#endif
            , metadata);
    }
#if NETFX_CORE
    private static string ToRTString(this Type type)
    {
        string name = type.FullName;
        if(name.StartsWith("System."))
            return name.Substring(7);
        else
            return name;
    }
#endif

WinRT vs. Silverlight - Part 2 - Code Namespace

See intro blogpost here.

The namespaces in WinRT has changed for all the UI related classes. Generally System.Windows has been replaced with Windows.UI.Xaml, and the rest is the same below that. If we to use the “NETFX_CORE” compiler directive that WinRT projects comes with, the typical default using statements that would compile on both Silverlight, WPF and WinRT would look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
#if !NETFX_CORE
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
#else
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Xaml.Shapes;
#endif

This is also described in greater detail here: http://msdn.microsoft.com/en-us/library/windows/apps/hh465136(v=VS.85).aspx

WinRT vs. Silverlight - Part 1 - XML Namespace

See intro blogpost here.

For the most part your XAML ports right over to WinRT. However an important change is how you register namespaces from your assemblies.

Here's how you do this in Silverlight and WPF for an assembly "MyAssembly.dll" and namespace MyAssembly.MyNamespace:

    xmlns:local="clr-namespace:MyAssembly.MyNamespace;assembly:MyAssembly"

And similar for namespaces in the same assembly as where the XAML file lives (ie MyAssembly):

    xmlns:local="clr-namespace:MyAssembly.MyNamespace"

In WinRT, you only declare the namespace (never the assembly) and instead use "using" instead of "clr-namespace":

    xmlns:local="using:MyAssembly.MyNamespace"

Unfortunately we don't have #if-def statements in XAML so you can just use compiler directives on your XAML and make it work on both platforms. So until we get that (or Microsoft reverts the above change) you are going to have to duplicate and maintain two sets of XAML. :-(

I actually do like this change, and this is probably how it should always have been, but it's a change that cause a lot of pain for developers trying to reuse their existing codebase. The benefit doesn't seem to pain (from what I understand the Windows team simply didn't like it said "clr" in there, plus they don't have the exact same concepts down in the runtime so the assembly part was left out.)

WinRT vs. Silverlight - Part 0

I recently wrote a blog post series on how to share your code between Silverlight and WPF.

With the announcements of Windows 8 at the //BUILD/ conference and the new Windows Runtime (WinRT) which can be built against using C# and XAML I thought it appropriate to start a new series on how to make your existing Silverlight/WPF code run on WinRT. I'm mostly writing this as notes to myself and hope you will also find them useful. Personally I've already found a lot of issues with porting code over. Not that there are significant changes, but the documentation is very limited at this point, and the gotchas enough to make you waste a lot of time on resolving this. Hopefully this will act as a resource to get it working for you as well. Keep an eye on this post. I'll post new links as I go along learning new things about WinRT.

Generally what I have found is that with respect to XAML WinRT is more compatible to Silverlight than WPF, so expect it easier to use your Silverlight knowledge, and don't try and use WPF XAML features at this point. Things like DataTriggers etc. are not supported, and for the most part, the UI related methods in code are more similar to Silverlight than .NET 4 (note however that non-UI code is closer to the "original" .NET, since this is essentially the same CLR and compiler used).

I won't go into too much detail about what this means for Silverlight and WPF. There's plenty of blogs and newssites that has their (over?)reactions described in detail. This series will really just focus on how to take your existing code and get it running on WinRT.

Click to select a topic below:

  1. WinRT vs. Silverlight - Part 1 - XML Namespace
  2. WinRT vs. Silverlight - Part 2 - Code Namespace
  3. WinRT vs. Silverlight - Part 3 - Dependency Properties
  4. WinRT vs. Silverlight - Part 4 - Dispatcher
  5. WinRT vs. Silverlight - Part 5 - Defining default style template
  6. WinRT vs. Silverlight - Part 6 - Using Tasks
  7. WinRT vs. Silverlight - Part 7 - Making WebRequests 
  8. WinRT vs. Silverlight - Part 8 - What other people are blogging
  9. Coming… WinRT vs. Silverlight - Part 9 - File IO
  10. Coming… WinRT vs. Silverlight - Part 10 – Various CTP bugs…
  11. More…

WPF vs. Silverlight - Part 11 - Silverlight on Phone vs. Browser

See intro blogpost here.

Well technically this is not a WPF vs Silverlight post, but a SL vs WP7, but it still kinda belongs in this series.

Generally the differences in the API’s between Browser Silverlight and Windows Phone Silverlight are pretty slim. However dealing with the phone can be quite different anyway. First there’s often less security restrictions on the phone to worry about. Secondly there’s a lot of phone specific APIs like sensor data, camera, contacts etc). The screen is also smaller so often some controls doesn’t make sense to have on the phone, or needs to have a separate layout to enhance the experience on this small touch-centric screen. Lastly (and very importantly) the small amount of memory, processing power and battery life means that performance is a concern. This often forces you to go down a slightly different avenue for your application, and for certain custom controls.

For the API differences I’m again going to be cheap and just point you to the main resource on MSDN that has some really good info on that matter:

Other notable things:

  • In Silverlight for Windows Phone, effects such as Blur and DropShadow are not supported.
  • Custom pixel shaders are not supported, so the PixelShader type is not supported.
  • Silverlight applications on Windows Phone are hosted on the client device and do not run inside of a browser. Silverlight features that are based on a browser host are not supported. These features include the HTML DOM bridge, JavaScript programmability, and the Silverlight plug-in object reference.
  • Isolated storage on Windows Phone does not enforce quotas to restrict the size of isolated storage for Silverlight-based applications. The default quota size of 1 MB does not apply. (however there’s still a 2Gb limit on Isolated Storage for WP7, or less if you run out of space).
  • Manipulation events that Silverlight doesn’t have (well technically they are there but throw a not supported exception), are the same as in WPF, so WP7 has better touch closer to WPF than Silverlight.

Next: WPF vs. Silverlight - Part 11– Silverlight on Phone vs. Browser

WPF vs. Silverlight - Part 10 - XAML Parser Differences

See intro blogpost here.

The XAML parser for WPF and Silverlight are not one and the same, and this also means that there (for whatever reason) are differences in how they interpret the xaml (as kinda hinted at in part 7).

MSDN has a pretty good description on those differences, so I won’t repeat the entire thing (please go read it!), other than point to a couple of important items:

  • Silverlight 4 introduces a XAML parser that behaves differently than Silverlight version 3 and is closer to the WPF XAML parser implementation.  Silverlight includes a XAML parser that is part of the Silverlight core install. Silverlight uses different XAML parsers depending on whether your application targets Silverlight 3 or Silverlight 4. The two parsers exist side-by-side in Silverlight 4 for compatibility. (read: You are more likely to hit issues porting an SL3 app to WPF than from SL4)
  • In some cases, the XAML parsing behavior in Silverlight differs from the parsing behavior in Windows Presentation Foundation (WPF). WPF has its own XAML parser (read: We made a new XAML parser for Silverlight, and cut some corners...)
  • Object elements inside a ResourceDictionary in Silverlight may have an x:Name instead of or in addition to an x:Key. If x:Key is not specified, the x:Name is used as the key. (read: Always use x:Key since this works in both)

Most of the other differences are things supported only in WPF, which is to be expected since Silverlight is a subset. Again this is why I recommend starting with Silverlight and then porting to WPF.

Other things worth noting:

WPF v3.5 does not have a VisualStateManager. Silverlight “invented” this and WPF 4 added it. If you build for WPF 3.5, you can use the WPFToolkit, which adds this support to 3.5.

Compiler conditionals in XAML

As demonstrated in many of the previous parts, you can use compiler conditionals in code-behind (ie. #if SILVERLIGHT...) to write code specific to the platform. Unfortunately you don’t have that luxury in XAML. If you need to have different xaml for the different platforms, I haven’t found a way around duplicating the entire piece of XAML in each project. So no, this won’t work Sad smile :

image

Next: WPF vs. Silverlight - Part 11 - Silverlight on Phone vs. Browser

WPF vs. Silverlight - Part 9 - Reusing code in Visual Studio #2

See intro blogpost here.

In the previous post, I covered how to configure your project to create both a Silverlight and a WPF build. However, I usually like to structure my control libraries slightly different, and place the theme file for a specific custom control next to the control code, instead of having an ever-growing Themes\Generic.xaml file with all the controls merged together. It makes it easier to find the theme for a specific control without having to scroll an enormous XAML file. My Silverlight project will usually look like this:

image

In Generic.xaml I instead “merge” in this file using a Merged Dictionary:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="/MyLibrary;component/Controls/TemplatedControl1.Theme.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

As you add more controls, you simply add another entry into the resource dictionary. So the next step would be to link this new TemplatedContro1.Theme.xaml file into WPF, and make your solution look like the following:

image

However, this won’t work in WPF! When you run the WPF version, the template will never get applied, because the template is never found. There seems to be a bug in WPF that the Silverlight and Windows Phone compilers doesn’t have, and it literally took me forever to find this problem: WPF doesn’t like linked resource files that isn’t located in the root of the project! The only workaround I’ve found so far is to move the TemplatedControl1.Theme.xaml to the root of the WPF project (still linked though) and create a new non-linked Generic.xaml file for WPF (since it now has to point to a different location of the theme file).

So your WPF project will instead look like this:

image

Note that the WPF\MyLibrary\Themes\Generic.xaml is no longer linked, but is a copy of the Silverlight file, with the \Controls\ part removed from the ResourceDictionary Source path.

By the way, if you followed the same steps for creating a Windows Phone 7 project, the WP7 compiler doesn’t have this problem so this workaround is specific for WPF only.

Next: WPF vs. Silverlight - Part 10 - XAML Parser Differences

WPF vs. Silverlight - Part 8 - Reusing code in Visual Studio #1

See intro blogpost here.

So now that you know several of the code differences between Silverlight and WPF, how would you set this up in Visual Studio? You could create two projects and copy the code over from one to the other, but then you would have to maintain two sets of code. There’s an easier way:

Create two new Class Library projects in VS2010. One for Silverlight and one for WPF. I recommend calling them the exact same (I know some people like to add WPF or SL to the name to distinguish them, but that forces other libraries that uses them to be different so don’t do that!). If you need one for Windows Phone 7 as well, simply repeat the steps for WPF coming later...

image

image

image

Note that VS will balk at you for naming the project the same. For now just call it for instance “MyLibrary2” or something.

Next in the solution explorer, create a Silverlight and a WPF folder, and move the projects to these. You can now rename the WPF project so it’s called the same. Also go into the project settings and remove the “2” from the assembly name and default namespace. Lastly deleted the default classes that were created for you, as well as the Generic.xaml file in WPF.

image image

OK we are all set. We have two empty projects. One for WPF and one for Silverlight.

In Silverlight add a new “Silverlight Templated Control” item. You now have a custom control in Silverlight. We could copy this to WPF, but instead we’ll link it over. Right-click WPF\MyLibrary, and select “Add existing item”. Browse to the class you added to silverlight, but DON’T click the add button. Instead click the little down-arrow next to the add button and pick “Add as link”.

image image

Repeat the same step for the Generic.xaml file.

Notice in the solution explorer that the “TemplatedControl1.cs” icon in WPF has a little arrow in the lower left corner? This means this is not really located in the WPF\MyLibrary folder, but is pointing to the file in the Silverlight folder.

Now it’s time to remember what was covered in “Part 1”. Add the following code to the new control:

    static TemplatedControl1()
    {
#if !SILVERLIGHT 
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(TemplatedControl1),
            new FrameworkPropertyMetadata(
            typeof(TemplatedControl1))); 
#endif
    }

Also put the “this.DefaultStyleKey…” in a SILVERLIGHT conditional.

Your code should now look something like this:

image

For the most part, from here on the code you write for your Silverlight control, should work in WPF. If you hit a difference between the two or want to enhance the WPF version with WPF specific features, use the conditionals as shown above.

This blogpost will continue in the next part with some interesting file-link bugs in Visual Studio you need to be aware of.

Next: WPF vs. Silverlight - Part 9 - Reusing code in Visual Studio #2