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.

Blend 2015: Cannot add additional fields to a type… error

Yesterday repaved my machine and installed Windows 10 and Visual Studio 2015, I then loaded one of the projects I’m working on and I’ve a been shocked to discover that none of my views was rendering in Blend 2015 because of this error: “Cannot add additional fields to a type that does not have a constructor”

image

Thanks to Blend team I was pointed to a workaround that fixed it (at least for me)

Go to Tools->Options->XAML designer and check the option: Run project code in XAML Designer (if supported) and reload the project

image

 

Hope it helps.

Behaviors for Xamarin Forms v2.0

I’ve pushed version 2.0 of my behavior implementation for Xamarin Forms and moved it to a new location on GitHub: https://github.com/corradocavalli/Corcav.Behaviors

The reason for this is that, in order to prevent conflict with Xamarin API I’ve renamed the root namespace so upgrading to this version will break your code and I’m really sorry for this, but I’m sure it won’t take too long to fix it.

I’ve also removed old nuget package and replaced with this one : ’https://www.nuget.org/packages/Corcav.Behaviors/

Version 2.0 uses Xamarin Forms 1.3.4 and Unified API project as iOS demo.

Sorry for breaking your code, my fault using Xamarin as assembly name Sad smile (lesson learned), honestly didn’t expect such success, and I thank you for that.

Introducing Xamarin Forms Behaviors

The goal of this post is to introduce you to the Xamarin.Forms.Behavior package available on NuGet, if you landed here I presume you already know what Xamarin Forms is, if not, follow this link so you’ll understand why so many developers are excited about it.

Now that I can assume you’re a Xamarin Forms master, let’s concentrate on Behaviors. Once I read Xamarin Forms documentation I was really happy to see that you can design cross-platforms user interfaces using XAML and that the XAML support in Xamarin Forms is nearly identical to the one available in Windows development apart some minor differences.

If you don’t know what a Behavior is I can summarize it for you in this sentence: The capabity to add code inside a UI described using XAML” the question now is: Why should I add code inside XAML, hasn’t code behind created just for this? well, yes and no, if you know MVVM (if not, you should!) you’ll know that the entire logic should reside inside the VieModel associated with the View and that communication between View and ViewModel should happen (in a perfect world) through Databinding.

Unfortunately in “real” world this is not always possible and you have to use code to make things work, often this code resides in code behind and for this reason is not testable and not even reusable.

Let’s take an example: A simple view made up of two Entry elements and a Button, the View has a ViewModel associated to its BindingContext and we want the button to be enabled only when both Entry fields are not empty and it’s enabled state must toggle “live” while user typing.

This is the XAML contained inside Xamarin Forms’s PCL project:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"      
        x:Class="Xamarin.Behaviors.Demo.Views.MainView">
 <StackLayout>
  <Entry Placeholder="Enter Firstname" />
  <Entry  Placeholder="Enter Lastname" />
  <Button Text="Ok" Command="{Binding TestCommand}" />    
 </StackLayout>
</ContentPage>

and here’s the ViewModel:

public class MainViewModel : INotifyPropertyChanged
 {
  public event PropertyChangedEventHandler PropertyChanged;

  private string firstName = "Nome";
  private string lastName = "Cognome";
  private Command testCommand;
  private Command<object> unfocusedCommand;
  private string message;
  private string welcomeMessage; 
  
  public string FirstName
  {
   get { return this.firstName; }

   set
   {
    if (value != this.firstName)
    {
     this.firstName = value;
     this.RaisePropertyChanged();
     this.TestCommand.ChangeCanExecute();
    }
   }
  }
  
  public string LastName
  {
   get { return this.lastName; }

   set
   {
    if (value != this.lastName)
    {
     this.lastName = value;
     this.RaisePropertyChanged();
     this.TestCommand.ChangeCanExecute();
    }
   }
  }
  
  public string Message
  {
   get  {return this.message; }

   private set
   {
    if (value != this.message)
    {
     this.message = value;
     this.RaisePropertyChanged();
    }
   }
  }  
  public string WelcomeMessage
  {
   get { return this.welcomeMessage;}

   set
   {
    if (value != this.welcomeMessage)
    {
     this.welcomeMessage = value;
     this.RaisePropertyChanged();
    }
   }
  }
  
  public Command TestCommand
  {
   get
   {
    return this.testCommand ?? (this.testCommand = new Command(
      () =>
      {
       this.WelcomeMessage = string.Format("Hello {0} {1}", this.FirstName, this.LastName);
      },
      () =>
      {
       return !string.IsNullOrEmpty(this.FirstName) && !string.IsNullOrEmpty(this.LastName);
      }));
   }
  }

  public Command<object> UnfocusedCommand
  {
   get
   {
    return this.unfocusedCommand ?? (this.unfocusedCommand = new Command<object>(
      (param) =>
      {
       this.Message = string.Format("Unfocused raised with param {0}", param);
      },
      (param) =>
      {
       // CanExecute delegate
       return true;
      }));
   }
  }
  
  protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
  {
   PropertyChangedEventHandler handler = PropertyChanged;
   if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  }
 }

ViewModel is associated with the View’s constructor for brevity:

public partial class MainView
 {
  public MainView()
  {
   InitializeComponent();
   this.BindingContext = new MainViewModel();
  }
 }

As you see the Button is connected to ViewModel’s TestCommand via Databinding and thanks to ICommand interface it is enabled only when both ViewModel’s FirstName and LastName properties are not empty.

Now the hardest part: How do we update those properties when Entry content changes?

Easy: we subscribe Entry’s TextChanged method and when it fires we update associated property. Cool, but wouldn’t it be nice if we could encapsulate this logic into a reusable component, usable in XAML, so that we don’t need to reinvent the wheel each time?

Here’s where Behaviors can help you.

Install Xamarin.Forms.Behaviors Package from NuGet and  and create a class that inherits from Behavior<T> where <T> is the UI component that the behavior will attach to, in our case the Entry element.

public class TextChangedBehavior : Behavior<Entry>
 {
  public static readonly BindableProperty TextProperty = BindableProperty.Create<TextChangedBehavior, string>(p => p.Text, null, propertyChanged: OnTextChanged);

  private static void OnTextChanged(BindableObject bindable, string oldvalue, string newvalue)
  {
   (bindable as TextChangedBehavior).AssociatedObject.Text = newvalue;
  }

  public string Text
  {
   get { return (string)GetValue(TextProperty); }
   set { SetValue(TextProperty, value); }
  }

  protected override void OnAttach()
  {
   this.AssociatedObject.TextChanged += this.OnTextChanged;
  }

  private void OnTextChanged(object sender, TextChangedEventArgs e)
  {
   this.Text = e.NewTextValue;
  }

  protected override void OnDetach()
  {
   this.AssociatedObject.TextChanged -= this.OnTextChanged;
  }
 }

Behavior and Behavior<T> both have OnAttach and OnDetach methods that gets invoked when the behavior is attached/detached from parent UI element, so we subscribe TextChanged event and when it triggers we update behavior’s bindable property Text.

I’ll be you’re now wondering: How do I use it in my XAML? very easy, here’s the updated XAML for Entry element (just first one indicated for brevity)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"
        x:Class="Xamarin.Behaviors.Demo.Views.MainView">
 <StackLayout>
  <Entry Placeholder="Enter Firstname" >
   <b:Interaction.Behaviors>
    <b:BehaviorCollection>
     <b:TextChangedBehavior Text="{Binding FirstName, Mode=TwoWay}" />     
    </b:BehaviorCollection>
   </b:Interaction.Behaviors>
  </Entry>
  ...
  </StackLayout>
</ContentPage
  

After adding a xmlns pointing to Xamarin.Forms.Behavior namespace we “inject” the code into XAML, so now as we type on Entry the Firstname property it’s updated (and vice versa of course thanks to INotifyPropertyChanged and Two Way binding mode.)

One of the real advantages of using Behaviors in Windows Development is that they’re visually supported by Expression Blend design tool, so you don’t even need to write any XAML, just drag the behavior and configure it using point and click Smile unfortunately since we don’t even have a XAML designer in Xamarin Forms typing is the only available solution at the moment.

If you think the syntax is quite boring I agree, that’s why inside the project on GitHub I added a XML snippet that generates the surrounding code for you, just grab it and import it in Visual Studio, add the behavior syntax and press Ctrl+K+S

image

and you’ll have the plumbing code added for you, don’t forget to add required xmlns directive/s.

xmlns:b="clr-namespace:Xamarin.Behaviors;assembly=Xamarin.Behaviors"

since it’s not added automatically by the snippet.

Am not a Xamarin Studio expert so I don’t know if it support XML Expansions, if so send me the snippet and I’ll add it to the project.

Here’s the XAML taken from the example available on GitHub:

<Entry Placeholder="Enter Firstname" >
   <b:Interaction.Behaviors>
    <b:BehaviorCollection>
     <b:TextChangedBehavior Text="{Binding FirstName, Mode=TwoWay}" />
     <b:EventToCommand EventName="Unfocused" Command="{Binding UnfocusedCommand}" CommandParameter="FirstName" />
    </b:BehaviorCollection>
   </b:Interaction.Behaviors>
  </Entry>

the example shows two behaviors included in the package, TextChangedBehavior and EventToCommand, a behavior that invokes a Command when an event occurs.

Congratulations! you’re now able to write your own behavior, group them in a portable library and reuse it in every Xamarin Forms project.

If you’re already a XAML developer you already know what behaviors are and I hope you’ll like to have them in Xamarin Forms, if not I encourage you to play with it, personally can’t even think using XAML with MVVM without them.

Ok, now let’s dream about a Xamarin Forms designer supporting the same Behavior infrastructure as Expression Blend, am I asking too much? we’ll see.

Cheers!

NuGet Package: here

GitHub repo: here

The tale of a GridViewItem customization

Once upon a time, in a galaxy not so far away, there was a guy (me Smile) who was working on a Windows Store 8.1 application and was asked to create a GridView whose items should look like this picture:

image

The guy (again, me) thought: What’s the problem, did it many times! and he started setting a data source:

public class Item
    {
        public string Text { get; set; }
    }

    public class DemoViewModel
    {
        public DemoViewModel()
        {
            this.Items = new List<Item>();
            for (int i = 0; i < 10; i++)
            {
                this.Items.Add(new Item() { Text = "Item " + i });
            }
        }

        public IList<Item> Items { get; set; }
    }

He then added a GridView to a page, bound the data source and created a simple ItemTemplate:

<Page x:Class="GridViewDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:GridViewDemo"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">
    <Page.Resources>
        <local:DemoViewModel x:Key="vm"></local:DemoViewModel>
        <DataTemplate x:Key="MyItemTemplate">
            <Grid Width="100"
                  Height="60">
                <TextBlock HorizontalAlignment="Center"
                           TextWrapping="Wrap"
                           Text="{Binding Text}"
                           VerticalAlignment="Center" />
            </Grid>
        </DataTemplate>
        
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
          DataContext="{StaticResource vm}">
        <GridView ItemsSource="{Binding Items}"
                  ItemTemplate="{StaticResource MyItemTemplate}"
                   />
    </Grid>
</Page>

Run the solution and he got something quite close to what he was asked to realize:

image

Ok, just a couple of customizations and we’re done, he thought…

Let’s start with the selected background: The guy knows that background brush is managed inside ItemContainerStyle so he fired up Blend 2013, edited GridView’s ItemContainerStyle and here’s what he got:

image

Just a simple GridViewItemPresenter that has a series of Brush properties that give you the opportunity to customize several container aspects

image

In his case he needed to customize the color of SelectedBackground so, since it is bound to a resource named ListViewItemSelectedBackgroundThemeBrush he added a Brush resource with the same name inside Page resources and selected state was done, here’s updated result:

<SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush"
                         Color="Orange"></SolidColorBrush>

image

But a question started to rise in his mind: “How to i set default (gray) background color?” there’s no Background color exposed by GridViewItemPresenter nor he can set it inside ItemTemplate otherwise it wouldn’t change when item is selected.

He tried lookind inside MSDN docs hoping to find a brush key that controls item default background but he had no luck Sad smile and navigated a lot the Internet until he realized he did something similar in the past for a Windows 8.0 application.

He then opened that old source code and discovered what has changed: The GridViewItemPresenter has been introduced in Windows 8.1, here’s how ItemContainerStyle looks in Windows 8.0:

image

Since you have access to all the elements composing the GridViewItem what the guy did was copying the style into Windows 8.1 app and edited VisualStateManager states (I’m sure, dear reader, you know how to do that…)

So, here’s final result:

image

The guy secretly told me that he wasn’t happy for such solution, probably GridViewItemPresenter has been introduced to improve GridView’s performances but he found no other easier way to solve the puzzle.

Based on a true story… Smile

PS: In case you need Windows 8.0 GridView’s ItemContainerStyle you can get it here.

Debug design time issues in Blend 2013

In 2010 (wow! that’s a long time ago…) I blogged about how to debug Blend design time exceptions, since then things have changed, Blend and Visual studio designer merged and so the XAML designer is now hosted in a separate process named XDesProc.exe (at least in Windows Store applications)

Laurent Bugnion has a detailed blog post about how to attach Visual Studio debugger to Blend to debug a Windows Store application at design time so i won’t repeat it here, the reason of this post is to integrate it with another step required when you use Visual Studio 2013 and Blend 2013.

Since with latest release PDB are no longer copied to cache location used by designer your simbols won’t be loaded and your attach procedure won’t work.

The solution is very easy, just point the debugger symbols to the proper PDB files of your application and everything will work as expected.

To point the PDBs just use: Tools –> Options-> Debugger

image

Then add the folder where your app’s PDB file resides.

Blend can’t locate types in external assemblies

While developing a Windows Store app I run into a Blend issue that caused me some headache.

I tend to define common converters in external assemblies in order to reuse them in other projects, so i added a reference to a Windows Store library project containing the converters I needed then swiched to Blend to use them from Create DataBinding dialog, and here’s what i got:

image

Problem: My library was not listed.

Really weird since here’s what I got doing the same from Visual Studio 2012

image

My MvvmHelper library is listed. Confused smile

Using Visual Studio to add the assembly resulted in following Blend error:

image

Ok, i presume you probably want to know the reason (and how to fix it): The problem was caused by projects having different build configurations: that main project has a X86 configuration (required by Bing Maps component) while all referenced libraries where AnyCPU and looks like that Blend 2012 doesn’t like it.

Moving the entire solution to X86 solved the issue.

Blend team is working on having it fixed before Blend 2013 release.

Happy Blending!

Note: Many thanks to @unni for helping me on this.