Tuesday, May 29, 2012

RadChart for Windows 8 WinRT – Taking its First Breath

This is part three of the RadChart for WinRT blog series. For more information please refer to the other parts of the series:
Part one - A Prelude
Part two - The Compilation

Okay, we have already compiled our Windows Phone Chart under WinRT (refer to the previous post). The whole process went pretty straightforward and took less than an hour. Now, let’s move on with setting-up a demo project with a simple chart in it to verify the compilation and to check for some hidden exceptions. The steps are well familiar: File->New Project->Visual C#->Windows Metro Style->Application. Adding the reference to our freshly compiled chart and declaring it in XAML:
<UserControl x:Class="RadChartDemo.MainPage"
    xmlns:telerikChart="using:Telerik.Windows.Controls"
    mc:Ignorable="d"
    d:DesignHeight="768" d:DesignWidth="1366">
     
    <Grid x:Name="LayoutRoot">
      <telerikChart:RadCartesianChart>
      </telerikChart:RadCartesianChart>
    </Grid>
     
</UserControl>
Running the project (fingers crossed), eager to see if everything is OK. Unfortunately no – we get our first exception:
An exception of type 'Windows.UI.Xaml.Markup.XamlParseException' occurred in RadChartDemo.exe but was not handled in user code.
Additional information: The type 'RadCartesianChart' was not found. [Line: 11 Position: 38].
Hmm, suspicious, everything looks properly set-up. Double-checking the XAML and the namespaces – they are fine. Starting the app again, hoping this was a sporadic :) exception. Well, the problem is still here and it is definitely not sporadic. Trying to find some hints about this in the internet but to no avail – WinRT is alive for literally several days and not much information is available. Fine, no problem – will create the chart in code and add it to the layout root.
RadCartesianChart chart = new RadCartesianChart();
this.LayoutRoot.Children.Add(chart);
Pressing F5 again to see what happens. Visual Studio now complains with another exception, this time displayed in a Message Box:
Unable to activate Windows Tailored application
It is getting more and more interesting. What the f*** is going wrong now? Again, Internet doesn’t tell anything, revealing only several people fighting with the same problem. The other frustrating issue is that Visual Studio doesn’t break at the code line that triggers the underlying exception. Although we are handling the Application.Current.UnhandledException event the exception is not caught there. After some debugging it turned out that the exception is caused during the Application.Run call and probably by some unmanaged code.
Next step – removing all the theme files from Generic.xaml. Having in mind the previous exception with custom type resolution this failure may be due to the same problem. Bingo – the Run method is now successfully passed and we are breaking with a NullReferenceException due to the missing control template. The problem is isolated successfully, now thinking of a way to specify the control template. As a test, let’s put an empty Style instance, targeting RadCartesianChart, in the application resources, put a break point before the Run method and examine the Resources property in the debugger. The result is very impressive:
((Windows.UI.Xaml.Application)(this)).Resources' threw an exception of type 'System.Runtime.InteropServices.COMException'
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
Point taken – no custom types in XAML in this early version of WinRT. Period. So far so good but how to display the chart actually? Trying code behind as our last resort:
Style style = new Style();
Style.TargetType = typeof(RadCartesianChart);
Unfortunately the result is pretty much the same – COM exception with the “go figure” error code. What? We should wait for a more stable version of the framework to get the demo done? No way, let’s not give up and do our best in working-around this issue.
Actually this was the biggest challenge we faced while building the demo shown in the above video. After dozens of trial-error scenarios we successfully found the only possible solution. Creating a ControlTemplate targeting the base (well familiar to WinRT) Control type did the trick. Yes, sounds crazy but the chart was properly initialized with a visual tree and it took its first breath in this new world.
To sum up the pitfalls:
  • No custom types, deriving directly from Control allowed. Neither in XAML nor in code behind.
    Solution: use the base Control type to declare Style objects in XAML and assign them to the desired control in code.
  • DependencyProperty.Register will raise a NullReferenceException if a custom type is specified as the OwnerType argument.
    Solution: use the base Control class as an owner type:
    DependencyProperty.Register(name, type, typeof(Control).FullName, metadata)
  • Some Dependency Properties like ItemsSource of type System.Collections.IEnumerable will fail to register.
    Solution: we haven’t found a solution yet. The friendly “NullReferenceException” is raised because the string “System.Collections.IEnumerable” is not resolved to a valid Type.
We believe that the above issues are either bugs or not implemented functionality in these early WinRT bits and they will not be present once a more mature version is out. Anyway, if you are experimenting for yourself it is good to know what to expect.
So, we have our charts in the demo created and initialized in code while the layout is done in XAML. There are many aspects of the application layout we consider interesting and which are worthy mentioning. A typical Metro app should support four different types of layout – FullScreen, Portrait, Filling and Snapped. This implies some more complex visual trees and event handling. But I will talk more about this stuff in my next posts to come, so make sure you do not miss them :)
In the mean time If you are curious about our RadChart for Windows Phone, part of RadControls for Windows Phone, do not hesitate to give it a try.

No comments: