Xamarin Forms Triggers vs Behaviors vs Effects

Introduction

Xamarin Forms has many ways to modify the UI based on certain criteria, data or events such as Triggers, Behaviors or Effects. You can also accomplish the same or similar things with each technique hence initially it can be confusing as to which method would be the best for each scenario.

computer-on-desk

Triggers

Triggers take a trigger source such as an event and then can change a property on that control in response to the trigger. The basic principle is, a trigger is activated and you set properties or invoke code. Below are the following triggers you can use.

  • Property
  • Data
  • Event
  • Multi Trigger

Documentation: Working with Triggers

Example Use Case: Update the Background Color of Entry control when IsFocused becomes true.

public class BackgroundColorTrigger : TriggerAction<Entry>
{    
     protected override void Invoke(Entry sender)
     {
         sender.BackgroundColor = Color.Yellow;
     }
}

Then we can apply it to an Entry Control and define what triggers the trigger.

// Add to Page Attributes (Above Trigger is in Namespace Mobile.Trigger)
xmlns:trigger="clr-namespace:Mobile.Trigger"

<Entry Text="{Binding EntryField}">   
    <Entry.Triggers>
        <EventTrigger Event="Focused">
            <trigger:BackgroundColorTrigger />
        </EventTrigger>
    </Entry.Triggers>
</Entry>

Behaviors

Behaviors allow you to enhance the functionality of a Xamarin Forms control without sub classing. Using the Behaviors property you can add behaviors that attached to the Control and can execute code when events of that control are raised.

Documentation: Introduction to Behaviors

Example Use Case: Apply validation rules to an Entry control.

Here is an example of applying a maximum length validator to an Entry Control. First we create a behavior.

public class MaxLengthCheckValidator: Behavior<Entry>
{

    public static readonly BindableProperty IsValidProperty = BindableProperty.Create("IsValid", typeof(bool), typeof(MaxLengthCheckValidator), false);
    public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create("MaxLength", typeof(int), typeof(MaxLengthCheckValidator), 0);

    public int MaxLength
    {
       get { return (int)GetValue(MaxLengthProperty); }
       set { SetValue(MaxLengthProperty, value); }
    }

    public bool IsValid
    {
       get { return (bool)GetValue(IsValidProperty); }
       set { SetValue(IsValidProperty, value); }
    }

    protected override void OnAttachedTo(Entry bindable)
    {
       bindable.TextChanged += bindable_TextChanged;
    }

    private void bindable_TextChanged(object sender, TextChangedEventArgs e)
    {
       IsValid = e.NewTextValue?.Length >= MinLength;
    }

    protected override void OnDetachingFrom(Entry bindable)
    {
       bindable.TextChanged -= bindable_TextChanged;
    }
 }

Then we apply it to an entry control. We can use the IsValid property to bind to something just as a Button IsEnabled Property or similar to stop users from progressing forward without meeting the forms requirements.

// Add to Page attributes
xmlns:behavior="clr-namespace:Mobile.Behavior"

<Entry Text="{Binding EntryField}">
    <Entry.Behaviors>
        <behavior:MaxLengthCheckValidator MaxLength="10" IsValid="{Binding Source={x:Reference this}, BindingContext.IsUsernameValid, Mode=OneWayToSource}" />
    </Entry.Behaviors>
</Entry>

Effects

Effects allow the changing of platform specific properties on a native control without the need for a Custom Renderer. They are typically used for changing styling of a property when the property has not been exposed via the Xamarin Forms Control.

  • Effects are designed to be reusable
  • Need a custom renderer if you want to override methods
  • Need a custom renderer if you want to replace the control used on the platform

Documentation: Introduction to Effects

Example Use Case: Changing the color of the placeholder text in an Entry control.

First on the native platform, in this example iOS, we create a Platform Effect.

[assembly:ResolutionGroupName ("Xamarin")]
[assembly:ExportEffect (typeof(PlaceholderEffect), "PlaceholderEffect")]
namespace Mobile.iOS
{
    public class PlaceholderEffect : PlatformEffect<UIView, UITextField>
    {
        protected override void OnAttached()
        {
            Control.AttributedPlaceholder = new NSAttributedString(Control.Placeholder, null, UIColor.Red);
        }

        protected override void OnDetached()
        {
        }

        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)
        {
            base.OnElementPropertyChanged(args);
            // You can do effects only when certain properties change here.
        }
    }
}

Next if we are in a PCL we need to add a RoutingEffect so XAML in the PCL can reference the platform specific implementation.

public class PlaceholderEffect : RoutingEffect
{
    public PlaceholderEffect () : base ("Xamarin.PlaceholderEffect")
    {
    }
}

Now we can add the effect to the control.

// Add this to your page attributes (change Mobile.Effects to whatever full namespace your placeholder effect is in)
xmlns:local="clr-namespace:Mobile.Effects"

<Entry Text="{Binding EntryField}">
    <Entry.Effects>
        <local:PlaceholderEffect />
    </Entry.Effects>
</Entry>
Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

2 Comments

  1. Raja Babua

    IsValid = e.NewTextValue?.Length >= MinLength;

    Shouldn’t the MinLength be MaxLength?
    I guess just a typo, please update.

Leave A Comment?