Using behaviors in Xamarin.Forms

Behaviors are used to encapsulate logic, which can be attached to a specific component. This logic can be used to make the component behave in a specific way, for instance make a log entry every time a certain event is fired, or rearrange child entities. Support for behaviors were added to Xamarin.Forms version 1.3.0.

Xamarin.Forms 1.3.0 Pre-release

At the time of writing, Xamarin.Forms version 1.3.0 is in pre-release. You can download the Nu-Get packaged needed to follow this example from here. You will need to drop the binding to the version of Xamarin.Forms you are currently using, and retarget all of your projects to use the Xamarin.Forms 1.3.0 pre-release assembly:

Xamarin 1.3 NuGet

Behaviors

In order to make a behavior, we will create a new class which will inherit from Behavior<T>:

using System;
using Xamarin.Forms;

namespace XamarinTests.Behaviors
{
	public class ChangeColorButtonBehavior : Behavior<Button>
	{
		protected override void OnAttachedTo (Button bindable)
		{
			bindable.Clicked += ButtonClicked;
			base.OnAttachedTo (bindable);
		}

		protected override void OnDetachingFrom (Button bindable)
		{
			bindable.Clicked -= ButtonClicked;
			base.OnDetachingFrom (bindable);
		}

		private void ButtonClicked(object sender, EventArgs e)
		{
			var button = sender as Button;
			button.BackgroundColor = button.BackgroundColor != Color.Blue ? Color.Blue : Color.Red;
		}
	}
}

The way behaviors are implemented in Xamarin.Forms is slightly different from the way it is implemented by Microsoft in their ecosystem. First of all, we do not have access to the AssociatedObject member in our class. Instead, the associated object is injected in the relevant overrides instead. From here we can subscribe to all relevant events, and perform as usual. In this example, I am flipping the background color of a button every time it is clicked. It might not be the most exciting example, but it is sufficient to demonstrate concept of behaviors.

Adding behaviors to elements

Now that our behavior implementation is done, it is time to add it to a Button element:

<?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:behaviors="clr-namespace:XamarinTests.Behaviors;assembly=XamarinTests"
             x:Class="XamarinTests.BehaviorTestpage">
  <ContentPage.Content>
    <StackLayout>
      <Button Text="Click to chance color!">
        <Button.Behaviors>
          <behaviors:ChangeColorButtonBehavior />
        </Button.Behaviors>
      </Button>
      <Button Text="Click to do nothing!" />
    </StackLayout>
  </ContentPage.Content>
</ContentPage>

This piece of XAML also shows a key difference between the way behaviors are implemented in Xamarin.Forms. Here it is not necessary to import a special namespace to handle behaviors, as every element inheriting from VisualElement contains an IList<Behavior> member. To access the ChangeColorButtonBehavior created earlier in this example, we import the namespace in which it resides using the standard clr-namespace import syntax. We then add the behavior to the first Button element, and now we are ready to test the behavior:

Button click black

When the view is loaded for the first time, both of the Button elements will contain their standard background color. If we click both of the Button elements now, we will get the following:

Button click blue

Here we can see the behavior attached to the first button in action. The background color of the first Button element is now blue. The second Button remains unaffected by the behavior, as it is not attached to that element. By clicking both of the Button elements again, we get the following:

Button click red

Once again the background color of the second Button element remains unchanged, while the background color of the first Button element has been changed to red. By repeating this pattern we will see the color of the first Button element flip between blue and red.

comments powered by Disqus