Using the Windows 8.1 Hub as an ItemsControl 06 January 2014 Diederik-Krols WinRT This article presents a Windows 8.1 Hub control with ItemsSource and ItemTemplate properties, making it easily bindable and more MVVM-friendly. The Hub control has become the main host on the startup screen of many Windows Store apps: it’s flexible but still presents a standard look-and-feel with the title and section headers at the appropriate location, it nicely scrolls horizontally, and it comes with semantic zoom capabilities (well, at least with some help). Although it visually presents a list of items, it’s not an ItemsControl: the Hub control expects you to provide its sections and their corresponding data template more or less manually. Let’s solve that issue and create a Hub control that’s closer to an ItemsControl: I initially started by hooking up attached properties to the existing Hub class, but then I discovered that this class is not sealed. So I created a subclass, named ItemsHub: public class ItemsHub : Hub { // ... } Then I just added some of the missing properties as dependency properties (using the propdp snippet): ItemTemplate as a DataTemplate, and ItemsSource as an IList. public DataTemplate ItemTemplate { get { return (DataTemplate)GetValue(ItemTemplateProperty); } set { SetValue(ItemTemplateProperty, value); } } public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(ItemsHub), new PropertyMetadata(null, ItemTemplateChanged)); public IList ItemsSource { get { return (IList)GetValue(ItemsSourceProperty); } set { SetValue(ItemsSourceProperty, value); } } public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IList), typeof(ItemsHub), new PropertyMetadata(null, ItemsSourceChanged)); When ItemTemplate is assigned or changed, we iterate over all Hub sections to apply the template to each of them: private static void ItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ItemsHub hub = d as ItemsHub; if (hub != null) { DataTemplate template = e.NewValue as DataTemplate; if (template != null) { // Apply template foreach (var section in hub.Sections) { section.ContentTemplate = template; } } } } When ItemsSource is assigned or changed, we repopulate the sections and their headers from the source IList, and re-apply the data template (you should not make assumptions on the order in which the dependency properties are assigned): private static void ItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ItemsHub hub = d as ItemsHub; if (hub != null) { IList items = e.NewValue as IList; if (items != null) { hub.Sections.Clear(); foreach (var item in items) { HubSection section = new HubSection(); section.DataContext = item; section.Header = item; DataTemplate template = hub.ItemTemplate; section.ContentTemplate = template; hub.Sections.Add(section); } } } } Instead of defining a HeaderPath property, or creating a HeaderTemplate, I decided to fall back on the default template (a text block) and to assign the whole item to the section header. Now all you need to do to show a descent header is overriding the ToString method in the (View)Model class: public override string ToString() { return this.Name; } Here’s how to create an ItemsHub control in XAML and define the bindings to its new properties in a light-weight MVVM style: <Page.DataContext> <local:MainPageViewModel /> </Page.DataContext> <Page.Resources> <DataTemplate x:Key="DataTemplate"> <Image Source="{Binding Image}" /> </DataTemplate> </Page.Resources> <Grid> <local:ItemsHub Header="Hub ItemsControl Sample" ItemTemplate="{StaticResource DataTemplate}" ItemsSource="{Binding Manuals}" /> </Grid> Here’s the result in the attached sample app. Each Hub section represents a business object (an Ikea Instruction Manual) from a collection in the ViewModel: I focused on the properties that make the most sense in MVVM apps, but -as I mentioned- the framework Hub class is not sealed. So you can use this same technique to add other useful properties like Items and DataTemplateSelector. Here’s the full code, it was written with Visual Studio 2013 for Windows 8.1: U2UConsult.WinRT.HubItemsControl.zip (759.57 kb) Enjoy!Diederik
Using Lex.DB as a local storage in a Windows 8 Store app 10 December 2013 Diederik-Krols WinRT Lex.DB is a lightweight, in-process database engine, completely written in C#. It can be used on .NET 4+, Silverlight 5+, Windows Phone 8+, WinRT, and Android (through Xamarin). That makes it a direct competitor against SQLite. The latter seems to become the de facto standard for storing structured data in Store Apps. Now while SQLite is technology neutral, unfortunately it’s not processor neutral. In a Windows 8 Store app, the dependency on SQLite requires you to create x64, x86, and ARM specific packages. As a side effect, this screws up the Visual Studio XAML Designer on your 64-bit development machine. Embedding processor-specific components has a negative impact on development, debugging, and deployment. That’s a high price to pay. So I went looking for a developer-friendly storage engine that doesn’t have these issues, and that’s how I came across Lex.DB. I created a Windows 8.1 MVVM Store App that maintains a local cache of representative business objects. Here’s how the app looks like: You may recognize this app from my previous blog post on SQLite. It’s the exact same app indeed; the migration from SQLite to Lex.DB took me less than 10 minutes. And I love the result. The easiest way to install Lex.DB is through NuGet: You’ll end up with just a reference to a .dll, the opportunity to create a processor-neutral app package, and an operational Visual studio XAML designer: Unlike SQLite, the business object does not have to be decorated with attributes. Here’s the Person class of which I’ll store some instances: internal class Person { /// <summary> /// Gets or sets the identifier. /// </summary> public int Id { get; set; } /// <summary> /// Gets or sets the name. /// </summary> public string Name { get; set; } /// <summary> /// Gets or sets the description. /// </summary> public string Description { get; set; } /// <summary> /// Gets or sets the status. /// </summary> /// <remarks>Is an enum in the viewmodel.</remarks> public int Status { get; set; } /// <summary> /// Gets or sets the picture. /// </summary> /// <remarks>Is a blob in the database.</remarks> public byte[] Picture { get; set; } } Although it's persisted, you need to initialize the database once, every time your app runs. It has to have a name, as well as the list of mappings to the model classes that you want to store in it. You put code like this e.g. in the OnNavigatedTo event of the main page of your app, or -like I did- in the static constructor of your data access layer class: private static DbInstance db; static Dal() { // Create database db = new DbInstance("storage"); // Define table mapping // * 1st parameter is primary key // * 2nd parameter is autoGen e.g. auto-increment db.Map<Person>().Automap(p => p.Id, true); // Initialize database db.Initialize(); } AutoMap creates a table field for each class property. Its first parameter indicates the primary key, the second parameter is optional, it determines whether or not the primary key value will be automatically generated.After initialization, the DB is ready to use. This is the list of calls in the data access layer of the sample app: public static List<Person> GetAllPersons() { return db.Table<Person>().LoadAll().ToList(); } public static Person GetPersonById(int id) { return db.Table<Person>().LoadByKey(id); } public static void SavePerson(Person person) { db.Table<Person>().Save(person); } public static void DeletePerson(Person person) { db.Table<Person>().Delete(person); } Admit it: CRUD operations don't get easier than this. There’s also a purge statement to clear a table or the whole database; and the save and delete methods have an overload that takes a list of objects. These came in handy for (re-)populating the initial table: public static async Task InitializePersonTable() { // Clear table db.Table<Person>().Purge(); // (Re-)Populate table List<Person> persons = new List<Person>(); Person person = new Person(); person.Id = 1; // Person properties persons.Add(person); person = new Person(); person.Id = 2; // Person properties persons.Add(person); // More of these ... db.Table<Person>().Save(persons); } By the way: all calls do exist in a synchronous and an asynchronous implementation. So after less than ten minutes, I ended up with a cleaner data access layer, a model class without technical attributes, a processor-neutral app package, and an operational Visual Studio XAML Designer. SQLite is nice, but when you’re less interested in transactions, referential integrity, and SQL languages, then Lex.DB may be a better choice to store local data in a Windows 8 Store app. Here’s the full code of the sample project. Is was written in Visual Studio 2013 for Windows 8.1: U2UC.WinRT.LexDbSample.zip (1.70 mb) Enjoy,Diederik
Using SQLite in a Windows Store MVVM App 05 December 2013 Diederik-Krols WinRT Some of my Windows Store Apps are desperately seeking for a local database. I was getting tired of waiting on Microsoft to release a SQL Express for WinRT - which as far as I know, was never planned. So I decided to test-drive SQLite: a free, technology neutral, self-contained, zero-configuration, transactional SQL database engine. I created a small but representative Windows 8.1 MVVM Store app that creates a database and executes the common CRUD operations against a list of business objects. The business object not only has common properties of the integer and string data types, but it also hosts an enumeration and a picture. Here’s how the sample app looks like: Although it's a single project, the app is structured like a full-fledged layered MVVM application. It contains the mandatory MVVM infrastructure that is still missing in the .NET framework: a base class to propagate changes, and a delegatecommand a.k.a. relaycommand. [Redmont: you may take this as a hint.] On top of that, the app strictly separates data access, models, viewmodels, and views: Let's get our hands dirty. Before you can start using SQLite, you have to install the engine and SDK. I installed the prerelease of SQLite for Windows Runtime 8.1 which comes as a Visual Studio Extension: To use the SDK, you have to reference it in your Visual Studio project, together with the C++ Runtime Package: Unfortunately you will now have to select a target platform in your Visual Studio to build against. ‘Any CPU’ is not allowed anymore. I’ll come back to that later... Next to the SDK you also have to install a .NET wrapper to talk to it. I went for SQLite.NET and installed it through Tim Heuer’s NuGet package: SQLite-Net adds two C# files to your project: SQLite.cs and SQLiteAsync.cs. I love that source code approach: it allows you to see and tweak the code (e.g. change the namespace), and place breakpoints during debugging. By the way: there are more wrappers available, such as sqlite-winrt on CodePlex. A SQLite database is just a flat file. All you have to do is decide where to store it, and then access it through an IDisposable connection – as if it were any other ADO.NET store: string dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "Storage.sqlite"); using (var db = new SQLiteConnection(dbPath)) { // ... } The easiest way to create a table is the code-first approach that we know from entity framework. All you need to do is decorating a model class with the appropriate attributes. SQLite supports declarative … hmm … declarations for primary keys, identities (auto increment), constraints, etcetera. There’s a full list in the SQLite.cs class. Here’s the model class from the sample project: /// <summary> /// Represents a person. /// </summary> internal class Person { /// <summary> /// Gets or sets the identifier. /// </summary> [PrimaryKey, AutoIncrement] public int Id { get; set; } /// <summary> /// Gets or sets the name. /// </summary> [MaxLength(64)] public string Name { get; set; } /// <summary> /// Gets or sets the description. /// </summary> public string Description { get; set; } /// <summary> /// Gets or sets the status. /// </summary> /// <remarks>Is an enum in the viewmodel.</remarks> public int Status { get; set; } /// <summary> /// Gets or sets the picture. /// </summary> /// <remarks>Is a blob in the database.</remarks> public byte[] Picture { get; set; } } The Status field –an integer- actually comes from an enumeration. SQLite does support foreign key relationships but that would be overkill in this simple scenario. The person’s Picture will be stored inside the table, as a byte array. To create the table you don’t need to know the syntax. The SQLite attributes will be used to define and configure the fields of the table. This is all it takes to create the Person table: public static void CreateDatabase() { // Create a new connection using (var db = new SQLiteConnection(DbPath)) { // Create the table if it does not exist var c = db.CreateTable<Person>(); } } Later on, you can call GetMapping to verify the mappings between table fields and class properties: var info = db.GetMapping(typeof(Person)); To (re-)populate the table with some records, I created some instances of the Person class. To create a new record, or modify an existing one, all you have to do is this: var i = db.InsertOrReplace(person); This call conveniently returns the primary key value of the record. In the sample app, I don't really need this because the Model stays referenced by the ViewModel while it is inserted in the database. This is the kind of shortcuts you can take in a single-tier app. InsertOrReplace will use the primary key you provide. To force the insertion of a new record with auto-generation of a new primary key, you have to call the Insert method. So here’s how the SavePerson method in my data access layer looks like: public static void SavePerson(Person person) { using (var db = new SQLiteConnection(DbPath)) { // Activate Tracing db.Trace = true; if (person.Id == 0) { // New db.Insert(person); } else { // Update db.Update(person); } } } For selecting the list of persons in the table, LINQ is your friend: public static List<Person> GetAllPersons() { List<Person> models; using (var db = new SQLiteConnection(DbPath)) { // Activate Tracing db.Trace = true; models = (from p in db.Table<Person>() select p).ToList(); } return models; } The same is true when you want to seek a specific person: public static Person GetPersonById(int Id) { using (var db = new SQLiteConnection(DbPath)) { Person m = (from p in db.Table<Person>() where p.Id == Id select p).FirstOrDefault(); return m; } } By the way, SQLite allows you to place an index on columns that you use frequently in the WHERE-clause: just decorate these with the Indexed attribute. The following delete statement should not come as a surprise: db.Delete(person); But you could also use the underlying SQL language to do the trick: db.Execute("DELETE FROM Person WHERE Id = ?", person.Id); If you activate the tracing (the "db.Trace = true;" statement) during debugging, then you can nicely follow what the SQLite engine is doing - and learn the syntax at the same time: So far for the Model and the Data Access Layer. Let’s take a look at the ViewModels. The PersonViewModel wraps most of the Model’s properties in a very straightforward way: public string Description { get { if (this.model == null) { return string.Empty; } return this.model.Description; } set { if (this.model != null) { this.model.Description = value; this.OnPropertyChanged(); } } } Of course, there are a couple of exceptions. As I already mentioned, the Status property in the Person Model –and hence in the SQLite table- is an integer. Its value will come from an enumeration: internal enum Status { Good, Neutral, Evil } So in the ViewModel we’ll implement a small conversion: public Status Status { get { if (this.model == null) { return Status.Neutral; } return (Status)this.model.Status; } set { if (this.model != null) { this.model.Status = (int)value; } } } In the View however, we’re interested in the string representation. So the ViewModel has an extra property to which the View can two-way-bind: public string StatusString { get { return this.Status.ToString(); } set { this.Status = (Status)System.Enum.Parse(typeof(Status), value); } } I’m using an EnumerationSlider to allow the user to modify the value: <controls:EnumerationSlider Enumeration="U2UC.WinRT.SQLiteSample.ViewModels.Status" Value="{Binding StatusString, Mode=TwoWay}" /> Another less straightforward wrapper in the ViewModel is the one for the picture. When the value of the picture is loaded into the ViewModel (from the Model when it is read from the database, or from a file when the user uploads it in Edit mode) it will be as an array of bytes. However, when the picture needs to be displayed in a View, it needs to be an ImageSource. This means we end up with an asymmetric property, with a getter and a setter of a different type. That’s not allowed in .NET, so we need to define two separate properties: public ImageSource ImageSource { get { if (this.model != null && this.picture == null) { this.picture = this.model.Picture.AsBitmapImage(); } return this.picture; } } public byte[] Picture { set { this.picture = null; this.model.Picture = value; this.OnPropertyChanged("ImageSource"); } } Further, we need a couple of methods to translate a storage file into a byte array, and a byte array into a bitmap. I implemented these as extension methods: public static async Task<byte[]> AsByteArray(this StorageFile file) { IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read); var reader = new Windows.Storage.Streams.DataReader(fileStream.GetInputStreamAt(0)); await reader.LoadAsync((uint)fileStream.Size); byte[] pixels = new byte[fileStream.Size]; reader.ReadBytes(pixels); return pixels; } public static BitmapImage AsBitmapImage(this byte[] byteArray) { if (byteArray != null) { using (var stream = new InMemoryRandomAccessStream()) { stream.WriteAsync(byteArray.AsBuffer()).GetResults(); // I made this one synchronous on the UI thread; this is not a best practice. var image = new BitmapImage(); stream.Seek(0); image.SetSource(stream); return image; } } return null; } Here’s how the sample app looks like in Edit/Insert mode, showing an EnumerationSlider and an Image Upload button: Here’s the full source code. It was written in Visual Studio 2013 and is targeting Windows 8.1: U2UC.WinRT.SQLiteSample.zip (1.18 mb) Enjoy,Diederik P.S.I promised to come back to the target processor selection. If your development machine is a 64bit machine (which it most probably is) then you have bad luck. If you target x64, then your Visual Studio XAML Designer will give up on you: If you target x86, the Designer will work: … but you can’t run the solution anymore: So if you need the XAML Designer, you just have to temporarily switch to x86 mode. It's uncomfortable, but it works.
Drawing a Circular Gradient in Windows Store and Windows Phone apps 15 November 2013 Diederik-Krols Windows Phone, WinRT This article shows a way to easily create a circular gradient effect in a Windows Store app or a Windows Phone app. The standard linear and radial gradients are nice, but they do not allow you to draw something like this: <Spoiler> There’s no magic involved. </Spoiler> What we’re doing here is just drawing a bunch of arcs at the appropriate place and in the appropriate color. Fortunately we have some helper classes for each task at hand. First there is the RingSlice control from WinRT XAML Toolkit. To use it, you can reference the framework dll’s in your app, e.g. through Nuget. Alternatively, you can copy the RingSlice and PropertyChangeEventSource classes from the toolkit's source code into your app. That’s what I did for this sample, because I also wanted to build a Phone version. Here’s an artist impression of the RingSlice’s main characteristics: The RingSlice control uses the center of its host container as the reference. So you don’t have to refresh your trigonometry knowledge to calculate the absolute position of the arc. In order to simulate a circular gradient, we’re going to put a collection of such RingSlices next to each other, and give them a color variation. That color shift is calculated using an extension method of (the source) Color that takes the target color and a percentage as parameters: // Interpolates two colors public static Color Interpolate(this Color color1, Color color2, double fraction) { if (fraction > 1) { fraction = 1; } if (fraction < 0) { fraction = 0; } Color result = new Color(); result.A = 255; result.R = (byte)(color1.R * fraction + color2.R * (1 - fraction)); result.G = (byte)(color1.G * fraction + color2.G * (1 - fraction)); result.B = (byte)(color1.B * fraction + color2.B * (1 - fraction)); return result; } Here’s the code that draws one of the quarters of the first image (Color from Yellow to Green, StartAngle from 0 to 89): XAML <Viewbox> <Grid x:Name="GradientHost" Height="600" Width="600" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Viewbox> C# for (int i = 0; i < 90; i++) { Brush brush = new SolidColorBrush(Colors.Green.Interpolate(Colors.Yellow, (double)i / 90)); this.GradientHost.Children.Add( new RingSlice() { StartAngle = i, EndAngle = i + 1, Fill = brush, Radius = 300, InnerRadius = 150, Stroke = brush } ); } I used this technique to draw gradient scales behind the Modern Radial Gauge for Windows 8.* and Windows Phone 8.Just put the Gauge inside a ViewBox, together with a container to host the circular gradient, like this: <Viewbox> <Grid> <Grid x:Name="ScaleGrid" Height="200" Width="200" /> <controls:Gauge ScaleBrush="Transparent" ScaleTickBrush="Transparent" TickBrush="Transparent" TrailBrush="Transparent" /> </Grid> </Viewbox> … and draw the RingSlices in a little loop. For determining the Radius and InnerRadius, you consider the size of the host (200x200 in the sample, while the ViewBox will take care of scaling). For the StartAngle and EndAngle all you have to consider is the number of segments you want to draw, and the range - the main arc of the Gauge sweeps from -150° to 150°: for (int i = 0; i < 100; i++) { double startAngle = (i * 3) - 150; Brush brush = new SolidColorBrush(Colors.MidnightBlue.Interpolate(Colors.Lavender, (double)i / 100)); this.ScaleGrid.Children.Add( new RingSlice() { StartAngle = startAngle, EndAngle = startAngle + 3, Fill = brush, Stroke = brush, Radius = 80, InnerRadius = 50 }); } Here are some examples of the radial gauges with a circular gradient scale, on Windows 8: … and Windows Phone: Here’s the source code with the helper classes. It was written in Visual Studio 2012: U2UC.WinRT.CircularGradientSample.zip (353.46 kb) Enjoy,Diederik
An auto-hyperlinking RichTextBlock for Windows 8.1 Store apps 29 October 2013 Diederik-Krols WinRT This article shows how to let a XAML RichTextBlock control detect URLs and email addresses in its raw text, and show these as hyperlinks. The code only applies to Windows 8.1 because I’m using the brand new Hyperlink control. Here’s a screenshot of the attached sample app. There’s a regular textbox on top in which you can type whatever you like, the ‘Assign’ button sends your text to the pimped RichTextBlock at the bottom. This will transform all URLs and email addresses from the raw text into an operational hyperlink: Unfortunately, the RichTextBlock control lives in a sealed class, so putting the logic in a child class was not an option. So I decided to go for an attached property called “RawText”: /// <summary> /// Ads auto-hyperlinking to a RichTextBlock control. /// </summary> public static class HyperlinkExtensions { /// <summary> /// The raw text property. /// </summary> public static readonly DependencyProperty RawTextProperty = DependencyProperty.RegisterAttached("RawText", typeof(string), typeof(RichTextBlock), new PropertyMetadata("", OnRawTextChanged)); /// <summary> /// Gets the raw text. /// </summary> public static string GetRawText(DependencyObject obj) { return (string)obj.GetValue(RawTextProperty); } /// <summary> /// Sets the raw text. /// </summary> public static void SetRawText(DependencyObject obj, string value) { obj.SetValue(RawTextProperty, value); } /// <summary> /// Called when raw text changed. /// </summary> private static void OnRawTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // Transformation logic ... } } In that same class I also defined an extension method that allows you to easily assign the raw text to the control: /// <summary> /// Sets the raw text. /// </summary> /// <remarks>Extension method.</remarks> public static void AssignRawText(this RichTextBlock rtb, string value) { rtb.SetValue(RawTextProperty, value); } Strangely, I could not name this extension method SetRawText(), because the C# compiler considered it a duplicate of the setter for the attached property. [Yes, I realize that it *is* a duplicate. But in Windows 8.0 I could get away with this, and that makes it ‘strangely’...] You can assign the property in C#: this.OutputBox.AssignRawText(this.InputBox.Text); ... or in XAML: <RichTextBlock x:Name="OutputBox" hyper:HyperlinkExtensions.RawText="Your raw text here." /> The ‘hyperlinkables’ are detected by a regular expression that I found over here. The URLs and email addresses are added as Hyperlink to the Inlines collection of a Paragraph in the Block collection of the RichTextBlock. The rest of the raw text is added as plain Run instances. What I like about the regex is that it also detects the URLs without a protocol (like www.u2uconsult.com). These look nice in the text, but for the NavigateUri property of the Hyperlink, it’s better to add the protocol. Here’s the full transformation logic: /// <summary> /// Called when raw text changed. /// </summary> private static void OnRawTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RichTextBlock rtb = (RichTextBlock)d; if (rtb != null) { // Working variables. string result = string.Empty; int index = 0; Paragraph par = new Paragraph(); string text; Run run; Hyperlink link; string source = e.NewValue.ToString(); // Regex initialization. string pattern = @"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\jQuery15206922996124803609_1383046336084(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)"; Regex regex = new Regex(pattern); var matches = regex.Matches(source); foreach (Match match in matches) { // Add text before match. int matchIndex = match.Index; text = source.Substring(index, matchIndex - index); run = new Run(); run.Text = text; par.Inlines.Add(run); // Add match as hyperlink. string hyper = match.Value; link = new Hyperlink(); run = new Run(); run.Text = hyper; link.Inlines.Add(run); // Complete link if necessary. if (!hyper.Contains("@") && !hyper.StartsWith("http")) { hyper = @"http://" + hyper; } if (hyper.Contains("@") && !hyper.StartsWith("mailto")) { hyper = @"mailto://" + hyper; } link.NavigateUri = new Uri(hyper); par.Inlines.Add(link); index = matchIndex + match.Length; } // Add text after last match. text = source.Substring(index, source.Length - index); run = new Run(); run.Text = text; par.Inlines.Add(run); // Update RichTextBlock content. rtb.Blocks.Clear(); rtb.Blocks.Add(par); } } Here’s how the sample app looks like when I tapped the URL link: ... and the e-mail address: Here’s the sample app. It was written in the VS2013 preview for the Windows 8.1 preview: U2UC.WinRT.HyperlinkBox.zip (148.67 kb) Enjoy!Diederik
An Image Cropper control for Windows 8 Store apps 11 October 2013 Diederik-Krols WinRT This article presents a Windows 8 Store app XAML control that allows the user to select an area in a displayed image, and get a reference to that area as a writeable bitmap. [More]
Reusing Vector Graphics in Windows 8 Store Apps 26 August 2013 Diederik-Krols WinRT The Flat Design paradigm and the related anti-skeumorphism movement make bitmap images less and less popular in today's apps and applications. Everywhere in the user interface, PNG's and JPG's are being replaced by crisp scalable light-weight vector graphics. In the XAML world these vector graphics are represented by instances of the PathGeometry class. Recently I spent some time looking for a way to reuse Path objects in Windows 8 Store apps - and at the same time in different versions of WPF (our customers also want flat design in their Windows applications). Ideally, you should define a PathGeometry only once -e.g. as a Resource- and then reuse it in an app in multiple views, with different sizes and colors, preferably leveraging the data binding power of the XAML engine. I tried several approaches, and eventually ended up with creating a new custom control, the IconControl. Here's an example of the result. It displays a horizontal StackPanel with several instances of the same complex XAML icon -the prancing horse from a well known car brand- in different colors and sizes: The corresponding XAML looks like this: <local:IconControl Height="100" Width="100" Padding="20" Background="White" Foreground="PaleGreen" Data="{StaticResource PrancingString}" /> <local:IconControl Height="100" Width="100" Padding="10" Background="PaleGreen" Foreground="White" Data="{StaticResource PrancingString}" /> <local:IconControl Height="100" Width="100" Padding="20" Background="White" Foreground="Pink" Data="{StaticResource PrancingString}" /> <!-- etcetera --> I realize that is seems overkill to create a custom control to just display a Path, but I didn't find a light-weigth alternative. Here are some of my attempts. I started with defining a full Path object as a resource, like this: <Path x:Key="PrancingHorse" Data="M22.923445,61.752014L22.733789,61.759857 22.468277,61.918045 (... there's more ...) 20.410011,0.88699341z" Fill="#FFFFFFFF" /> I hoped to be able to use the resource in a view, e.g. like this: <ContentControl Content="{StaticResource PrancingHorse}" /> There's design time support in Visual Studio: Unfortunately, this is what happens at run-time: The next attempt was to store the PathGeometry as a Resource. I intended to use it in the views like this: <Path Data="{StaticResource PrancingGeometry}" /> That sounds nice, except that it doesn't seem possible to define the PathGeometry as a resource. There are no type converters available to translate the path string into a PathGeometry's Segment or Figure. The following two resources are not accepted: <PathGeometry x:Key="PrancingGeometry">No TypeConverter</PathGeometry> <PathGeometry x:Key="PrancingGeometry" Figures="No TypeConverter"> <PathFigure Segments="No TypeConverter" /> </PathGeometry> After a couple of iterations, I concluded that the only way to reuse a path was to store it as a resource of type String: <x:String x:Key="PrancingString">M22.923445,61.752014L22.733789,61.759857 22.468277,61.918045 (... there's more ...) 20.410011,0.88699341z</x:String> This resource can be reused in multiple views, like this: <Border Height="200" Width="200" BorderBrush="Black" Padding="20"> <Viewbox Stretch="Uniform"> <Path Data="{StaticResource PrancingString}" Fill="Red" /> </Viewbox> </Border> Of course, giving each occurence a different size, margin, foreground and background color would require copy-pasting a large chunk of XAML. So I moved that chunk of XAML into a control template. I created a new custom control, with a dependency property called Data to store a PathGeometry, and gave it the following default style: <Style TargetType="local:IconControl"> <Setter Property="Padding" Value="0" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:IconControl"> <Grid Background="{TemplateBinding Background}"> <Path Data="{TemplateBinding Data}" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Margin="{TemplateBinding Padding}" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> Then, the lack of type converters in WinRT hit me again. When the dependency property was defined as String, nothing appeared in the control. When the dependency property was defined as PathGeometry, I recieved an exception at design time: And the control remained empty at runtime. So I decorated the control with two properties: Data as a String and DataGeometry as a PathGeometry. The idea was to use the string in the binding (as Data= "{...}"): <local:IconControl Height="200" Width="200" Padding="20" Background="Yellow" Foreground="Black" Data="{StaticResource PrancingString}" /> ... and to use the geometry in the control's template (in "TemplateBinding DataGeometry"): <ControlTemplate TargetType="local:IconControl"> <Grid Background="{TemplateBinding Background}"> <Path Data="{TemplateBinding DataGeometry}" Fill="{TemplateBinding Foreground}" Stretch="Uniform" Margin="{TemplateBinding Padding}" /> </Grid> </ControlTemplate> Here's the control's code: /// <summary> /// Displays a Path. /// </summary> public sealed class IconControl : Control { public static readonly DependencyProperty DataGeometryProperty = DependencyProperty.Register("DataGeometry", typeof(PathGeometry), typeof(IconControl), new PropertyMetadata(null)); public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(String), typeof(IconControl), new PropertyMetadata(null, new PropertyChangedCallback(OnDataChanged))); public IconControl() { this.DefaultStyleKey = typeof(IconControl); } // Write-only to be used in a binding. public String Data { private get { return (String)GetValue(DataProperty); } set { SetValue(DataProperty, value); } } // Read-only to be used in the control's template. public PathGeometry DataGeometry { get { return (PathGeometry)GetValue(DataGeometryProperty); } private set { SetValue(DataGeometryProperty, value); } } private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { // Convert the String into a PathGeometry // ... } } The only thing left now, was to write the code to convert the String into a PathGeometry. In WPF this is literally a one-liner: ic.DataGeometry = PathGeometry.CreateFromGeometry(PathGeometry.Parse(e.NewValue.ToString())); In the Windows Store App API, the Parse method is missing, as well as the PathFigureCollectionConverter. My favorite search engine brought me to this ancient String-to-PathGeometry Converter. It was written for SilverLight 2, but also does the trick in WinRT! I just had to change some namespaces when copying the code into a new class, a PathGeometryParser that converts a String into a PathGeometry, and back: Using that class, the conversion is still a one-liner: ic.DataGeometry = new PathGeometryParser().Parse(e.NewValue.ToString()); I would prefer an implementation of the Parse method as an Extension Method to String (e.g. AsPathGeometry), but I'm happy it works. The new IconControl can be used to draw and redraw vector graphics with bindable path, size, and colors - as you saw in the beginning of this article. Here's a screenshot of the sample app that includes the IconControl and some other experiments to reuse a Path icon: Here's the source code: U2UConsult.WinRT.ShapesReuse.zip (149.51 kb) Enjoy!Diederik
Binding a Slider to an Enumeration in a Windows 8 Store app 22 July 2013 Diederik-Krols WinRT Very often the values inside an enumeration type represent a sequence or a ranking, like small-medium-large or good-better-best. In a UI it would be appropriate to represent such a field through a slider control. This article explains how to build such a slider in XAML and C# and how to use it in a MVVM Windows 8 Store app. The slider is implemented as a lightweight user control to allow maximum templatability. The template just comes with a TextBlock that displays the value, and a Slider to change that value. Here’s the template: <Style TargetType="local:EnumerationSlider"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:EnumerationSlider"> <StackPanel> <TextBlock Name="PART_TextBlock" Text="{TemplateBinding Value}" FontSize="24" /> <Slider Name="PART_Slider" SnapsTo="StepValues" StepFrequency="1" IsThumbToolTipEnabled="False" /> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> The control has two properties, implemented as Dependency Property. Enumeration is the string that contains the fully qualified name of the Enum to which you want to bind, and Value is the property that holds the current enumeration value as a string. When the Enumeration property is assigned, we populate an internal collection with the enumeration values. The Slider's steps represent the index in that collection, so we reset its maximum to the number of items in the enumeration (minus one). Here’s that process: private List<string> names; private static void OnEnumerationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { EnumerationSlider es = d as EnumerationSlider; if (es != null) { Type t = Type.GetType(es.Enumeration); es.names = Enum.GetNames(t).ToList(); var slider = es.GetTemplateChild(SliderPartName) as Slider; if (slider != null) { slider.Value = 0; slider.Maximum = es.names.Count() - 1; } } } When the viewmodel triggers a value change –e.g. when initializing a binding- we calculate the numeric value for the Slider by looking it up in the private names collection: private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { EnumerationSlider es = d as EnumerationSlider; if (es != null) { var slider = es.GetTemplateChild(SliderPartName) as Slider; if (slider != null) { slider.Value = es.names.IndexOf(es.Value.ToString()); } } } The other way round, when the Slider is pushed by the user, we continuously update the control’s Value property: protected override void OnApplyTemplate() { var slider = this.GetTemplateChild(SliderPartName) as Slider; if (slider != null) { slider.ValueChanged += Slider_ValueChanged; } // ... } private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e) { this.Value = this.names[(int)(sender as Slider).Value]; } The control is ready now, it can be bound to any enumeration. So let’s first define some enumerations. They represent the size and temperature of Starbucks coffees: namespace Enumerations { public enum Sizes { Demi, @Short, Tall, Grande, Venti, Trenta } public enum Temperatures { Cold, LukeWarm, Warm, Hot, Boiling } } Here’s a screenshot of the demo app. The two sliders on it are bound to two different enumerations: The EnumerationSlider exposes its Value as a string, not as an instance of the linked Enumeration type. So it cannot be bound to a viewmodel’s Enum-type property through a TwoWay Binding. When you move the Slider, an "Error: Cannot save value from target back to source." will be produced. You can solve that problem with a ValueConverter, but then you would need to write one for each enumeration type, and use it in every binding. You could also create a wrapper class for each enumeration that hosts the string-to-value conversion. If you search for ‘BindableEnum’ you’ll find examples of this. I personally prefer to decorate the viewmodel with a wrapper property of type string that passes the value to the 'real' property, like this: public class MainPageViewModel : BindableBase { private Sizes coffeeSize = Sizes.Grande; /// <summary> /// Coffee Size property as it comes directly from the Mvvm Model. /// </summary> public Sizes CoffeeSize { get { return coffeeSize; } set { this.SetProperty(ref this.coffeeSize, value); this.OnPropertyChanged("CoffeeString"); } } /// <summary> /// Wrapper around the CoffeeSize property to make it bindable. /// </summary> public string CoffeeString { get { return this.coffeeSize.ToString(); } set { this.CoffeeSize = (Sizes)System.Enum.Parse(typeof(Sizes), value); } } // ... } That code may look cumbersome, but at least it’s in the correct place. The extra property makes the model easily bindable to the view. That’s exactly what a viewmodel is supposed to do. Here’s how to bind viewmodel to the control: <controls:EnumerationSlider Enumeration="Enumerations.Sizes" Value="{Binding CoffeeString, Mode=TwoWay}" /> <controls:EnumerationSlider Enumeration="Enumerations.Temperatures" Value="{Binding TemperatureString, Mode=TwoWay}" /> That's it! We now have a Slider that's two-way-bindable to any enumeration property of a viewmodel. Here’s the code: U2UConsult.WinRT.EnumerationSlider.zip (493.88 kb)Enjoy! Diederik
A Modern UI radial gauge control for Windows 8 Store apps 24 June 2013 Diederik-Krols WinRT Recently I had the amazing opportunity to briefly work together with Arturo Toledo and his great team of designers from Toledo2. This article presents one of the artefacts of that cooperation. It’s a Modern UI radial gauge control for Windows 8 Store apps. Arturo Toledo did the hard work of designing it, I merely wrote an implementation of it in C# and XAML. Here are some examples of how the control may look like in an app. Yes, these are all instances of one and the same control type: Stunning, right? And I did not even start templating it… Here’s how I named the graphical regions in the control’s default style: This is the list of configurable properties: Minimum: minimum value on the scale (double) Maximum: maximum value on the scale (double) Value: the value to represent (double) ValueStringFormat: StringFormat to apply to the displayed value (string) Unit: unit measure to display (string) NeedleBrush: color of the needle (Brush) TickBrush: color of the outer ticks (Brush) ScaleWidth: thickness of the scale in pixels – relative to the control’s default size (double) ScaleBrush: background color of the scale (Brush) ScaleTickBrush: color of the ticks on the scale (Brush) TrailBrush: color of the trail following the needle (Brush) ValueBrush: color of the value text (Brush) UnitBrush: color of the unit measure text (Brush) Here's how to define an instance of this gauge in your XAML: <controls:Gauge Minimum="0" Maximum="100" Height="{Binding Size}" Value="{Binding Value}" TickBrush="Transparent" ScaleTickBrush="Transparent" NeedleBrush="SaddleBrown" TrailBrush="SaddleBrown" ValueBrush="SaddleBrown" Unit="bottles of beer on the wall" UnitBrush="SaddleBrown"> <controls:Gauge.ScaleBrush> <SolidColorBrush Color="SaddleBrown" Opacity=".2" /> </controls:Gauge.ScaleBrush> </controls:Gauge> All of the properties are implemented as Dependency Properties. This code –generated through the ‘propdp’ code snippet- actually accounts for more than 50% of the code-behind of the gauge. I’m not going to dive deeply in the implementation, since I already did that in this article on building custom controls. That article also presents a radial gauge - from which I borrowed the needle and ticks code. That gauge definitely looks skeumorphic compared to the new one. For the different colors I did not use properties of type Color or String, but Brush. This gives code completing and designer support in Visual Studio: It also gives you the possibility to work with LinearGradientBrush or more exotic Brush types if you want. The main beef of the source code draws the scale in OnApplyTemplate, and redraws the needle and trail in OnValueChanged. To keep these calculations simple, I embedded the whole control in a ViewBox with a fixed width and height of 200 pixels. Here’s the structure of the control’s default style: <Style TargetType="local:Gauge"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:Gauge"> <Viewbox> <Grid Height="200" Width="200"> <!-- Ticks --> <ItemsControl ItemsSource="{TemplateBinding Ticks}" VerticalAlignment="Center" HorizontalAlignment="Center"> <!-- ... --> </ItemsControl> <!-- Scale --> <Path Name="PART_Scale" Stroke="{TemplateBinding ScaleBrush}" StrokeThickness="{TemplateBinding ScaleWidth}" /> <!-- Trail --> <Path Name="PART_Trail" Stroke="{TemplateBinding TrailBrush}" StrokeThickness="{TemplateBinding ScaleWidth}" /> <!-- Scale Ticks --> <ItemsControl ItemsSource="{TemplateBinding Ticks}" VerticalAlignment="Center" HorizontalAlignment="Center"> <!-- ... --> </ItemsControl> <!-- Value and Unit --> <StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Center"> <TextBlock Name="PART_ValueText" Foreground="{TemplateBinding ValueBrush}" FontSize="20" FontWeight="SemiBold" Text="{TemplateBinding Value}" TextAlignment="Center" Margin="0 0 0 2" /> <TextBlock Foreground="{TemplateBinding UnitBrush}" FontSize="16" TextAlignment="Center" Text="{TemplateBinding Unit}" Margin="0" /> </StackPanel> <!-- Needle --> <Grid> <!-- ... --> <Path Name="PART_Needle" Stretch="Uniform" HorizontalAlignment="Center" Fill="{TemplateBinding NeedleBrush}" Data="M 0,0 l 0,100 l 5,0 l 0,-100 l -5,0" RenderTransformOrigin="0.5,1" /> </Grid> </Grid> </Viewbox> </ControlTemplate> </Setter.Value> </Setter> </Style> Most of the elements have a name that adheres to the ‘PART_*’-scheme convention. The code-behind needs these elements in its calculation. Only the Ticks and ScaleTicks ItemControls and the Unit TextBlock are done entirely in XAML. The DataTemplate required some binding, but TemplateBinding doesn’t work at that place. So I created a ‘Proxy’ for each of these to cache the control’s properties, like this: <!-- Ticks --> <Line x:Name="TicksProxy" Visibility="Collapsed" Fill="{TemplateBinding TickBrush}" /> <ItemsControl ItemsSource="{TemplateBinding Ticks}" VerticalAlignment="Center" HorizontalAlignment="Center"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Rectangle Height="18" Width="5" Fill="{Binding Fill, ElementName=TicksProxy}"> <!-- ... --> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> I’m not sure if this is the standard way to achieve TemplateBinding inside an ItemTemplate, but it does the trick. To avoid a proliferation of properties, I decided to go for minimal XAML and do the drawing of the ArcSegments for both the scales entirely in code-behind. As a result, they’re not templateable in [this version of] the control. Here’s how the scale is drawn in the OnApplyTemplate method: protected override void OnApplyTemplate() { // Draw Scale var scale = this.GetTemplateChild(ScalePartName) as Path; if (scale != null) { var pg = new PathGeometry(); var pf = new PathFigure(); pf.IsClosed = false; var middleOfScale = 77 - this.ScaleWidth / 2; pf.StartPoint = this.ScalePoint(-150, middleOfScale); var seg = new ArcSegment(); seg.SweepDirection = SweepDirection.Clockwise; seg.IsLargeArc = true; seg.Size = new Size(middleOfScale, middleOfScale); seg.Point = this.ScalePoint(150, middleOfScale); pf.Segments.Add(seg); pg.Figures.Add(pf); scale.Data = pg; } OnValueChanged(this, null); base.OnApplyTemplate(); } The control is not implemented [yet] in a control library, I just created the class file and the default style inside the main project: That's why the resource dictionary with the gauge’s style is not embedded in Templates\generic.xaml, but in a separate resource dictionary –Gauge.xaml- that is added to the app in app.xaml: <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Common/StandardStyles.xaml"/> <ResourceDictionary Source="Controls/Gauge.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> Here’s the full source code of the sample project, including the source code of the gauge: U2UConsult.WinRT.Modern.zip (78.95 kb).Enjoy!Diederik
Printing a XAML ItemsControl from a Windows 8 Store app 22 May 2013 Diederik-Krols WinRT This article describes how to print the contents of an ItemsControl in a XAML and MVVM based Windows 8 Store app. The code is an evolution of the printing framework that I published a couple of months ago. In a nutshell, this framework wraps the pages to be printed inside a RichTextBlock control. That is the only WinRT control that properly supports pagination, at least when you connect it to a TextBlockOverflow. Pagination is the only real problem to overcome if you want to print dynamic pages. A RichTextBlock is limited in the sense that it can only contain Paragraphs. So if you want to print an ItemsControl, then you have to make it the content of a Paragraph. That means you have to wrap it in an InlineUIContainer first. Confused? Well, here's how the body of the print page looks like in the attached sample app: <RichTextBlock> <Paragraph> <InlineUIContainer> <Image Source="ms-appx:///Assets/droids.png" Height="400" /> </InlineUIContainer> </Paragraph> <Paragraph> <InlineUIContainer> <ItemsControl ItemsSource="{Binding Droids}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0"> <ItemsControl.ItemTemplate> <DataTemplate> <Grid Margin="0 20"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="auto" /> <RowDefinition Height="auto" /> </Grid.RowDefinitions> <Image Source="{Binding Image}" Height="60" Width="60" Margin="0 20 20 20" Opacity="1" /> <TextBlock Grid.Column="1" Text="{Binding Name}" Foreground="Black" FontSize="36" Margin="0 20" /> <TextBlock Grid.Row="1" Grid.ColumnSpan="2" TextWrapping="Wrap" Text="{Binding Description}" Foreground="Black" FontSize="18" Margin="0 0 20 20" /> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </InlineUIContainer> </Paragraph> </RichTextBlock> The first version of my printing framework rendered the paragraphs one by one to see if they fitted the print page. A paragraph that could not be fully added to the page, automatically overflowed entirely to the next print page Here’s the original code: // Move content from print page to print template - paragraph by paragraph. var printPageRtb = printPage.Content as RichTextBlock; while (printPageRtb.Blocks.Count > 0) { var paragraph = printPageRtb.Blocks.First() as Paragraph; printPageRtb.Blocks.Remove(paragraph); var container = paragraph.Inlines[0] as InlineUIContainer; if (container != null) { // Place the paragraph in a new textblock, and measure it. var measureRtb = new RichTextBlock(); measureRtb.Blocks.Add(paragraph); PrintingRoot.Children.Clear(); PrintingRoot.Children.Add(measureRtb); PrintingRoot.InvalidateMeasure(); PrintingRoot.UpdateLayout(); measureRtb.Blocks.Clear(); // .Remove(paragraph); // Apply line height to trigger overflow. paragraph.LineHeight = measureRtb.ActualHeight; } firstPage.AddContent(paragraph); }; Unfortunately that approach didn't allow an ItemsControl to span more than one print page, so the framework was useless if you wanted to print long lists. Recently, I had to deliver an app that needed to print out a list of records, possibly a long list. So I created a sample app to isolate the problem. Here's a screenshot of it. The list on the left doesn’t fit on the screen, but also not on a single print page: Here are some vain attempts to solve the issue. I first tried to create an ItemsControl with a RichTextBlock as ItemsPanel and a Paragraph as Item Template root. The idea was to render this control directly (as part of the current screen, that's what the printing framework does with all controls) and then move the paragraph children to the print page. But the construction of such an ItemsControl is not allowed: RichTextBlock is not a Panel *and* Paragraph cannot be used as Item. Making an ItemsControl behave like a Paragraph is not possible, so I tried to do the opposite: creating a RepeatingParagraph control, a Paragraph with an ItemsSource property. Unfortunately the classes in the Windows.UI.Xaml.Documents namespace are sealed (whose idea is that?), and with attached properties I couldn’t get deep enough into the binding mechanisms. In the meantime, the deadline of the app was approaching. So I decided to change the core framework logic instead of the controls. I refactored the Paragraph rendering to a separate method: // Renders a Paragraph private double Render(Paragraph paragraph) { var measureRtb = new RichTextBlock(); measureRtb.Blocks.Add(paragraph); PrintingRoot.Children.Clear(); PrintingRoot.Children.Add(measureRtb); PrintingRoot.InvalidateMeasure(); PrintingRoot.UpdateLayout(); measureRtb.Blocks.Clear(); return measureRtb.ActualHeight; } When rendering the print page, I verified for each Paragraph whether or not it was embedding an ItemsControl. These paragraphs got the new treatment. For all others the original code was called: // Move content from print page to print template - paragraph by paragraph. var printPageRtb = printPage.Content as RichTextBlock; while (printPageRtb.Blocks.Count > 0) { var paragraph = printPageRtb.Blocks.First() as Paragraph; printPageRtb.Blocks.Remove(paragraph); var container = paragraph.Inlines[0] as InlineUIContainer; if (container != null) { var itemsControl = container.Child as ItemsControl; if (itemsControl != null) { // New code to render an ItemsControl. // ... } else { // Original code to render a complex Paragraph // ... } } else { // Original code to render a simple Paragraph // ... } }; After a few iterations, I came up with this algorithm to render all items in an ItemsControl as a separate Paragraph, allowing individual items to overflow to the next print page. First we have to make sure that the control reads its ItemsSource. That is done by … rendering it. Then we walk through the rendered children via the ItemContainerGenerator. We wrap each item in a new InlineUIContainer and in a new Paragraph. We render that Paragraph again, to measure it. Then we move that Paragraph to the print page. Here's the code, the whole code, and nothing but the code: // Render the paragraph, to read the ItemsSource this.Render(paragraph); // Render children individually foreach (var item in itemsControl.Items) { var x = itemsControl.ItemContainerGenerator.ContainerFromItem(item) as ContentPresenter; Paragraph p = new Paragraph(); InlineUIContainer c = new InlineUIContainer(); var o = x.ContentTemplate.LoadContent() as UIElement; (o as FrameworkElement).DataContext = item; c.Child = o; p.Inlines.Add(c); p.LineHeight = this.Render(p); firstPage.AddContent(p); } Here’s the result in the sample app. The list nicely spans two pages: Here’s the code for the sample app, including the whole printing framework: U2UConsult.Win8.PrintItemsControl.zip (3.18 mb) Enjoy! Diederik