6 Comments

The Windows Phone analytics service Wensus uses KendoUI DataViz components to draw the reports. The DataViz documentation is good but I think that there can never be enough examples. So, here’s few more. All the examples are available through jsFiddle.

image

The examples have been tested with KendoUI version 2012.2.710.

Bar chart with the margins removed between series

By default, if you create a Bar Chart with multiple series, there’s a margin between the bars which represent different series.

image

To make the chart more readable, it may be better to remove the margin. You can do this by setting the “spacing”-property to 0.

image

jsFiddle: http://jsfiddle.net/HdFsr/1/

Code:

$("#chart").kendoChart({
    title: {
        text: "Kendo Chart Example"
    },
    series: [{
        name: "Example Series",
        data: [200, 450, 300, 125],
        spacing: 0},
    {
        name: "Another Series",
        data: [200, 450, 300, 125],
        }],
    categoryAxis: {
        categories: [2000, 2001, 2002, 2003]
    }
});​

Automatically adjust step to make charts readable for an unknown amount of datapoints

Step-property can be used to configure how many labels are rendered for the categoryAxis. Without setting “step” and if there’s too much data, the chart may get messy:

But it’s much more readable when step is set to 10:

But what happens when you set the step to 10 and your backend sends you only few datapoints? The chart respects the step-property and again the chart may look clumsy:

The solution is to adjust the step-property dynamically, based on the amount of data. For this you can use chart’s dataBound-event in combination with the DataSource-component:

function dataBound(e) {
    var chart = $("#chart").data("kendoChart");
    if (dataSource.view().length > 4) {
        chart.options.categoryAxis.labels.step = 10;
    }
    else {
        chart.options.categoryAxis.labels.step = 1;
    }    
}

jsFiddle: http://jsfiddle.net/wkGud/1/

Code:

var dataSource = new kendo.data.DataSource({
    data: [{
        "ReportDate": "2012-01-02T00:00:00",
        "Value": 500.000000},
    {
        "ReportDate": "2012-06-01T00:00:00",
        "Value": 350.000000},
    {
        "ReportDate": "2012-07-01T00:00:00",
        "Value": 100.000000},
    {
        "ReportDate": "2012-08-16T00:00:00",
        "Value": 150.000000},
    {
        "ReportDate": "2012-08-17T00:00:00",
        "Value": 250.000000}]
});

function dataBound(e) {
    var chart = $("#chart").data("kendoChart");
    if (dataSource.view().length > 4) {
        chart.options.categoryAxis.labels.step = 10;
    }
    else {
        chart.options.categoryAxis.labels.step = 1;
    }    
}

$("#chart").kendoChart({
    title: {
        text: "Employee Sales"
    },
    dataSource: dataSource,
    series: [{
        type: "line",
        field: "Value"}],
    categoryAxis: {
        field: "ReportDate",
        type: "Date",
        baseUnit: "days"
    },
    dataBound: dataBound

});

Customizing the series colors:

KendoUI provides different themes out of the box, but configuring just the colors used by the charts is easy with seriesColors-property.

For example the default theme uses red and green:

image

If we want to display the same chart with different shades of blue, we can set the seriesColors:

seriesColors: ["#b4dbeb", "#8cc7e0", "#174356", "#0c242e"],

image

jsFiddle: http://jsfiddle.net/BmQd9/1/

Code:

$("#chart").kendoChart({
    title: {
        text: "Kendo Chart Example"
    },
    seriesColors: ["#b4dbeb", "#8cc7e0", "#174356", "#0c242e"],
    series: [{
        name: "Example Series",
        data: [200, 450, 300, 125]},
    {
        name: "Another Series",
        data: [200, 450, 300, 125]
        }],
    categoryAxis: {
        categories: [2000, 2001, 2002, 2003]
    }
});​

Links:

KendoUI Dataviz Documentation

23 Comments
  •   Posted in: 
  • UWP
Note: This is a repost of my Stack Overflow question. Feel free to comment here or on the SO.

 

I'm having some problems in Windows 8 Metro apps (XAML & C#) regarding the user's regional settings. It seems that the apps won't respect user's regional settings, so even if your Windows 8 is set to display dates and times in Finnish format, the apps will still display them using US-formatting. But this is such a big problem that there must be something I'm missing?

To test this I started by creating a WPF-application. The application just prints out the CurrentCulture and the formatted DateTime.Now:

private void Culture_Loaded_1(object sender, RoutedEventArgs e) 
        { 
            this.Culture.Text = System.Globalization.CultureInfo.CurrentCulture.DisplayName; 
        }

        private void Date_Loaded_1(object sender, RoutedEventArgs e) 
        { 
            this.Date.Text = DateTime.Now.ToString(); 
        }

Here's my default regional settings:

 

When run, the app displayed the date in Finnish format:

Then I changed the regional settings to US:

And when the app was run again, the culture and formatting changed:

This is as I expected everything to work and this is also how I expected WinRT apps to work.

So as a next step, I created a WinRT (XAML & C#) app with the same code and reverted the regional settings back to Finnish. The problem: 

Even when I've defined through regional settings that the formatting should be "Finnish", the WinRT app displays the datetime with US-formatting. I then modified the app's project file and made fi-FI the default language:

This change also modified the app's culture: 

Strange. I changed the Default Language back to its default value and the formatting was restored to US. I then created folders "Strings - fi-FI" inside the project and added an empty "Resources.resw" to the project. This empty file seems to be enough, as I was now getting the Finnish formatting: 


As soon as I remove the empty resource file, the formattings reverts back to US: 


Very strange.

Any ideas? Is this a bug, or something that needs to be considered when building WinRT apps? Any ideas how thing work on the JavaScript side of things? Please chime by leaving a comment here or on the Stack Overflow.

0 Comments

imageBackground

Keeping the Windows Phone app’s assemblies small is one of the optimization techniques when you want to improve the application’s startup time. As the documentation states:

When you submit your applications to the Windows Phone marketplace, they are signed for verification purposes and the signature is checked each time the application starts. The amount of time it takes to check the assembly signatures increases as the size of the application assemblies increases.

In this tutorial I’ll demonstrate how to split a Windows Phone app into multiple assemblies – which are loaded on-demand, not on startup - when using Caliburn.Micro.

The Problem

If you want to use Caliburn.Micro and you also want to split the app into multiple assemblies, the problems starts with the app’s bootstrapper and IOC. Given the scenario that we have the following assemblies:

  • LoadAssembliesOnDemand – The main assembly, which starts the app.
  • Module1 – Another assembly which will contains views (pages and user controls) and view models
  • Module2 – Another assembly with views and view models

Now if we configure the Caliburn.Micro’s container as we usually do, the code ends up looking like the following:

container.PerRequest<MainPageViewModel>(); 
container.PerRequest<Module1.MyPageViewModel>(); 
container.PerRequest<Module2.AnotherViewModel>();

And here’s the debug output from our app’s startup:

image

As you can see, configuring the container as we did forces the platform to load both the Module1 and Module2 assemblies, even though we don’t need them yet. What we need is a way to configure the IOC container  later, so that the external assemblies are loaded only on-demand.

The Solution

The solution to this problem is to use NuGet to get the following package:

Caliburn.Micro.WP71.Recipes.ExternalModules

This Caliburn.Micro recipe allows you to add assembly-level bootstrappers into your app.

If we get back to our example, with the help of this recipe we can remove all the Module1 and Module2 container initialization code from our main bootstrapper:

container.PerRequest<MainPageViewModel>();

Instead we call the recipe’s Initialize-method. Here’s our bootstrapper’s complete Configure-method:

protected override void Configure() 
{ 
    container = new PhoneContainer(RootFrame); 
    container.RegisterPhoneServices(); 

    container.PerRequest<MainPageViewModel>();

    Caliburn.Micro.WP71.Recipes.ExternalModules.ExternalModuleLoader.Initialize(); 
}

Now we can add the following class into our Module1 project:

public class Bootstrapper : ExternalAssemblyBootstrapper 
{ 
    protected override void ConfigureContainer(PhoneContainer container) 
    { 
        container.PerRequest<MyPageViewModel>(); 
        container.PerRequest<FeaturePageViewModel>(); 
    } 
}

And the following into Module2:

public class Bootstrapper : ExternalAssemblyBootstrapper 
{ 
    protected override void ConfigureContainer(PhoneContainer container) 
    { 
        container.PerRequest<AnotherViewModel>(); 
    } 
}

These bootstrappers are executed only when Caliburn.Micro tries to access the given assembly for the first time. If we now start the app, we can see that Module1 and Module2 aren’t loaded on the startup:

image

Now if we navigate to MyPage.xaml inside the Module1:

navigation.UriFor<MyPageViewModel>() 
    .Navigate();

We can see that the Module1.dll is loaded:

image
Also if add a breakpoint to the Module1’s Bootstrapper, you can see that the code in there is executed. But only once, when you navigate to the page the first time:

image

The bindings between views and view models work as they should:

image

The implementation

The recipe works by making modifications to Caliburn.Micro’s ViewModelLocator and ViewLocator. The modifications gets around the issues caused by Windows Phone platform not allowing the call to Assembly.Load, prohibiting the use of Caliburn.Micro’s built-in SelectAssemblies and AssemblySource capabilities.

There are some limitation with the recipe’s current implementation. For example, it only works with the Caliburn.Micro’s built-in PhoneContainer. Also it expects that the ViewModel class names all end with ViewModel.

Links

The recipe’s source code is available from GitHub. The assembly is available through Nuget.

The example app’s source code is available from the same GitHub repository.

28 Comments
  •   Posted in: 
  • UWP

imageOne of our Windows 8 WinRT apps requires a ListView with two features:

  1. "Auto-stick". The ListView must automatically scroll to the bottom when a new message is added to it.
  2. "Scroll detection". User can disable the "Auto-stick" by manually scrolling the ListView. If the user scrolls the ListView to bottom, the "Auto-stick" is enabled, otherwise it's disabled.

Here's some guidance on how you can achieve these features in a WinRT app using C# and XAML.

Automatically scrolling ListView to bottom

The ListView can be programmatically scrolled using the ScrollIntoView-method. You can pass in the item and the ListView jumps to show it. Here's how you can automatically scroll the ListView to show the last item when the list's ItemsSource is an ObservableCollection and a new item is added to the collection:

1. Register a listener to collection's CollectionChanged-event:
private readonly ObservableCollection<string> items = new ObservableCollection<string>(); 
...

        private void MyListviewLoaded(object sender, RoutedEventArgs e) 
        { 
            this.MyListView.ItemsSource = items;

            items.CollectionChanged += (s, args) => ScrollToBottom(); 
        }
2. In the ScrollToBottom-method, set the ListView's SelectedIndex to the last item in the collection, then use ScrollIntoView to scroll to the SelectedItem:
private void ScrollToBottom() 
        { 
            var selectedIndex = MyListView.Items.Count - 1; 
            if (selectedIndex < 0) 
                return;

            MyListView.SelectedIndex = selectedIndex; 
            MyListView.UpdateLayout();

            MyListView.ScrollIntoView(MyListView.SelectedItem); 
        }

Another option (used by the WinRT XAML Toolkit) is to get the ScrollViewer-control from inside the ListView, and call its ScrollToVerticalOffset-method:

private void ScrollToBottom() 
        { 
            var scrollViewer = MyListView.GetFirstDescendantOfType<ScrollViewer>(); 
            scrollViewer.ScrollToVerticalOffset(scrollViewer.ScrollableHeight); 
        }

GetFirstDescendantOfType is part of the WinRT XAML toolkit. Here's the VisualTreeHelperExtensions -class from the toolkit which includes this extension method:

public static class VisualTreeHelperExtensions 
    { 
        public static T GetFirstDescendantOfType<T>(this DependencyObject start) where T : DependencyObject 
        { 
            return start.GetDescendantsOfType<T>().FirstOrDefault(); 
        }

        public static IEnumerable<T> GetDescendantsOfType<T>(this DependencyObject start) where T : DependencyObject 
        { 
            return start.GetDescendants().OfType<T>(); 
        }

        public static IEnumerable<DependencyObject> GetDescendants(this DependencyObject start) 
        { 
            var queue = new Queue<DependencyObject>(); 
            var count = VisualTreeHelper.GetChildrenCount(start);

            for (int i = 0; i < count; i++) 
            { 
                var child = VisualTreeHelper.GetChild(start, i); 
                yield return child; 
                queue.Enqueue(child); 
            }

            while (queue.Count > 0) 
            { 
                var parent = queue.Dequeue(); 
                var count2 = VisualTreeHelper.GetChildrenCount(parent);

                for (int i = 0; i < count2; i++) 
                { 
                    var child = VisualTreeHelper.GetChild(parent, i); 
                    yield return child; 
                    queue.Enqueue(child); 
                } 
            } 
        }

        public static T GetFirstAncestorOfType<T>(this DependencyObject start) where T : DependencyObject 
        { 
            return start.GetAncestorsOfType<T>().FirstOrDefault(); 
        }

        public static IEnumerable<T> GetAncestorsOfType<T>(this DependencyObject start) where T : DependencyObject 
        { 
            return start.GetAncestors().OfType<T>(); 
        }

        public static IEnumerable<DependencyObject> GetAncestors(this DependencyObject start) 
        { 
            var parent = VisualTreeHelper.GetParent(start);

            while (parent != null) 
            { 
                yield return parent; 
                parent = VisualTreeHelper.GetParent(parent); 
            } 
        }

        public static bool IsInVisualTree(this DependencyObject dob) 
        { 
            return Window.Current.Content != null && dob.GetAncestors().Contains(Window.Current.Content); 
        }

        public static Rect GetBoundingRect(this FrameworkElement dob, FrameworkElement relativeTo = null) 
        { 
            if (relativeTo == null) 
            { 
                relativeTo = Window.Current.Content as FrameworkElement; 
            }

            if (relativeTo == null) 
            { 
                throw new InvalidOperationException("Element not in visual tree."); 
            }

            if (dob == relativeTo) 
                return new Rect(0, 0, relativeTo.ActualWidth, relativeTo.ActualHeight);

            var ancestors = dob.GetAncestors().ToArray();

            if (!ancestors.Contains(relativeTo)) 
            { 
                throw new InvalidOperationException("Element not in visual tree."); 
            }

            var pos = 
                dob 
                    .TransformToVisual(relativeTo) 
                    .TransformPoint(new Point()); 
            var pos2 = 
                dob 
                    .TransformToVisual(relativeTo) 
                    .TransformPoint( 
                        new Point( 
                            dob.ActualWidth, 
                            dob.ActualHeight));

            return new Rect(pos, pos2); 
        } 
    }

Detecting when ListView is scrolled to the bottom

In our case the auto-stick is enabled or disabled based on where the user scrolls the ListView. This requires that we can detect when the ListView is scrolled (or actually, when the scrolling ends) and also we need to know if the ListView is scrolled to the bottom. In order to achieve these, we first need to access the ListView's ScrollViewer and then the ScrollViewer's vertical ScrollBar. We can use the GetFirstDescendantOfType and GetDescendantsOfType -extension methods from WinRT XAML Toolkit (shown above) to get these controls:

            var scrollViewer = MyListView.GetFirstDescendantOfType<ScrollViewer>();

            var scrollbars = scrollViewer.GetDescendantsOfType<ScrollBar>().ToList();

            var verticalBar = scrollbars.FirstOrDefault(x => x.Orientation == Orientation.Vertical);

Now that we have the vertical scroll bar, we can register an event handler to its Scroll-event:

if (verticalBar != null) 
                verticalBar.Scroll += BarScroll;

In the BarScroll-method we receive and event argument of type ScrollEventargs. This argument tells us when the scrolling has ended. After making sure that we have received the event we need, we can use the argument's NewValue-property to make sure if we have scrolled to the bottom:

void BarScroll(object sender, ScrollEventArgs e) 
        { 
            if (e.ScrollEventType != ScrollEventType.EndScroll) return;

            var bar = sender as ScrollBar; 
            if (bar == null) 
                return;

            System.Diagnostics.Debug.WriteLine("Scrolling ended");

            if (e.NewValue >= bar.Maximum) 
            { 
                System.Diagnostics.Debug.WriteLine("We are at the bottom"); 
                LockToBottom = true; 
            } 
            else 
            { 
                System.Diagnostics.Debug.WriteLine("We are away from the bottom"); 
                LockToBottom = false; 
            } 
        }

Now we just need to the edit the ScrollToBottom-method so that the automatic scrolling happens only if the LockToBottom-property is set to true:

private void ScrollToBottom() 
        { 
            if (!LockToBottom) 
                return;

            var selectedIndex = MyListView.Items.Count - 1; 
            if (selectedIndex < 0) 
                return;

            MyListView.SelectedIndex = selectedIndex; 
            MyListView.UpdateLayout();

            MyListView.ScrollIntoView(MyListView.SelectedItem); 
        }

Sample:

A sample app if available from the GitHub.

image

Add few messages to the list to see how it auto scrolls, because the “Auto Stick” is enabled by default. Then scroll the list up and auto stick is disabled.

Links:

WinRT XAML Toolkit

3 Comments
  •   Posted in: 
  • UWP

imageIt’s happy times for the WinRT developers: Caliburn.Micro for WinRT is here. The core parts (INPC, EventAggregator) have actually been available since the developer preview was released last year, but now Nigel Sampson and Keith Patton have done a great work and have ported the rest of the framework to WinRT. Here’s a short introduction about how to get started, aimed for those who have previous experience working with the framework.

Note: Caliburn.Micro is aimed to the XAML & C#-developers. It’s built as a class library so it cannot be used with C++.

Update 5.12.2012:The post and the sample has been updated to work with the Caliburn.Micro version 1.4.

Bootstrapper

This guide is based on the “Blank App XAML” –template. The project needs to reference the following assemblies:

  • Caliburn.Micro.WinRT
  • Caliburn.Micro.WinRT.Extensions
  • Windows.UI.Interactivity

After creating a new solution, the first thing we need is to make the Caliburn.Micro to bootstrap the application. With other supported platforms,  this is usually done with a dedicated Bootstrapper-class. But with WinRT we use a custom “Application”-class to make this happen.

Every WinRT XAML template has a class called App (in App.xaml and App.xaml.cs files). The built-in App-class inherits the Windows.UI.Xaml.Application. When Caliburn.Micro is used in WinRT, the App is replaced with a class which inherits Caliburn.Micro.CaliburnApplication. This requires two modifications. First, we change the XAML from this:

<Application 
    x:Class="caliburn_micro_winrt_getting_started.App" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:caliburn_micro_winrt_getting_started">

    <Application.Resources> 
        <ResourceDictionary> 
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel 
                    Required by Visual Studio project and item templates 
                 --> 
                <ResourceDictionary Source="Common/StandardStyles.xaml"/> 
            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary> 
    </Application.Resources> 
</Application>

to this:

<cal:CaliburnApplication 
    x:Class="caliburn_micro_winrt_getting_started.App" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="using:caliburn_micro_winrt_getting_started" 
    xmlns:cal="using:Caliburn.Micro">

    <Application.Resources> 
        <ResourceDictionary> 
            <ResourceDictionary.MergedDictionaries>

                <!-- 
                    Styles that define common aspects of the platform look and feel 
                    Required by Visual Studio project and item templates 
                 --> 
                <ResourceDictionary Source="Common/StandardStyles.xaml"/> 
            </ResourceDictionary.MergedDictionaries>

        </ResourceDictionary> 
    </Application.Resources> 
</cal:CaliburnApplication>

Note that we have replaced the first and last line of the declaration. The same change must be done to code-behind:

sealed partial class App : Caliburn.Micro.CaliburnApplication 
{

Or alternatively:

sealed partial class App 
{

Our “bootstrapper” is now in place but as you can notice, the project doesn’t compile. What we need to do is to replace the code in App.xaml.cs with the initialization code required by Caliburn.Micro. As you can see, this class ends up looking like the “Bootstrapper” –class from other platforms. Here’s an example of a working App.xaml.cs:

using System;
using System.Collections.Generic;
using Caliburn.Micro;
using Windows.ApplicationModel.Activation;

namespace caliburn_micro_winrt_getting_started
{
    sealed partial class App
    {
        private WinRTContainer container;

        public App()
        {
            InitializeComponent();
        }

        protected override void Configure()
        {
            container = new WinRTContainer();
            container.RegisterWinRTServices();
        }

        protected override object GetInstance(Type service, string key)
        {
            return container.GetInstance(service, key);
        }

        protected override IEnumerable<object> GetAllInstances(Type service)
        {
            return container.GetAllInstances(service);
        }

        protected override void BuildUp(object instance)
        {
            container.BuildUp(instance);
        }

        protected override void PrepareViewFirst(Windows.UI.Xaml.Controls.Frame rootFrame)
        {
            container.RegisterNavigationService(rootFrame); 
        }

        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            DisplayRootView<MainPage>();
        }
    }
}

The bootstrapper is now in place so it’s time to build the views and view models.

The view

In our bootstrapper we defined “MainPage” as the default view. The Visual Studio template already contains the MainPage so we don’t have to implement it. What is required is the view model.

The view model

Add a class called MainPageViewModel to the project. Caliburn.Micro will automatically bind the view against this class. An instance of MainPageViewModel is created and set as the data context of the MainPage. As with other supported platforms, MainPageViewModel can be inherited from a Screen-class and also the Conductor is available:

public class MainPageViewModel : Screen 
{ 
}

At this point we’re actually all set and can start adding features like we usually do with Caliburn.Micro. Our sample app still looks rather uninteresting so let’s add something simple to the view.

Conventions

Caliburn.Micro for WinRT supports conventions like the other supported Caliburn.Micro platforms. For example the framework can automatically bind a button against a view model’s method and a text box against the view model’s string-property. Let’s add a button and an empty textbox to the MainPage.xaml:

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}"> 
    <Button x:Name="SayHello" Content="Say hello!" HorizontalAlignment="Left" VerticalAlignment="Top"/> 
    <TextBlock x:Name="HelloText" HorizontalAlignment="Left" VerticalAlignment="Center"/> 
</Grid>

And then add the following to to MainPageViewModel:

public class MainPageViewModel : Screen 
{ 
    private string helloText; 
    public string HelloText 
    { 
        get { return helloText; } 
        set { helloText = value; NotifyOfPropertyChange(() => HelloText); } 
    }

    public void SayHello() 
    { 
        this.HelloText = "Hi from the Caliburn.Micro for WinRT!"; 
    } 
}

And we’re all set. The button named “SayHello” is automatically bound against the SayHello-method and the same happens with the textbox HelloText.

image

Conclusion

Caliburn.Micro has previously been easily the best framework to make you more productive when building apps for Windows Phone, Silverlight and WPF. And now we have the same powerful framework available for WinRT.

Links