Corrado's Blog 2.0

Online thoughts of a technology funatic

Beware of generated XAML in UWP

I admit, this is s strange blog post title but that’s what this post is going to talk about.

I’m working on a UWP app that has different min and target runtimes:

image

After doing some UI work with Visual Studio & Blend I’ve discovered that the app was crashing on machines without Anniversary edition installed. At the end of a debuggin session I’ve found the reason: The XAML template generated by the tools contains incompatible elements (resources mainly, but also new properties) that are not present on previous builds.

To give you an example, this is an extract from a ComboBox default template, generated by Blend when you use the Template->Edit copy feature:

10586

<Setter Property="Foreground"

Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />

14393 (Anniversary)

<Setter Property="Foreground"

Value="{ThemeResource ComboBoxForeground}" />

The reason of this is because the tools generate the template from the Target version SDK and not the Min version SDK that might even not be present.

The team said that they’re going to give you some warnings in the future when situations like this happen, but in the meantime, at least when you’re doing design work, be sure to selected, the min target version SDK otherwise you might end up in troubles.

Xamarin Forms: CarouselView in action

Xamarin Forms are getting better with each new release, version 2.2, actually in preview, includes new interesting addition like Effects and CarouselView.

CarouselView replaces the now deprecated CarouselPage with a more flexible control that can be embedded in any page and can have any size you want, being curious I wanted to see it in action.

I created a new Xamarin Forms project and updated all projects NuGet Packages to version 2.2.0.5-pre2 (you have to select “Include prerelease” option to have it listed since, at the moment, it hasn’t officially released yet.

image

I suddenly added a MainView xaml page to the PCL project and set it as MainPage inside App.cs

public class App : Application { public App() { // The root page of your application MainPage = new MainView(); } }

CarouselView inherits from ItemView so it requires a collection of items associated to it’s ItemSource property, I then created an array of Persons and associated to CarouselView with this code

public partial class MainView : ContentPage { public MainView() { this.InitializeComponent(); Person[] persons = { new Person() { Name = "Corrado", ImageUri = "male.png" }, new Person() { Name = "Giulia", ImageUri = "female.png" } }; this.MyCarouselView.ItemsSource = persons; CarouselView v; } } public class Person { public string Name { get; set; } public string ImageUri { get; set; } }

MyCarouselView is the CarouselView I previously added to MainView.xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:testCarouselView="clr-namespace:TestCarouselView;assembly=TestCarouselView" x:Class="TestCarouselView.MainView"> <CarouselView x:Name="MyCarouselView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" /> </ContentPage>

Great, but we’re missing something: The ItemTemplate. but since I want to use a different template for each page I decided to use another recent addition to Xamarin Forms: the DataTemplateSelector, so I created this class that inherits from abstract DataTemplateSelector.

public class CarouselTemplateSelector : DataTemplateSelector { public DataTemplate MaleTemplate { get; set; } public DataTemplate FemaleTemplate { get; set; } protected override DataTemplate OnSelectTemplate(object item, BindableObject container) { Person person = (Person)item; switch (person.ImageUri) { case "male.png": return MaleTemplate; case "female.png": return FemaleTemplate; default: throw new ArgumentOutOfRangeException(); } } }

So simple that don’t think it requires a detailed explanation, it just returns proper DataTemplate depending on the name of ImageUri, ok, not very professional but this is just a demo right? Smile

I generally like to have TemplateSelectors instantiated via xaml together with their associated template definition in one place, so I added them to MainView xaml resources, here’s complete markup:

<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:testCarouselView="clr-namespace:TestCarouselView;assembly=TestCarouselView" x:Class="TestCarouselView.MainView"> <ContentPage.Resources> <ResourceDictionary> <!--Female template--> <DataTemplate x:Key="FeMaleTemplate"> <StackLayout BackgroundColor="Pink" Orientation="Horizontal"> <Image Source="{Binding ImageUri}" VerticalOptions="Center" Margin="50,0,0,0" WidthRequest="100" HeightRequest="200" /> <Label VerticalOptions="Center" Margin="60,0,0,0" Text="{Binding Name}" TextColor="Black" FontSize="30" /> </StackLayout> </DataTemplate> <!--Male template--> <DataTemplate x:Key="MaleTemplate"> <Grid BackgroundColor="Aqua"> <Image Source="{Binding ImageUri}" VerticalOptions="Start" Margin="00,50,0,0" WidthRequest="100" HeightRequest="200" /> <Label VerticalOptions="Center" HorizontalOptions="Center" Margin="0,500,0,0" Text="{Binding Name}" TextColor="Black" FontSize="30" /> </Grid> </DataTemplate> <!--Template selector--> <testCarouselView:CarouselTemplateSelector x:Key="CarouselTemplateSelector" MaleTemplate="{StaticResource MaleTemplate}" FemaleTemplate="{StaticResource FeMaleTemplate}" /> </ResourceDictionary> </ContentPage.Resources> <!--Carousel View--> <CarouselView PositionSelected="OnPositionSelected" x:Name="MyCarouselView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" ItemTemplate="{StaticResource CarouselTemplateSelector}" /> </ContentPage>

From the xaml you’ll immediately recognize the two (simple) DataTemplates, the custom DataTemplateSelector , how it gets associated to CarouselView ItemTemplate but if you look closely you’ll also recognize a nice addition to Forms v2.2: Margin property!

Yes we can now stop using nested views with Padding to fine tune control position inside a Page, well done Xamarin!

If you want to be informed when the position of CarouselView changes just subscribe PositionChanged event, in my case I mapped it to this method:

private void OnPositionSelected(object sender, SelectedPositionChangedEventArgs e) { Debug.WriteLine(e.SelectedPosition.ToString()); }

We can now run the sample code and we’ll get this outputs (Android/iOS)

Android       ios

CarouselView is a great new entry, in special case if you want to create applications based on sliding views (quite common today) there’s just one feature I miss: Orientation, at the moment looks like you can only slide horizontally, hope Xamarin will consider it for final release.

Xamarin Forms preview with Gorilla Player

One of the major complaints about Xamarin Forms is the lack of designer with relative preview so, at the time of this writing, the development process is made up of a continuous sequence of: write XAML, deploy, see result, stop, edit XAML and try again, not a very convenient and productive way to work Sad smile

GorillaPlayer is a tool from a company named UXDivers that provides real time XAML preview on any Emulator/Simulator speeding up development process.

Note: GorillaPlayer is actually in beta and available via invite only, go request your invite here: www.gorillaplayer.com the player is available for both Visual Studio and Xamarin Studio (both Windows and iOS)

Once you get the invite, download the installer for your platform, enter the invitation code and let the installer complete installation, I encourage you to select the “Install Player + SDK + Samples” option since it contains a fundamental component (a.k.a. The Player)

image
If everything goes well, you should now have a new element in your tray area (on Windows Platform)

image

Right clicking the icon you’ll see all Gorilla Player’s options, I suggest you to have a look at Getting Started Walkthrough

image:

In order to see your XAML output you must install the Gorilla Player App in target emulator/simulator (in alternative using included Gorilla Player’s SDK, the player can be integrated directly in your app, see SDK page for more details) the player will try to connect with the host running on your machine

image

and once connection is completed (you have both automatic and manual setup options)  you’ll see the monkey smiling and ready to render your XAML

image

Let’s see some XAML then!

While the player app is running, create a brand new Xamarin Forms app (or open an existing one…) and open/add a XAML page, you should see the preview live on the emulator/simulator, if not check Gorilla Player’s option under: Tools->Gorilla Player (in Visual Studio) if not connected select the Connect option and check Follow me option

image

Note: using Stick to this XAML will let you freeze the rendered XAML while working on another file.

If Gorilla can’t render your XAML you’ll see an error message like this:

image

Otherwise you’ll get the final output, here’s a demo XAML fragment:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="GorillaTest.Views.MyView"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="MyLabelStyle" TargetType="Label"> <Setter Property="HorizontalOptions" Value="Center" /> <Setter Property="VerticalOptions" Value="CenterAndExpand" /> <Setter Property="FontSize" Value="20" /> </Style> </ResourceDictionary> </ContentPage.Resources> <StackLayout BackgroundColor="Teal"> <Image Source="icon.png" WidthRequest="100" HeightRequest="100" /> <Label Text="Gorilla Player Rocks!" Style="{StaticResource MyLabelStyle}" TextColor="White" /> </StackLayout> </ContentPage>

image

As you see the Player supports every XAML element including Images, Styles, Resources, etc it also support ContentViews (see here)

But what about design time data? : If you have a ListView I presume you want to see how it renders at runtime right? luckily Gorilla Player has a great support for design time data too, with several options (see here) probably the quickest one is to use add a json file with sample data to your project.

Let’s take this XAML as example (taken from Gorilla’s demo MyCoolCompanyApp)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="MyCoolCompanyApp.MyPeople" xmlns:common="clr-namespace:UXDivers.Artina.Player;assembly=UXDivers.Artina.Player.Common" BackgroundColor="#455a64" xmlns:local="clr-namespace:MyCoolCompanyApp;assembly=MyCoolCompanyApp"> <ContentPage.Content> <Grid> <Image Opacity="0.5" x:Name="img" Source="bridge_bg.png" Scale="1.5" Aspect="AspectFill"/> <StackLayout Padding="10,30,20,0"> <ListView ItemsSource="{Binding .}" SeparatorVisibility="None" BackgroundColor="Transparent" SeparatorColor="#DFDFDF" HasUnevenRows="false" RowHeight="120"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <local:MyPeopleTemplate /> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </Grid> </ContentPage.Content> </ContentPage>

The output rendered by Gorilla Player is:

image

Awesome! but since we are at design time, were do the ListView data come from? If you look at PCL project you’ll see that it includes a SampleData.json file

image

with this content:

{ "MyPeopleTemplate.xaml": { "Name": "John Silverstain", "City": "MELBOURNE", "Department": "Marketing", "Color": "Red", "Age": 29, "Followers": 243, "Photo": "friend_thumbnail_27.jpg" }, "MyPeople.xaml": [ { "Name": "John Silverstain", "City": "MELBOURNE", "Department":"Marketing", "Color":"Red", "Age":29, "Followers":243, "Photo":"friend_thumbnail_27.jpg" }, { "Name": "Pam Tailor", "City": "SIDNEY", "Department":"Design", "Age":32, "Followers":24, "Photo":"friend_thumbnail_75.jpg" }, { "Name": "Casy Niman", "City": "HOBART", "Department":"Accounts", "Age":58, "Followers":267, "Photo":"friend_thumbnail_93.jpg" }, { "Name": "Gorge Tach", "City": "NEWCASTLE", "Department":"Design", "Age":29, "Followers":127, "Photo":"friend_thumbnail_55.jpg" }, { "Name": "Cristina Maciel", "City": "HOBART", "Department":"Mobile Dev.", "Age":32, "Followers":80, "Photo":"friend_thumbnail_31.jpg" }, { "Name": "Simon Deuva", "City": "MELBOURNE", "Department":"Media", "Age":58, "Followers":420, "Photo":"friend_thumbnail_34.jpg" } ] }

As you see, the file contains a set of sample data, in json format, that will be associated to each page (MyPeopleTemplate.xaml and MyPeople.xaml in this case) ideally simulating the same data that the associated ViewModel will provide at runtime. in the docs you’ll find alternative design time solutions like using a Json data class or a Plain object.

While in beta, the product is already very stable and a total life saver if you do Xamarin Forms development so I encourage you to give it a try and help the team fixing all issues so that we can get an official v 1.0 soon.

Issues can be filed here.

Happy Gorilla rendering! Smile

XAML relative binding trick

MVVM newcomers find creating a UI like this (a simple ListView containing a button that removes current row) quite intricated.

image

This because, while you can add a command to the item bound to each row, it’s more convenient to have a common DeleteCommand on parent ViewModel that accepts the Item to remove from the collection feeding the list.

Here’s our ViewModel:

public class MyViewModel { private RelayCommand<ReportUnit> deleteCommand; public MyViewModel() { this.Items = new ObservableCollection<ReportUnit>(); for (int i = 0; i < 10; i++) { this.Items.Add(new ReportUnit() { Name = $"Item {i}" }); } } public RelayCommand<ReportUnit> DeleteCommand { get { return this.deleteCommand ?? (this.deleteCommand = new RelayCommand<ReportUnit>((o) => { this.Items.Remove(o); })); } } public ObservableCollection<ReportUnit> Items { get; private set; } } public class ReportUnit { public string Name { get; set; } }

And here’s the page XAML:

<Page x:Class="DemoBinding.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <Style x:Key="ListItemContainerStyle" TargetType="ListViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> </Style> </Page.Resources> <Grid x:Name="RootGrid"> <ListView ItemsSource="{Binding Items}" ItemTemplate="{StaticResource MyItemTemplate}" ItemContainerStyle="{StaticResource ListItemContainerStyle}"> </ListView> </Grid> </Page>

The “magic” is of course inside MyItemTemplate:

<DataTemplate x:Key="MyItemTemplate"> <Grid d:DesignWidth="568.775" Height="80" d:DesignHeight="100"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> <TextBlock TextWrapping="Wrap" Text="{Binding Name}" VerticalAlignment="Center" FontSize="26.667" /> <Button Grid.Column="1" Content="Delete" HorizontalAlignment="Stretch" Command="{Binding DataContext.DeleteCommand, ElementName=RootGrid}" CommandParameter="{Binding}" VerticalAlignment="Stretch" Margin="5" /> </Grid> </DataTemplate>

As you see, the  button ‘steal’ the DataContext of RootGrid element and invokes MyViewModel’s DeleteCommand while passing its own DataContext as CommandParameter.

Simple and clean. Smile