Xamarin.Forms

La chiara e netta separazione tra la UI e l’application logic è il concetto che sta alla base del pattern MVVM. Molte volte, però, non è semplice capire distinguere le responsabilità, almeno in termini di rappresentazione della UI. Se devo cambiare un colore in base al contenuto, è il ViewModel che lo decide? Dove indico il colore?

Tendenzialmente saremo portati ad aggiungere una proprietà nel ViewModel con l’indicazione del colore da visualizzare. E magari definiamo come tipo della proprietà l’enum Xamarin.Forms.Color. Sebbene semplice, questo approccio è sbagliato perchè assegna al ViewModel una responsabilità della View, oltre al rischio di non rendere il ViewModel compatibile se questo deve essere reso riutilizzabile in diverse piattaforme (non Xamarin.Forms).

Quindi?

Il ViewModel si deve limitare a riportare il dato, senza avere conoscenza del modo in cui esso verrà rappresentato dalla View. Se in una lista di persone dobbiamo mostrare un colore diverso a seconda del sesso, blu per i maschietti e rosa per le femminucce, allora il ViewModel si limiterà a indicare il sesso del contatto visualizzato. Sarà poi responsabilità della View decidere cosa deve essere visualizzato e in che forma.

Una soluzione decisamente elegante e che ci viene incontro in questo contesto è l’utilizzo del DataTrigger.

La via elegante: il Data Trigger

In Xamarin.Forms un trigger permette di definire un’azione al verificarsi di un’evento o al cambio del valore di una proprietà. La sua peculiarità? Possiamo definire tutto in XAML, a livello dichiarativo, senza scrivere una riga di codice. Esistono quattro diverse tipologie di Triggers:

  • Property Trigger: attivato quando la proprietà di un controllo viene impostata su un particolare valore;
  • Event Trigger: attivato quando da un controllo viene generato un particolare evento;
  • Multi Trigger: consente l’attivazione del trigger sulla base della valutazione di più condizioni;
  • Data Trigger: consente di verificare la condizione del trigger, su una specifica proprietà, utilizzando il binding;

Nello specifico scenario, ovviamente, il DataTrigger è il tipo di trigger che fa al caso nostro. Il codice è decisamente semplice. Dobbiamo aggiungere alla collection Triggers di un controllo Xamarin.Forms, ad esempio BoxView, e definire la proprietà del ViewModel da controllare e il valore che quella proprietà deve avere per attivare il trigger. Se la condizione si verifica, viene utilizzato il Setter definito nel trigger per impostare la proprietà BackgroundColor del BoxView su un nuovo colore, Pink in questo caso:

<BoxView.Triggers>
	<DataTrigger TargetType="BoxView" Binding="{Binding Gender}" Value="{x:Static vm:GenderType.Female}" >
  		<Setter Property="BackgroundColor" Value="Pink" />
	</DataTrigger>
</BoxView.Triggers>

 

Questo il codice completo del ListView:

<ListView ItemsSource="{Binding Contacts}" Margin="0,50,0,0">
	<ListView.ItemTemplate>
		<DataTemplate>
			<ViewCell>
				<StackLayout Orientation="Horizontal">
					<BoxView WidthRequest="5" BackgroundColor="Blue">
						<BoxView.Triggers>
							<DataTrigger TargetType="BoxView" Binding="{Binding Gender}" Value="{x:Static vm:GenderType.Female}" >
  								<Setter Property="BackgroundColor" Value="Pink" />
							</DataTrigger>
						</BoxView.Triggers>
					</BoxView>
					<Label Text="{Binding Name}" VerticalOptions="Center" />
				</StackLayout>
			</ViewCell>
		</DataTemplate>
	</ListView.ItemTemplate>
</ListView>

e questo il risultato finale:

Semplice!

Read more

Xamarin.Forms is a great way to abstract the local implementation. But, you know, sometimes you need to perform some small adjustments based on the underlying OS. Is this the case of the iOS Status Bar style.

Xamarin.Forms implements, in the NavigationRenderer, a way to automatically set the style (dark/default or light) by checking the Luminosity value of the BarTextColor property. Check the following code:

if (statusBarColorMode == StatusBarTextColorMode.DoNotAdjust || barTextColor.Luminosity <= 0.5)
{
	// Use dark text color for status bar
	UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.Default;
}
else
{
	// Use light text color for status bar
	UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.LightContent;
}

For full code, check the NavigationRenderer source on github Xamarin.Forms project.

Now, if in your code you set the BarTextColor to black, then the status bar style will be the Default (dark). Otherwise, the status bar style will be light (white).

So, if we want to set the BarTextColor, in a classic Xamarin.Forms App class constructor, we’ll have something like this:

public App()
{
	InitializeComponent();

	MainPage = new NavigationPage(new MainPage())
	{
		BarBackgroundColor = Color.FromHex("#043596"),
		BarTextColor = Color.White
	};
}

But, this is not enough.

In iOS, we have two ways to set the StatusBarStyle:

  • at application level
  • at view controller level

The default behavior is at view controller level. Since Xamarin.Forms sets the StatusBarStyle at application level, we need to set the related property in the Info.plist. So, open the info.plist file, go in the Source tab and add a new entry with this values:

Name = UIViewControllerBasedStatusBarAppearance
Type – boolean
Value – No

And we have done! Now start the app and check the result:

Nice and simple!

Read more

This is the third post of the A little and simple Bindable (Horizontal) Scroll View saga. In the first post we saw how to implement a horizontal view with data binding capability. Then, in the second post, we have seen how to add an event to handle the tap gesture on list items.

In this post, we’ll see how to add the Command pattern to the TLScrollView and get working one of the most used way to catch the user UI interaction directly into the ViewModel.

Adding the Command and CommandParameter properties to the TLScrollView

The first step is to add two bindable properties: SelectedCommand and SelectedCommandParameter.

public static readonly BindableProperty SelectedCommandProperty =
	BindableProperty.Create("SelectedCommand", typeof(ICommand), typeof(TLScrollView), null);

public ICommand SelectedCommand
{
	get { return (ICommand)GetValue(SelectedCommandProperty); }
	set { SetValue(SelectedCommandProperty, value); }
}

public static readonly BindableProperty SelectedCommandParameterProperty =
	BindableProperty.Create("SelectedCommandParameter", typeof(object), typeof(TLScrollView), null);

public object SelectedCommandParameter
{
	get { return GetValue(SelectedCommandParameterProperty); }
	set { SetValue(SelectedCommandParameterProperty, value); }
}

The first one will be used to reference the Command object instance, the event handler into the view model, while the second one is the instance parameter that will be passed to the event handler.

After that, we need to modify the TLScrollView Render method to use the new SelectedCommand and SelectedCommandParameter properties, if used:

var command = SelectedCommand ?? new Command((obj) =>
{
	var args = new ItemTappedEventArgs(ItemsSource, item);
	ItemSelected?.Invoke(this, args);
});
var commandParameter = SelectedCommandParameter ?? item;

var viewCell = ItemTemplate.CreateContent() as ViewCell;
viewCell.View.BindingContext = item;
viewCell.View.GestureRecognizers.Add(new TapGestureRecognizer
{
	Command = command,
	CommandParameter = commandParameter,
	NumberOfTapsRequired = 1
});

Use the Command pattern to get the selected item

To use the Command pattern in our solution, we need to add a property in our viewmodel that will be binded to the UI control:

public ICommand ItemSelected { get; set; }

and then initialize it with an event handler in the viewmodel’s constructor:

public MyViewModel()
{
	ItemSelected = new Command(arg => DoSomething());
}

finally we can bind the SelectedCommand property to the ItemSelected property:

<controls:TLScrollView Orientation="Horizontal" ItemsSource="{Binding Items}" SelectedCommand="{Binding ItemSelected}" HeightRequest="100">

Use my ViewModelBase

One step further is to minimize coding by using my ViewModelBase implementation. After extending your custom ViewModel with my ViewModelBase, you can simply write a method with the name ItemSelected and the _ExecuteCommand suffix:

public void ItemSelected_ExecuteCommand(object args)
{
}

After that, you need to add square brackets around the ItemSelected name in your XAML SelectedCommand assignment definition:

SelectedCommand="{Binding [ItemSelected]}"

Nice and really simple. As usual, you can find full code with sample on my github repository.

Read more

A long time ago, in the first post, I wrote about the TLScrollView, a way to create a simple, horizontal and bindable list of items in Xamarin.Forms. The final result is something like the horizontal views on Apple App Store app.

After receiving some feedback, users ask for a way to handle the tap gesture on the items. We have two possible approaches: the first one is by using the classic ItemSelected event handlers, and the second one by using the Command pattern, typical solution in MVVM.

In this post we’ll explore the first approach.

Adding an ItemSelected handler to the TLScrollView

So, first of all, we need to add an ItemSelected event, a delegate of type EventHandler to the TLScrollView:

public event EventHandler<ItemTappedEventArgs> ItemSelected;

Now, in the Render method, we can add the following line in the for..each cycle, just after settings the BindingContext of the ViewCell:

viewCell.View.GestureRecognizers.Add(new TapGestureRecognizer
{
	Command = new Command((obj) =>
	{
		var args = new ItemTappedEventArgs(ItemsSource, item);
		ItemTapped?.Invoke(this, args);
	}),
	NumberOfTapsRequired = 1
});

Now, in your XAML, you can define the handler in this way:

<controls:XScrollView Orientation="Horizontal" ItemsSource="{Binding Items}" ItemSelected="Handle_ItemSelected" HeightRequest="100">

then you can implement your handle:

void Handle_ItemSelected(object sender, Xamarin.Forms.ItemTappedEventArgs e)
{
	// your code
}

That’s really simple! But if you want build a code in line with the Separation of Concern, typical principles of MVVM, a SelectedCommand property should be the best way.

I’ll show the step neeeded to add the command pattern to the TLScrollView in the next post of this series.

Full code is available here

Read more

Some days ago I have published a sample Xamarin.Forms control to simply move focus on others controls of the page. I’ve presented just the iOS version but now it’s the time to see also the Android implementation.

TLEntryRenderer in Android

The control is so simple that in just few lines of codes we’ll be able to realize the Android version. Here the renderer code:

[assembly: ExportRenderer(typeof(TLEntry), typeof(TLEntryRenderer))]
namespace TitiusLabs.Forms.Droid.Controls
{
	public class TLEntryRenderer : EntryRenderer
	{
		protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
		{
			base.OnElementChanged(e);

			var element = e.NewElement as TLEntry;
			if (element.ReturnButton == ReturnButtonType.Next)
			{
				Control.ImeOptions = Android.Views.InputMethods.ImeAction.Next;
				Control.EditorAction += (sender, args) =>
				{
					element.OnNext();
				};
			}
		}
	}
}

the code is available, as always, on github.

This is the final result:

movefocus_xamarinforms_android

Nice and simple!

Read more

Spending some time with good friends is always a great way to start ideas. So, while talking with one of them, he asked me the best way to handle focus on entries in a Xamarin.Forms Page. I’ve handled the problem many times in iOS and Android native projects, so I decided to create a new control in my library on github.

Welcome TLEntry: the custom Entry control

First of all, we have to create a custom control because the user needs to set the type of return button on the keyboard:

public class TLEntry : Xamarin.Forms.Entry
{
	public static readonly BindableProperty ReturnButtonProperty = 
		BindableProperty.Create("ReturnButton", typeof(ReturnButtonType), typeof(TLEntry), ReturnButtonType.None);

	public ReturnButtonType ReturnButton
	{
		get { return (ReturnButtonType)GetValue(ReturnButtonProperty); }
		set { SetValue(ReturnButtonProperty, value); }
	}
}

After doing that, we need to handle the tap on the button and move the focus on the next control. One way to do that is by knowing the next control and set the focus to it after the next button was pressed. So now we need to know the next control by settings a specific property:

[assembly:ExportRenderer(typeof(TLEntry), typeof(TLEntryRenderer))]
...
public class TLEntry
{
	public static readonly BindableProperty NextViewProperty = 
		BindableProperty.Create("NextView", typeof(View), typeof(TLEntry));

	public View NextView
	{
		get { return (View)GetValue(NextViewProperty); }
		set { SetValue(NextViewProperty, value); }
	}

	public void OnNext()
	{
		NextView?.Focus();
	}
}

Now is the time to create the platform specific renderers.

TLEntryRenderer: the iOS platform-specific renderer

A renderer is a special class with the role of transform a Xamarin Forms control in a native control. So now we needs to transform the TLEntry in a UITextField for the iOS platform. Since we already have renderers for standard control, handle the new ReturnButton and NextView properties simply means to extend the base renderer and create a new one like this:

public class TLEntryRenderer : EntryRenderer
{
	protected override void OnElementChanged(ElementChangedEventArgs&amp;amp;amp;amp;amp;amp;amp;amp;lt;Entry&amp;amp;amp;amp;amp;amp;amp;amp;gt; e)
	{
		base.OnElementChanged(e);

		var element = e.NewElement as TLEntry;
		if (element.ReturnButton == ReturnButtonType.Next)
		{
			Control.ReturnKeyType = UIKit.UIReturnKeyType.Next;
			Control.ShouldReturn += (textField) =&amp;amp;amp;amp;amp;amp;amp;amp;gt;
			{
				element.OnNext();
				return false;
			};
		}
	}
}

With this code, we set the ReturnKeyType on UITextView and add an handler that capture the pressure on the return button and go to the next item.

Now, in your Page, you can do something similar:

public partial class FormSamplesPage : ContentPage
{
	TLEntry Entry1 = new TLEntry();
	TLEntry Entry2 = new TLEntry();
	TLEntry Entry3 = new TLEntry();

	protected override void OnAppearing()
	{
		base.OnAppearing();

		Entry1.NextView = Entry2;
		Entry1.ReturnButton = ReturnButtonType.Next;

		Entry2.NextView = Entry3;
		Entry2.ReturnButton = ReturnButtonType.Next;

		Entry3.NextView = Entry1;
		Entry3.ReturnButton = ReturnButtonType.Next;

		this.Body.Children.Add(Entry1);
		this.Body.Children.Add(Entry2);
		this.Body.Children.Add(Entry3);
	}
}

this is the final result:

ezgif-2133599902

Nice!

You can find all code on my github space: https://github.com/fabiocozzolino/TitiusLabs.Xamarin

The Android version will be available soon!

Read more

The MVVM is one of the most used architectural pattern to easily separate the UI development from the business logic. When you choose that pattern, you know that the ViewModel class implements many things: property change notifications, commands to execute code based on user interaction, data loading, etc…, and, every time, you need to write the same code to complete those actions.

In this post we will see how to simplify the writing of the ViewModel classes by using some tricks and put them in a ViewModelBase class. If you don’t know nothing about the MVVM pattern, you can read more at the following page: https://msdn.microsoft.com/en-us/library/hh848246.aspx.

Data Binding

Bind data to your view is one of the principles on which MVVM is based. Data bindings is a mechanism that allows to tie any property of a visual element to a property of a backend class. That kind of tie can be bidirectional: from the view to the class and from the class to the view. While the first way is the simplest one, the second way needs just some code to be completed: you need to implement the INotifyPropertyChanged interface to notify the view that a property value has changed.

Implements the INotifyPropertyChanged interface requires some code that can be factored in the ViewModelBase class:

public abstract class ViewModelBase : INotifyPropertyChanged
{
	public event PropertyChangedEventHandler PropertyChanged;

	protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
	{
		var handler = PropertyChanged;
		if (handler != null)
			handler (this, new PropertyChangedEventArgs(propertyName));
	}
}

With this base class, now you can write our bindable properties in the ViewModel implementation without reimplement the INotifyPropertyChanged every time:

public class MyViewModel : ViewModelBase
{
	private string _title;
	public string Title
	{
		get 
		{
			return _title;
		}
		set
		{
			if (value != _title)
			{
				_title = value;
				OnPropertyChanged();
			}
		{
	}		
}

As said before, you need to notify to the View that something has changed. A lot of code, right? A step over could helps us to write a smaller code, like this:

public class MyViewModel : ViewModelBase
{
	public string Title
	{
		get { return GetValue<string>(); }
		set { SetValue(value); }
	}		
}

Better and simplest. To accomplish this, you can implement the GetValue and SetValue methods in the ViewModelBase class and stores the properties values in a Dictionary:

private Dictionary<string, object> properties = new Dictionary<string, object>();

protected void SetValue<T>(T value, [CallerMemberName] string propertyName = null)
{
	if (!properties.ContainsKey (propertyName)) {
		properties.Add (propertyName, default(T));
	}

	var oldValue = GetValue<T>(propertyName);
	if (!EqualityComparer<T>.Default.Equals(oldValue, value)) {
		properties [propertyName] = value;
		OnPropertyChanged (propertyName);
	}
}

protected T GetValue<T>([CallerMemberName] string propertyName = null)
{
	if (!properties.ContainsKey (propertyName)) {
		return default(T);
	} else {
		return (T)properties [propertyName];
	}
}

That piece of code simplifies writing a derived ViewModelBase class. Now the MyViewModel class, with the smaller code, is much more maintenable.

Automatic Relay Command implementation

A further step forward in your ViewModelBase consists in develop an automatic and simple way to delegate the execution of commands. In MVVM, a command is a piece of code executed in response of a view interaction. To create a command, you must implement the ICommand interface and put your code in it. The power of this approach helps you to create a code that can be used in multiple views, but sometimes you need to use that command only one time.

So, to simplify writing commands implementation, we can create a delegate at ViewModelBase level for each required command. Check this code:

private Dictionary<string, ICommand> commands = new Dictionary<string, ICommand>();

private const string EXECUTECOMMAND_SUFFIX = "_ExecuteCommand";
private const string CANEXECUTECOMMAND_SUFFIX = "_CanExecuteCommand";

public ViewModelBase()
{
	this.commands = 
		this.GetType ().GetTypeInfo ().DeclaredMethods
		.Where (dm => dm.Name.EndsWith (EXECUTECOMMAND_SUFFIX))
		.ToDictionary (k => GetCommandName (k), v => GetCommand (v));
}

private string GetCommandName(MethodInfo mi)
{
	return mi.Name.Replace (EXECUTECOMMAND_SUFFIX, "");
}

private ICommand GetCommand (MethodInfo mi)
{
	var canExecute = this.GetType().GetTypeInfo().GetDeclaredMethod (GetCommandName(mi) + CANEXECUTECOMMAND_SUFFIX);
	var executeAction = (Action<object>)mi.CreateDelegate (typeof(Action<object>), this);
	var canExecuteAction = canExecute != null ? (Func<object, bool>)canExecute.CreateDelegate (typeof(Func<object, bool>), this) : state => true;
	return new Command (executeAction, canExecuteAction);
}

public ICommand this[string name] {
	get{
		return commands [name];
	}
}

When the ViewModel instance is created, we collect any method with the suffix “ExecuteCommand” (you can decide to use any kind of suffix), so in the derived class we can write methods with the name SomethingExecuteCommand:

public class MyViewModel : ViewModelBase
{
	public void Save_ExecuteCommand(object state)
	{
	}

	public bool Save_CanExecuteCommand(object state)
	{
	}
}

In this example you see also a method called SaveCanExecuteCommand. This is optional, since the base class creates a delegate at runtime with return value equals to true if no one has been found.

Finally, in the view, you can write something like this:

<Button Command="{Binding [Save]}" CommandParameter="{Binding MyProperty}" />

Really simple!

Conclusion

The ViewModelBase is only a way to simplify ViewModel class development and avoid a lot of code duplication. Obviously this is not the answer for everything.

Let me know what do you think about it!

Read more

This is the first post about the new features included in Xamarin.Forms 2.0, released with Xamarin 4 a week ago.

In the previous versions of Xamarin.Forms when you made some mistakes in XAML, like a wrong property or a wrong value, you can’t catch the error until start a new debug session. Xamarin.Forms 2.0 adds a new attribute that allows checking XAML at compile-time. You have only add that code in the AssemblyInfo.cs file:

using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]

Now you got a compile-time error in case of wrong XAML:

Schermata 2015-12-08 alle 08.47.19

XamlCompilation and Xamarin.Forms performance

The compile-time xaml check is not the only benefit of XamlCompilation. Precompiled XAML will produce a smaller app file, since the XAMLs are no more embedded, and thus a much more fast app by removing the XAML load time.

Amazing!

Read more

In my talks, speaking about Xamarin.Forms, the most common question is: “Wonderful technology! But … when Xamarin.Forms is the preferred choice? Why (and when) I should use it instead of native apps?”

My answer: “It depends!”

Xamarin.Forms is really a great and fast way to develop mobile apps by abstracting controls in XAML, a simple description on what we want to do. That controls are then “magically rendered” in native controls. With this in mind, it’s impossible to abstract all the things completely, so sometimes it’s necessary to extend the framework with custom renderers. This means that you must know the target OS environment. No way.

In his post “How to success with Xamarin Forms”, Daniel Hindrikes says that you must don’t care if your app “doesn’t look perfect from the beginning. When you have created your app and built all the business logic, then you can start to look at how to make the app perfect.”. While I totally agree with him, I would add another step: after building all the business logic and the first UI version, evaluate if Xamarin.Forms is the right the framework for your app.

 

Read more