- Posted by Diederik Krols on April 8, 2012
This article describes how to create a custom Settings Panel for a Windows 8 Metro app (Consumer Preview) using XAML and C#. It also describes a way to broadcast the new settings to the app's components. Apps written in JavaScript and HTML5 can make use of the SettingsFlyout control. There's a full sample demonstrating everything. XAML developers have no out-of-the-box settings control. They have to look very hard to find just a modest quickstart. This article is loosely based on that quickstart.
Here's a screenshot of the demo app:

The app settings are stored in an instance of a custom class: AppSettings. They will be displayed by a custom user control: AppSettingsPane. That control is shown in a Popup when the settings charm is activated or the 'Settings' button is hit.
Since app settings are general, all functionality is implemented in the App class itself. I used a partial class to isolate the responsibilities.
Here's the run time routine:
When the app starts, settings are initialized:
// TODO: get initial settings from local storage, skydrive, cloud, or whatever.
private AppSettings appSettings = new AppSettings { NumberOfBottles = 2 };
The app registers a command with the Settings Charm:
SettingsPane.GetForCurrentView().CommandsRequested += App_CommandsRequested;
When executed, that command adds a new hyperlink in the default settings panel:

When that hyperlink is clicked, the app creates an instance of the custom user control, and displays it in a Popup. The Popup is positioned at the place where the system settings panel was: on the right hand side, using the full height, and 346 pixels wide:

Here's the command structure - the full code is attached at the end of this article:
private void App_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
SettingsCommand cmd = new SettingsCommand("SettingsId", "Preferences", (x) =>
{
// Create popup
_settingsPopup = new Popup()
{
IsLightDismissEnabled = true,
// ...
};
_settingsPopup.Closed += OnPopupClosed;
// ...
// Create settings pane
AppSettingsPane appSettingsPane = new AppSettingsPane()
{
// ...
DataContext = new AppSettings
{
NumberOfBottles = this.appSettings.NumberOfBottles,
UseGlass = this.appSettings.UseGlass
} // A copy of the settings, so app working screen bindings are not updated
};
// Hook settings pane in popup
_settingsPopup.Child = appSettingsPane;
// Display popup
_settingsPopup.IsOpen = true;
});
// Make commands available in settings pane
args.Request.ApplicationCommands.Add(cmd);
}
Note that the settings pane is bound to a copy of the app settings. That way the working screens are not continuously updated while changing the settings. The popup can be closed by hitting the back button on the settings pane (the arrow on top), or by tapping somewhere outside the settings pane (that's why the IsLightDismissEnabled property of the popup is set to true).
On closing the popup, the app's settings are updated and then broadcasted to all the relevant components. Using an event aggregator is a nice way of doing this. The following code uses a singleton instance of the event aggregator from the Caliburn Micro MVVM framework:
private void OnPopupClosed(object sender, object e)
{
_settingsPopup.Closed -= OnPopupClosed;
AppSettings newSettings = (_settingsPopup.Child as FrameworkElement).DataContext as AppSettings;
if (newSettings != null)
{
// Update app settings
this.appSettings = newSettings;
// Broadcast the new settings
EventAggregator.Instance.Publish(this.appSettings);
}
}
Views, viewmodels, services and other components that are interested in app settings changes, just need to implement the IHandle interface and register themselves to the event aggregator:
public sealed partial class BlankPage : Page, IHandle<AppSettings>
{
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Subscribe
EventAggregator.Instance.Subscribe(this);
}
public void Handle(AppSettings settings)
{
// Update
this.SettingsGrid.DataContext = settings;
}
}
Here's the source code of the sample app. It was written in Visual Studio 11 Express Beta for the Windows 8 Consumer preview: U2UConsult.Metro.SettingsSample.zip (343,44 kb)
Enjoy!
- Posted by Diederik Krols on March 28, 2012
This short article describes how to use the CarouselPanel in a Windows 8 Consumer Preview Metro style app. Don't expect the spectacular rotating 3D effects from the Infragistics WPF control with the same name. In the current release, a Metro CarouselPanel is nothing more than a vertically revolving conveyer belt. That's good enough: the CarouselPanel is one of those controls that keeps your design away from the traditional dull grid-and-combobox layout that we know from excel or standard winforms databinding. Here's a WPF example; it's a prototype of an application that allows you to mix your own cocktails by selecting the products and entering the corresponding quantity:

If you would sell this app through the store, you probably won't get rich. Grid-and-combobox design is so passé. On the other hand: if you would generate views on the same data model using the default ASP.NET MVC templates, you'll get exactly the same lame design...
Anyway, here's how this application may look like in Metro style. It's operated by swiping and tapping on the products carousel on the left, instead of fighting with comboboxes and empty grid rows:

The vertical strip on the left is an instance of a CarouselPanel. The CarouselPanel was already available in the Developer Preview of Windows 8, but only as a part of the ComboBox control template. In the Consumer Preview you can use it as ItemsPanelTemplate of any ItemsControl.
<ListView ItemsSource="{Binding YourCollectionHere}">
<ListView.ItemTemplate>
<DataTemplate>
<!-- Your Data Template Here -->
</DataTemplate>
</ListView.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<CarouselPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListView>
That's all there is! You can scroll via touch or via the mouse wheel. When you reach the end of the list, you can continue scrolling in the same direction. After the end of the list an empty placeholder is inserted, and then everything starts all over again. The following screenshot shows the placeholder - between the end of the list (pineapple juice) and the new beginning (white rum):

For those who want to use the control in a horizontal orientation (e.g. as a filmstrip), here's the good news: there is a CanHorizontallyScroll property in the documentation and in Visual Studio's Designer:

Here's the bad news: setting the property gives a compile time error. The horizontal strip in the demo app is just a GridView; you have to move back and forth to have an overview of all ingredients.
Anyway, the existence of the CanHorizontallyScroll property (and some of the other non-functioning class members) indicates that Microsoft has plans to do more with this control in the future.
Here's the code of the demo app. It was written in Visual Studio 11 Express Beta for Windows 8 Consumer Preview: U2UConsult.WinRT.CarouselSample.zip (770,55 kb)
Enjoy !
- Posted by Diederik Krols on March 19, 2012
Some people seem to think that the world has only one language, one currency, and one way to represent a date, a time, or a number. So WinRT comes without a StringFormat option in data binding. I know for sure that I never built a WPF or Silverlight application without extensively using that StringFormat option. Just think about how your calendar or online banking application would look like without the proper content formatting:
"Dear customer, at 3/20/2012 6:23:30 PM the balance of your bank account BE43068999999501 was at -850325, so we will withdraw that amount from your credit card 4417123456789113. Please call +442071311117 for further assistance."
You simply can't get away with that, so I believe that one of the next Metro versions *will* come with string formatting in bindings. In the mean time, we will have to implement formatting in the viewmodel, or help ourselves using a value converter. Here's an example of the latter. It supports two-way bindings, and it doesn't crash when you forget to specify the format:
public class StringFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
// No format provided.
if (parameter == null)
{
return value;
}
return String.Format((String)parameter, value);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
return value;
}
}
Just define it as a resource in XAML:
<Page.Resources>
<local:StringFormatConverter x:Key="StringFormatConverter" />
</Page.Resources>
And use it:
<TextBlock Text="{Binding SomeDateTime, Converter={StaticResource StringFormatConverter}, ConverterParameter='{}{0:dd MMM yyyy}'}" />
It works well against strings, dates, times, and numbers:

Here's the full source. It was built with Visual Studio 11 Express Beta, for the Windows 8 Consumer Preview: U2UConsult.WinRT.StringFormatConverterSample.zip (170,03 kb)
Enjoy!
- Posted by Diederik Krols on March 8, 2012
A long time ago in a galaxy actually not so far away, Colin Eberhardt wrote a Radial Gauge custom control for Silverlight in less than six hours. It had everything a gauge should have: a needle, and a scale with tick markers and labels. Hell, it even had colored quality range indicators. A couple of months ago, I thought "Hey, I can do that too." So I started a new Metro project in my Developer Preview of Windows 8. I tried to create a Metro version of that same radial gauge in less than six hours. Six lonely nights later, I still had absolutely nothing, and I started to consider anger management training. I gave up and started from scratch, this time on a much simpler control: a minimalistic slider. That involved a lot of work with -let's be honest- a rather lame result. The Developer Preview was clearly not an ideal environment for building custom controls.
But that was then and this is now. Yesterday, Tim Heuer revealed how to build a deployable custom control for XAML Metro style apps with the Consumer Preview of Windows 8. I discovered that the current beta of Visual Studio 11 comes with a template for a Templated Control. I happily noticed the return of the themes/generic.xaml file that we know from all the other XAML platforms. So I decided to have another go on the radial gauge custom control. Here's the result:
 |
 |
| Colin's Silverlight Gauge |
Diederik's Metro Gauge |
Here's how the gauge is defined in XAML:
<local:RadialGaugeControl Maximum="100"
Minimum="-100"
Value="65"
Unit="°C"
Height="200">
<local:RadialGaugeControl.QualitativeRanges>
<local:QualitativeRange Color="#FFFFFFFF"
Maximum="0" />
<local:QualitativeRange Color="#FFFFFF00"
Maximum="40" />
<local:QualitativeRange Color="#FFFFA500"
Maximum="80" />
<local:QualitativeRange Color="#FFFF0000"
Maximum="100" />
</local:RadialGaugeControl.QualitativeRanges>
</local:RadialGaugeControl>
The Metro version of the radial gauge is simplified in many ways:
• It has the Metro look-and-feel: it's sharp, without gradients or shadows. No chrome, but content!
• It does not delegate its look-and-feel to a separate viewmodel. All code is hosted by the control class itself.
• I simplified most of the calculations by creating a fixed size control and wrapping it in a Viewbox. After all, the control only contains vector graphics: Ellipse, Path, and Text.
There's probably more room for simplification and improvement, but this was a race against time, remember. At the end or the day, I'm happy with the result. Here's how the attached sample solution looks like. By the way, EBC -the unit of color- stands for European Brewing Convention (the European alternative for Lovibond) and EBU -the unit of bitterness- stands for European Bitterness Unit (the European version of IBU):

The conversion from Silverlight to Metro went very fast. The Consumer Preview version of Metro uses the same paradigms (and name spaces!) as the existing XAML platforms, so I'm going to spare you the details. A custom control is defined by a control class with dependency properties, and a generic.xaml file with the default style definition:

So if you can write a custom control in Silverlight, you can write a custom control in Metro! Sometimes you may have to work your way around some glitches. I noticed that the rotation transformation on the needle path isn't fired if it's defined in XAML. The values are correctly assigned by the TemplateBinding, but the transformation does not happen:
<Path.RenderTransform>
<RotateTransform Angle="{TemplateBinding ValueAngle}" />
</Path.RenderTransform>
So I moved it to the code behind:
Path needle = this.GetTemplateChild(NeedlePartName) as Path;
needle.RenderTransform = new RotateTransform() { Angle = this.ValueAngle };
I still had a lot of time left in my six hour frame, when I started the implementation of the qualitative ranges - the nicely colored arc segments. I discovered rapidly that there are no TypeConverters for WinRT structs such as Color. There is also no support for custom TypeConverters. Bummer. I had no choice but to redefine the Color property as a String - instead of a 'real' Color type:
public class QualitativeRange
{
public double Maximum { get; set; }
public String Color { get; set; }
}
That type change comes with a huge price: say "bye-bye Visual Studio Designer support" when assigning a Color in XAML. I then had to figure out how to translate the color string into a Brush, because there is no ColorConverter.ConvertFromString in Metro. So back to anger management training...
... or not. I decided to drop support for named colors and restrict the color values to hexadecimal codes only. I then upgraded an old HexToColor converter that I found in one of my legacy Silverlight (2.0?) frameworks. That definitely does the trick - at least if the input falls in the expected range:
namespace U2UConsult.Metro.RadialGauge
{
using System;
using Windows.UI;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
public class HexToColorConverter : IValueConverter
{
/// <summary>
/// Converts a hexadecimal string value into a Brush.
/// </summary>
public object Convert(object value, Type targetType, object parameter, string language)
{
byte alpha;
byte pos = 0;
string hex = value.ToString().Replace("#", "");
if (hex.Length == 8)
{
alpha = System.Convert.ToByte(hex.Substring(pos, 2), 16);
pos = 2;
}
else
{
alpha = System.Convert.ToByte("ff", 16);
}
byte red = System.Convert.ToByte(hex.Substring(pos, 2), 16);
pos += 2;
byte green = System.Convert.ToByte(hex.Substring(pos, 2), 16);
pos += 2;
byte blue = System.Convert.ToByte(hex.Substring(pos, 2), 16);
return new SolidColorBrush(Color.FromArgb(alpha, red, green, blue));
}
/// <summary>
/// And back again.
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
SolidColorBrush val = value as SolidColorBrush;
return "#" + val.Color.A.ToString() + val.Color.R.ToString() + val.Color.G.ToString() + val.Color.B.ToString();
}
}
}
To make the gauge interactive, I hooked a change event handler to the dependency property:
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(RadialGaugeControl), new PropertyMetadata(0.0, OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
RadialGaugeControl c = (RadialGaugeControl)d;
// ...
}
}
Unfortunately neither a GetTemplateChild nor a FindName method call were able to find the Needle element: both retrieved a null value. So I created a private field for the Needle, populated the field in the OnApplyTemplate call:
this.Needle = this.GetTemplateChild(NeedlePartName) as Path;
Then it became accessible in the change event handler:
if (c.Needle != null)
{
c.Needle.RenderTransform = new RotateTransform() { Angle = c.ValueAngle };
}
And the radial gauge became truly bindable:

Here's the code for the gauge control and the client app. It was written with Visual Studio 11 Express Beta for the Windows 8 Consumer Preview: U2UConsult.Metro.RadialGauge.zip (399,29 kb)
Enjoy !
- Posted by Diederik Krols on March 7, 2012
This article describes how to implement data binding and using variable sized cells in a VariableSizedWrapGrid control in a Windows 8 Metro application, Customer Preview release. The VariableSizedWrapGrid control exposes the ColumnSpan and RowSpan attached properties. These allow to specify the number of columns and rows an element should span. He're how the sample project looks like:

According to the official documentation the ColumnSpan and RowSpan values are interpreted by the most immediate parent VariableSizedWrapGrid element from where the value is set. So let's say we have a Thing class (I couldn't find a better name) with a Width property that contains the relative width (i.e. the number of columns to span). Our viewmodel exposes a list of Things that we want to show, and allows binding to the selected Thing:
public class MainPageViewModel : BindableBase
{
public List<Thing> Things
{
get
{
List<Thing> results = new List<Thing>();
results.Add(new Thing() { Name = "Beer", Height = 1, Width = 1, ImagePath = @"/Assets/Images/beer.jpg" });
results.Add(new Thing() { Name = "Hops", Height = 2, Width = 2, ImagePath = @"/Assets/Images/hops.jpg" });
results.Add(new Thing() { Name = "Malt", Height = 1, Width = 2, ImagePath = @"/Assets/Images/malt.jpg" });
results.Add(new Thing() { Name = "Water", Height = 1, Width = 2, ImagePath = @"/Assets/Images/water.jpg" });
results.Add(new Thing() { Name = "Yeast", Height = 1, Width = 1, ImagePath = @"/Assets/Images/yeast.jpg" });
results.Add(new Thing() { Name = "Sugar", Height = 2, Width = 2, ImagePath = @"/Assets/Images/sugars.jpg" });
results.Add(new Thing() { Name = "Herbs", Height = 2, Width = 1, ImagePath = @"/Assets/Images/herbs.jpg" });
// And so on, and so forth ...
return results;
}
}
private Thing selectedThing;
public Thing SelectedThing
{
get { return selectedThing; }
set { this.SetProperty(ref selectedThing, value); }
}
}
The viewmodel derives from BindableBase, a helper class provided by the new Visual Studio templates that implements property changed notification using the new C# 5 CallerMemberName attribute. The viewmodel is attached to the view in XAML. I'm glad that this finally works! In the Developer Preview we needed to do this in the code behind:
<Page.DataContext>
<local:MainPageViewModel />
</Page.DataContext>
Now the VariableSizedWrapGrid control is just a Panel, not an ItemsControl, so in a databound scenario we also need a GridView. In theory the next configuration would work. We simply attach the properties to the item data template of the GridView:
<GridView ItemsSource="{Binding Things}">
<GridView.ItemTemplate>
<DataTemplate>
<Grid VariableSizedWrapGrid.ColumnSpan="{Binding Width}" >
<!-- Insert Item Data Template Details Here -->
<!-- ... -->
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid />
</ItemsPanelTemplate>
<GridView.ItemsPanel>
</GridView>
This does not work. When data binding, each item is wrapped in a GridViewItem control, which apparently swallows the attached properties. So far for the theory. In practice, the only way to make the scenario work is to create a GridView child class and override the PrepareContainerForItemOverride method.
The control class would look like this:
public class VariableGridView : GridView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
var viewModel = item as Thing
element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, viewModel.Width);
element.SetValue(VariableSizedWrapGrid.RowSpanProperty, viewModel.Height);
base.PrepareContainerForItemOverride(element, item);
}
}
Of course we're not going to build a specialized GridView class for each model in our application, so it makes sense to define an interface:
public interface IResizable
{
int Width { get; set; }
int Height { get; set; }
}
Here's a reusable version of the GridView child. It only depends on the interface:
public class VariableGridView : GridView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
var viewModel = item as IResizable;
element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, viewModel.Width);
element.SetValue(VariableSizedWrapGrid.RowSpanProperty, viewModel.Height);
base.PrepareContainerForItemOverride(element, item);
}
}
And here's the Thing, the whole Thing, and nothing but the Thing:
public class Thing : IResizable
{
public string Name { get; set; }
public string ImagePath { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public ImageSource Image
{
get
{
return new BitmapImage(new Uri("ms-appx://" + this.ImagePath));
}
}
}
In the main page, we just replace GridView by the custom class:
<local:VariableGridView ItemsSource="{Binding Things}">
<local:VariableGridView.ItemTemplate>
<DataTemplate>
<Grid>
<!-- Insert Item Data Template Details Here -->
<!-- ... -->
</Grid>
</DataTemplate>
</local:VariableGridView.ItemTemplate>
<local:VariableGridView.ItemsPanel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid />
</ItemsPanelTemplate>
<local:VariableGridView.ItemsPanel>
</local:VariableGridView>
Tadaa !
Here's the source code. It was written with Visual Studio Express 11 Beta, for the Windows 8 Consumer Preview: U2UConsult.Metro.VariableSizedWrapGridSample.zip (951,87 kb)
Enjoy !
- Posted by Diederik Krols on March 1, 2012
This article describes how you can navigate through large amounts of data in a Metro application, on the Windows 8 Consumer Preview. We'll use a grouped and a non-grouped GridViews, a SemanticZoom, a WrapGrid, and a VariableSizedWrapGrid control. The app was built with the brand new Visual Studio 11 Beta. By the way, here's how that beta looks like:

Cool, isn't it ?
The Data
The app will display a small collection of Belgian beers. In real life Belgian beer has a wonderful aroma, an excellent flavor and ditto mouthfeel. In the demo app Belgian beer just has a name, a category, and an image. Here's how the base list is created:
/// <summary>
/// Returns a list of some Belgian beers.
/// </summary>
public static IEnumerable<BelgianBeer> BelgianBeers
{
get
{
List<BelgianBeer> result = new List<BelgianBeer>();
result.Add(new BelgianBeer() { Name = "Saison 1900", Category = "Belgian Saison", ImagePath = "Assets/Images/1900.jpg" });
// And we have plenty more of these ...
result.Add(new BelgianBeer() { Name = "Slaapmutske Tripel", Category = "Belgian Strong Ale", ImagePath = "Assets/Images/Slaapmutske.jpg" });
result.Add(new BelgianBeer() { Name = "Westmalle Tripel", Category = "Belgian Strong Ale", ImagePath = "Assets/Images/Westmalle.jpg" });
return result;
}
}
Here's how this beer collection will be displayed by the app. It will nicely group the individual beers by their category:

The data will be pulled from a CollectionViewSource that we define in XAML:
<UserControl.Resources>
<CollectionViewSource x:Name="cvs1"
IsSourceGrouped="True" />
</UserControl.Resources>
We're working in grouped mode here, so don't forget to set the IsSourceGrouped property. Since yesterday (the day the Consumer Preview was launched) the collection view source is happy with the result of a grouped LINQ query:
/// <summary>
/// Returns the same list of beers, grouped by category.
/// </summary>
public static IEnumerable<object> BelgianBeersByCategory
{
get
{
var query = from item in BelgianBeers
orderby item.Category
group item by item.Category into g
select g;
return query;
}
}
When the main view is created, we populate the collection view source with the result of that LINQ query:
this.cvs1.Source = MainViewModel.BelgianBeersByCategory;
Displaying grouped data in a GridView
The collection view source will be used as items source for a GridView. That GridView will do all the formatting through its many templates:
<GridView ItemsSource="{Binding Source={StaticResource cvs1}}"
IsSwipeEnabled="True">
<GridView.ItemTemplate>
<DataTemplate>
<!-- Insert Item Data Template Here -->
<!-- ... -->
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<!-- Insert Panel Template Here -->
<!-- ... -->
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<!-- Insert Group Header Template Here -->
<!-- ... -->
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<!-- Insert Group Panel Template Here -->
<!-- ... -->
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
Here's a graphical overview of the templates in a grouped GridView:

The Item Data Template (blue rectangle) describes how each item (beer) will be represented:
<StackPanel Margin="8">
<TextBlock Text="{Binding Name}"
Foreground="White" />
<Image Source="{Binding Image}"
Height="145"
Width="190"
Stretch="UniformToFill" />
</StackPanel>
The Item Panel Template (purple rectangle) describes how the groups (beer categories) will be arranged. I went for a horizontal stackpanel, so scrolling or swiping sideways will move you through the categories. Read on to discover why this was a bad idea:
<StackPanel Orientation="Horizontal" />
In grouped mode you have to fill the GroupStyle property. The Group Header Template (red rectangle) describes how the group header (beer category header) looks like:
<TextBlock Text="{Binding Key}" Foreground="Gold" />
The Group Panel Template (yellow rectangle) describes the arrangement of items (beers) in each group (beer category). In our app, the items are displayed in a VariableSizedWrapGrid. That's an advanced version of the old WrapPanel: elements are positioned in sequential order and go to the next row or column if there isn’t enough room. This control allows me to display some of the beers in a different size, by binding to the RowSpan and ColumnSpan properties. I'm not going to use these, so the panel will behave like just an ordinary WrapPanel:
<VariableSizedWrapGrid Orientation="Vertical" />
Semantic Zoom
We're merely displaying 21 beers here. What happens if you have a very large dataset ? Some of the local shops here have 300, 500 or even over 800 Belgian beers
! You will get very thirsty when scrolling to the last category...
Well, I have good news for you: there's a new control that allows you to jump easily into a specific group (beer category) in the data. It's called the SemanticZoom, the control that was formerly known as JumpViewer. This control allows you configure and combine two GridViews or anything else that implements the ISemanticZoomInformation interface: a details view -ZoomedInView- and a summary view -ZoomedOutView-. You can easily navigate between these two. The SemanticZoom is highly customizable, as you can see in the Guidelines for Semantic Zoom.
In our app, we're using the beer label GridView as details view. The summary view looks like this:

The summary view is also a GridView, but it's populated directly with the list of beer categories. Its item template is just a TextBlock:
<TextBlock Text="{Binding Group.Key}" Foreground="Gold" />
The items are arranged in a regular WrapGrid:
<WrapGrid MaximumRowsOrColumns="4" HorizontalAlignment="Center" VerticalAlignment="Center" />
You call the summary view via a pinch gesture in the details view. In the summary view, tapping on a category brings you directly to the corresponding group in the detailed view. At least, that's were you should return to. In the Developer Preview this code worked fine, but the Consumer Preview seems to always navigate to the first group. Anyway, the issue was reported...
... and solved. Apparently the item panel template (purple rectangle) has to be a WrapGrid:
<WrapGrid Orientation="Vertical" MaximumRowsOrColumns="1" />
Here's an overview of the semantic zoom structure:
<SemanticZoom x:Name="semanticZoom">
<!-- Details View -->
<SemanticZoom.ZoomedInView>
<GridView ItemsSource="{Binding Source={StaticResource cvs1}}"
IsSwipeEnabled="True">
<!-- Configure Details View Here -->
<!-- ... -->
</GridView>
</SemanticZoom.ZoomedInView>
<!-- Summary View -->
<SemanticZoom.ZoomedOutView>
<GridView>
<!-- Configure Summary View Here -->
<!-- ... -->
</GridView>
</SemanticZoom.ZoomedOutView>
</SemanticZoom>
Both GridViews use the same data, but you have to glue them together programmatically:
(this.semanticZoom.ZoomedOutView as ListViewBase).ItemsSource = cvs1.View.CollectionGroups;
Here's the app's tile after deployment, next to the highly addictive Metro version of Cut the Rope (that's an old screenshot by the way: I cut many more ropes since then). It's another VariableSizedWrapGrid in action:

Source Code
Here's the source code, it was written with VS11 beta for the Windows 8 Consumer Preview: U2UConsult.WinRT.GridViewSample.zip (2,72 mb)
Enjoy ... and Cheers !
- Posted by Diederik Krols on January 21, 2012
This article describes how to build custom WinRT Metro controls in C# and XAML, with the Developer Preview version of Visual Studio 11. WPF, Silverlight, and WinRT Metro have two ways to roll your own controls: custom controls, and user controls. User controls are composite controls that are created by dragging and dropping other controls onto a XAML surface. They are nothing more than content controls that are optimized for design-time use. User controls are typically for sharing within an application, but not with other applications. Custom controls on the other hand, are created by defining a class that derives -directly or indirectly- from Control, together with a definition of a default style. Custom controls are typically hosted in control libraries, and shared between multiple applications. Custom controls are much more flexible in terms of reuse, styling, templating, and theming.
For this article I created a simplified version of the Slider control. It's called SimpleSlider. It has a Minimum, Maximum, and Value property. Visually it only consists of a moving part -the thumb- and a colored rectangle of which the width is bound to the Value property:

I first created a project in .NET 4.0 WPF with Visual Studio 10. Then I tried to implement the same functionality in a .NET 4.5 Metro-style app. Here are screenshots of both versions:
Creation of the control
For WPF there is a WPF Custom Control Library project template. It creates a custom control derived from the most common base class: Control. You might want to change that into a more appropriate class, like ItemsControl or Selector. RangeBase would have been the ideal base class for a Slider, but I wanted to build everything from scratch, so I kept the default.
The Visual Studio template assigns the DefaultStyleKey dependency property through an OverrideMetaData call in a static constructor. It also creates a Themes folder with a generic.xaml with an (almost) empty default control template for the new user control. The project's assembly information gets a ThemeInfo attribute that contains the locations where that default style will be searched when the control needs to be displayed.
That's how it goes in Silverlight and WPF. For Metro style apps there is NO such project template - there's not even a class template for a custom control. The reason is that things like DefaultStyleKey, ThemeInfo and generic.xaml are not supported (yet?). So you have to create the SimpleSlider class and its generic.xaml manually. To inject the style file into the application, add it as a resource dictionary in app.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Adding Bindable Properties
By deriving from Control, a custom control inherits a set of useful dependency properties. These are properties to which the user of the control can databind: things like Background, FontSize, and Template. You can add custom dependency properties yourself - Visual Studio has a code snippet for that: propdp. It generates the dependency property registration for you:
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", "Object", typeof(SimpleSlider).FullName, new PropertyMetadata(0.0, OnValueChanged));
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
The PropertyMetadata allows you to define the default value and the method that should be called when the property's value is changed. When the Value property of the SimpleSlider is changed, we're going to redraw it:
private static void OnValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var customSlider = (SimpleSlider)dependencyObject;
customSlider.UpdateControls();
}
Contrary to WPF and Silverlight, the Register method takes strings instead of types. This is just temporary: Microsoft will regain compatibility with Silverlight and WPF in the upcoming beta of WinRT.
In the Developer Preview you need to specify 'Object' as the property type to make the bindings work, but that's also just a temporary bug.
Styling
Defining the default style for your custom control is not different from current technologies. You just define a style with the corresponding target type in a resource dictionary. Here's the full definition of the default style for the simple slider:
<Style TargetType="ctrl:SimpleSlider">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ctrl:SimpleSlider">
<Grid>
<Border Height="8"
VerticalAlignment="Stretch"
Background="LightGray" />
<Canvas Margin="0"
MinHeight="8">
<Rectangle x:Name="PART_Rectangle"
Height="8"
Fill="Yellow" />
<Thumb x:Name="PART_Thumb"
Width="8"
Height="8" />
</Canvas>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would suggest to NOT use TemplateBinding in a style definition, since this doesn't seem to work yet. The following code, where I replaced the Border in the template by a Rectangle with its Width bound to the actual width of the control, does not work in the Developer Preview:
<Rectangle Height="8"
Width="{TemplateBinding ActualWidth}"
VerticalAlignment="Stretch"
Fill="LightGray" />
If you're looking for inspiration about styles: all the default styles for WPF and Silverlight controls are on MSDN. You can find the full style for the WPF Slider here. The WinRT Metro styles are not published yet, but if you open the Basic Controls Sample, you'll find a light_generic.xaml file that has all the information. You'll immediately see why my control is called 'Simple' Slider...
Templating
The user of your custom control should be able to decide for 200% on how your control should look like in his application. But of course he needs to respect some basic requirements: a slider will always have a moveable part (the Thumb) and an indication of its Value (the Rectangle). The required elements in a style are by convention named with a 'PART_' prefix. The code behind file also exposes these elements' name and type through a TemplatePart attribute:
[TemplatePart(Name = ThumbPartName, Type = typeof(Thumb))]
[TemplatePart(Name = RectanglePartName, Type = typeof(Rectangle))]
public class SimpleSlider : Control
{
private const string ThumbPartName = "PART_Thumb";
private const string RectanglePartName = "PART_Rectangle";
// ...
}
This indicates to potential control re-stylers that the code-behind relies on these parts. So if you override the default style, you should make sure that it contains elements with the expected name and type.
The style -default or custom- is typically applied in the OnApplyTemplateCore method, that's Metro's version of the OnApplyTemplate method that we know from Silverlight and WPF. As a developer of custom controls, you should wrap the template part manipulation in defensive code. After all, you never know what template you will be dealing with at run-time. Use GetTemplateChild to find the template part you're interested in, since WPF's Template.Find does not exist in Silverlight and Metro:
protected override void OnApplyTemplateCore()
{
base.OnApplyTemplateCore();
this.thumb = this.GetTemplateChild(ThumbPartName) as Thumb;
if (this.thumb != null)
{
this.thumb.DragDelta += this.Thumb_DragDelta;
}
// ...
}
All changes to a dependency property fire the INotifyPropertyChanged event. Unfortunately, in the Developer Preview something goes wrong in the central binding mechanism when the ElementName property is used. The following code displays the initial slider value correctly in a textblock. But when the thumb is moved, the textbox just disappears:
<TextBlock Text="{Binding Path=Value, ElementName=SimpleSlider}" />
If you bring a viewmodel in the equation and use it as datacontext for slider and textbox, then everything works as expected. This looks like overkill, but as a die-hard MVVM developer I can live with that. Here's the -working- code for the value binding of the pacman-shaped slider:
<TextBlock Text="{Binding SliderValue}" />
Overriding a style
To override the default style, you just need to provide a new one, e.g. through XAML:
<ctrl:SimpleSlider.Style>
<Style TargetType="ctrl:SimpleSlider">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ctrl:SimpleSlider">
<!-- Your template here -->
<!-- ... -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ctrl:SimpleSlider.Style>
Just make sure you use the required template parts.
Conclusion
There are a couple of glitches in the Developer Preview, but in general the WinRT Metro framework already has most of the foundations to build reusable custom control libraries. In a couple of weeks there will be a new release: not a true beta release, but a so-called 'consumer preview'. I can't wait to get my hands on it...
Code
Here's the full code, the WinRT version was built with the Visual Studio 11 Developer Preview:
WPF: U2UConsult.WPF.SimpleSlider.zip (24,81 kb)
WinRT: U2UConsult.WinRT.SimpleSlider.zip (34,84 kb)
Enjoy!
Afterthought
I realize that it was unfair to compare WinRT Metro directly to WPF. The WinRT Metro mechanisms are much closer to Silverlight than they are to WPF. WinRT Metro currently feels like a stripped-down version of Silverlight (which itself is a stripped-down version of WPF). At first, I found that a bit strange. After all, the WinRT runtime is not restrained by footprint size: it doesn't have to be smaller than the Flash plugin. It's also not constrained by browser and operating system compatibility: it doesn't have to run in Opera on a Windows Server 2000, nor in Safari on a Mac. On the other hand, WinRT is targeted to run on cheap (well, hopefully) tablets powered by ARM processors, the 32-bit cores that drive smartphones, MP3-players, and the Nintendo DS. That counts as a constraint.
- Posted by Diederik Krols on January 3, 2012
WinRT, the new Windows 8 runtime for Metro applications, introduces a new interface for collection change notification. IObservableVector<T> replaces ye olde INotifyCollectionChanged. The ObservableCollection class still exists, you can continue to use it. Unfortunately its collection change events are ignored by the WinRT framework. I can assure you that this will give cross-platform developers a serious headache - or worse. Don't say I didn't warn you:

The IObservableVector<T> interface is defined, but the framework does not contain an implementation yet. There's no built-in collection that raises the new VectorChanged events. The fresh cocoon framework on CodePlex contains an implementation of ObservableVector<T>. Unsurprisingly it's a light-weight wrapper around an IList<T>. The class is described here.
Here's my own version of the class - I just adapted it to my property change notification mechanism:
namespace Mvvm
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
/// <summary>
/// IObservableVector<T> implementation.
/// </summary>
public class ObservableVector<T> : Collection<T>, INotifyPropertyChanged, IObservableVector<T>
{
// *** Events ***
public event PropertyChangedEventHandler PropertyChanged;
public event VectorChangedEventHandler<T> VectorChanged;
// *** Constructors ***
public ObservableVector()
: base()
{}
public ObservableVector(IList<T> list)
: base(list)
{}
// *** Protected Methods ***
protected override void ClearItems()
{
base.ClearItems();
this.PropertyChanged.Raise(this, o => o.Count);
this.PropertyChanged.Raise(this, o => o.Items);
this.OnVectorChanged(CollectionChange.Reset, 0);
}
protected override void InsertItem(int index, T item)
{
base.InsertItem(index, item);
this.PropertyChanged.Raise(this, o => o.Count);
this.PropertyChanged.Raise(this, o => o.Items);
this.OnVectorChanged(CollectionChange.ItemInserted, (uint)index);
}
protected override void RemoveItem(int index)
{
base.RemoveItem(index);
this.PropertyChanged.Raise(this, o => o.Count);
this.PropertyChanged.Raise(this, o => o.Items);
this.OnVectorChanged(CollectionChange.ItemRemoved, (uint)index);
}
protected override void SetItem(int index, T item)
{
base.SetItem(index, item);
this.PropertyChanged.Raise(this, o => o.Items);
this.OnVectorChanged(CollectionChange.ItemChanged, (uint)index);
}
// *** Event Handlers ***
protected void OnVectorChanged(CollectionChange collectionChange, uint index)
{
this.OnVectorChanged(new VectorChangedEventArgs(collectionChange, index));
}
protected virtual void OnVectorChanged(IVectorChangedEventArgs e)
{
if (this.VectorChanged != null)
this.VectorChanged(this, e);
}
// *** Private Sub-classes ***
private class VectorChangedEventArgs : IVectorChangedEventArgs
{
// *** Fields ***
private readonly CollectionChange collectionChange;
private readonly uint index;
// *** Constructors ***
public VectorChangedEventArgs(CollectionChange collectionChange, uint index)
{
this.collectionChange = collectionChange;
this.index = index;
}
// *** Properties ***
public CollectionChange CollectionChange
{
get
{
return this.collectionChange;
}
}
public uint Index
{
get
{
return this.index;
}
}
}
}
}
I consider this temporary code - I assume that next versions of WinRT will have a native version of ObservableVector<T>.
I built a small sample application around to demonstrate the usage of the class in a MVVM application: all the work is done through data and command bindings. The app just manages two collections of Dragons: 'All Dragons' and 'Favorites'. The selected Dragon in each ListBox can be moved to the other collection by clicking the buttons in the middle. Here's how the app looks like:

By the way, in the current version of WinRT -Developer Preview- the collection changed events are only handled if T is object, so you have to define the collection as follows:
public ObservableVector<object> Dragons { get; set; }
For any other type -like ObservableVector<string> or ObservableVector<Dragon>- the change events will be simply ignored by the binding mechanism. That's another headache
.
You use the class exactly the same way as good old ObservableCollection, e.g. as ItemsSource to a an ItemControl:
<ListBox DataContext="{Binding}"
ItemsSource="{Binding Dragons}"
SelectedItem="{Binding SelectedDragon, Mode=TwoWay}" />
Here's the full source code, it's built with Visual Studio 11 Developer Preview: U2UConsult.WinRT.ObservableVector.Sample.zip (47,83 kb)
Enjoy!
- Posted by Diederik Krols on December 27, 2011
This article demonstrates how to databind a radiobutton to an enumeration element, in a WinRT Metro application. The MVVM viewmodel has a property of an enumeration type, which is bound to the IsChecked property of some radiobuttons. A value converter compares the value from the viewmodel with an enumeration element that is provided as parameter to the converter. The Convert method returns true if both match, the ConvertBack method updates the bound value when the radiobutton is clicked or tapped.
Here's a screenshot of the attached sample application. The radiobuttons are bound to the CarColor property -an enumeration- of the viewmodel. The Vote-button updates that same property through a command:

The converter is much more complex than the WPF version from my previous article, it's even more complex than its corresponding Silverlight version that you can find here.
Here's a list of reasons why the implementation was not so straightforward:
- The x:Static markup extension is not allowed in a Metro application,
- Binding.DoNothing does not exist in WinRT, and
- unlike in WPF or Silverlight, the converter receives the enumeration value as an integer instead of a string.
When I observed all of this, my first reaction was AARGH!!! Don't worry: it was not a call of anger and frustration. In the noble Antwerp language aerg just means 'this is bad'. Non-believers: just follow this link.
As a result, the converter is much more complex than expected. It reconstructs the enumeration parameter from the binding expression by string parsing and reflection. Here's how it looks like:
namespace U2UConsult.WinRT.Converters
{
using System;
using System.Globalization;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Data;
/// <summary>
/// Converts an enum to a boolean.
/// </summary>
public class EnumToBooleanConverter : IValueConverter
{
/// <summary>
/// Compares the bound value with an enum param. Returns true when they match.
/// </summary>
public object Convert(object value, string typeName, object parameter, string language)
{
try
{
string parm = parameter.ToString();
int lastDot = parm.LastIndexOf(".");
string enumName = parm.Substring(0, lastDot);
string enumValue = parm.Substring(lastDot + 1);
Type t = Type.GetType(enumName);
string s = Enum.GetName(t, value);
object b = Enum.Parse(t, enumValue);
return b.ToString() == s;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// Converts the boolean back into an enum.
/// </summary>
public object ConvertBack(object value, string typeName, object parameter, string language)
{
try
{
string parm = parameter.ToString();
int lastDot = parm.LastIndexOf(".");
string enumName = parm.Substring(0, lastDot);
string enumValue = parm.Substring(lastDot + 1);
Type t = Type.GetType(enumName);
object b = Enum.Parse(t, enumValue);
return b;
}
catch (Exception)
{
return DependencyProperty.UnsetValue;
}
}
}
}
In your application, all you need to do is create an enumeration:
public enum CarColor
{
Yellow,
Red,
Pink,
Black
}
In the viewmodel, create a property of the enumeration type:
private CarColor carColor = CarColor.Black;
public event PropertyChangedEventHandler PropertyChanged;
public CarColor CarColor
{
get { return carColor; }
set {
this.carColor = value;
this.PropertyChanged.Raise(this, (o) => o.CarColor);
}
}
The propertychanged notification makes sure that the radiobutton follows all modifications of the property.
In the view, define the converter instance as a resource in XAML:
<UserControl.Resources>
<cv:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
</UserControl.Resources>
Bind the viewmodel's CarColor property to the Ischecked property of each radioButton. The enumeration value is provided as parameter to the converter with its fully qualified name. Also, you have to set the binding mode to TwoWay, and make sure that every radiobutton has its own GroupName. This is because we can't use Binding.DoNothing in the IValueConverter.ConvertBack Method. We always have to return the parameter, or DependencyProperty.UnsetValue. Both (re-)trigger all radiobuttons in the same group and that's not what we want; more info here.
Here's the full binding syntax in XAML:
<RadioButton Content="Giallo Modena"
GroupName="Yellow"
IsChecked="{Binding CarColor, Mode=TwoWay, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=U2UConsult.WinRT.DataBindingToEnum.ViewModels.CarColor.Yellow}" />
<RadioButton Content="Rosso Corsa"
GroupName="Red"
IsChecked="{Binding CarColor, Mode=TwoWay, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=U2UConsult.WinRT.DataBindingToEnum.ViewModels.CarColor.Red}" />
<RadioButton Content="Rosa Insapora"
GroupName="Pink"
IsChecked="{Binding CarColor, Mode=TwoWay, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=U2UConsult.WinRT.DataBindingToEnum.ViewModels.CarColor.Pink}" />
<RadioButton Content="Matte Nero"
GroupName="Black"
IsChecked="{Binding CarColor, Mode=TwoWay, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=U2UConsult.WinRT.DataBindingToEnum.ViewModels.CarColor.Black}" />
This solution is more error-prone and definitely slower than the WPF version, but it does the job. That's the good news. I also have bad news: the pink Ferrari photo is NOT photoshopped, aerg.
Anyway, here's the full source code. It was developed with Visual Studio 11 Developer Preview: U2UConsult.WinRT.DataBindingToEnum.zip (364,11 kb)
Enjoy!
- Posted by Diederik Krols on December 24, 2011
This article demonstrates how to databind a radiobutton to an enumeration element, in a WPF application. The MVVM viewmodel has a property of an enumeration type, which is bound to the IsChecked property of the radiobutton. A value converter compares the value from the viewmodel with an enumeration element that is provided as parameter to the converter. The Convert method returns true if both match, the ConvertBack method updates the bound value if there's no match.
Here's a screenshot of the attached sample application. The radiobuttons are bound to the Reindeer property -an enumeration- of the viewmodel. The Vote-button updates that same property through a command:

Here's the converter:
namespace U2UConsult.WPF.Converters
{
using System;
using System.Globalization;
using System.Windows.Data;
/// <summary>
/// Converts an enum to a boolean.
/// </summary>
public class EnumToBooleanConverter : IValueConverter
{
/// <summary>
/// Compares the bound value with an enum param. Returns true when they match.
/// </summary>
public object Convert(object value, Type targetType, object param, CultureInfo culture)
{
return value.Equals(param);
}
/// <summary>
/// Updates the bound value if it's different from the parameter.
/// </summary>
public object ConvertBack(object value, Type targetType, object param, CultureInfo culture)
{
return (bool)value ? param : Binding.DoNothing;
}
}
}
In your application, all you need to do is create an enumeration:
public enum Reindeer
{
Donner,
Blitzen,
Rudolph,
SantasLittleHelper
}
In the viewmodel, create a property of the enumeration type:
private Reindeer reindeer;
public event PropertyChangedEventHandler PropertyChanged;
public Reindeer Reindeer
{
get { return reindeer; }
set {
reindeer = value;
this.PropertyChanged.Raise(this, o => o.Reindeer);
}
}
The propertychanged notification makes sure that the radiobutton follows all modifications of the property.
In the view, define the converter instance as a resource in XAML:
<Window.Resources>
<cv:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
</Window.Resources>
Bind the viewmodel's property to the Ischecked property of each radioButton. The enumeration value is provided as parameter to the converter. Don't use the string representation of the element's value, but use the x:Static markup extension:
<RadioButton Content="Donner"
IsChecked="{Binding Reindeer,
Converter={StaticResource EnumToBooleanConverter},
ConverterParameter={x:Static vm:Reindeer.Donner}}" />
<RadioButton Content="Blitzen"
IsChecked="{Binding Reindeer,
Converter={StaticResource EnumToBooleanConverter},
ConverterParameter={x:Static vm:Reindeer.Blitzen}}" />
There you go!
Here's the WPF project: U2UConsult.WPF.DataBindingToEnum.zip (41,39 kb)
Enjoy!