Extended Xamarin.Forms Controls Functionalities

0
390

Xamarin.Forms are awesome and its always providing you with a native build where shared application logic layer and UI bundles together. Built-in Xamarin.Forms view controllers are also giving a huge advantage to add functionalities to the app from the user experience and user interface perspective.

However, its impossible to mix and match developers creative needs by the Xamarin engineers who build API’s for the forms UI. For that, we have one-stop solution that is the Xamarin.Forms Behaviors.

https://blog.xamarin.com/extend-xamarin-forms-controls-functionality-with-behaviors

Lets see how we can create a simple behaviour. In this behaviour i’m going to demonstrate a validation routing picker controler. Note that these behaviours can be applied to any of the views in Xamarin.Forms.

Here, the picker background color will change when the item is not represented in the current list of values.

 

blog

 

Behaviors Methods

To start with, all behaviors must inherit from the Behavior<T> class.

3
4
5
6
7
8
9
10
11
12
public class SimplePickerValidator : Behavior<Picker>
{
    protected override void OnAttachedTo(Picker bindable)
    {
        base.OnAttachedTo(bindable);
    }
    protected override void OnDetachingFrom(Picker bindable)
    {
        base.OnDetachingFrom(bindable);
    }

 

 

There are two methods that we override here:

  1. OnAttachedTo: Gets invoked whenever the behavior is attached to the Picker.
  2. OnDetachingFrom: Is naturally invoked when the behavior is being removed from the Picker.

Note that a strongly typed Picker is passed in to both methods. This is because we inherited from Behavior<Picker>.

When implementing a behavior, you’ll generally want to handle an event that the host control emits. Inside that event handler, you’ll be able to add the additional functionality, or additional behavior, to the control. So, the OnAttachedTo becomes the place to subscribe to the event, while the OnDetachingFrom becomes the place to unsubscribe from the same event.

This SimplePickerValidator behavior now looks like this:

public class SimplePickerValidator : Behavior<Picker>
{
    protected override void OnAttachedTo(Picker bindable)
    {
        bindable.SelectedIndexChanged += Bindable_SelectedIndexChanged;
    }
    protected override void OnDetachingFrom(Picker bindable)
    {
        bindable.SelectedIndexChanged -= Bindable_SelectedIndexChanged;
    }
    void Bindable_SelectedIndexChanged(object sender, EventArgs e)
    {
    }
}

Implementing

Before implementing the Bindable_SelectedIndexChanged method, there needs to be a way for the calling code, like the XAML page, to specify what the correct values are for this behavior to validate against.

Bindable properties to the rescue! That’s right, behaviors can contain bindable properties, just like any other Xamarin.Forms control. Add a property called ValidValues like so:

public class SimplePickerValidator : Behavior<Picker>
{
    static readonly BindableProperty ValidValuesProperty =
        BindableProperty.Create(nameof(ValidValues), typeof(string[]), typeof(PickerColorBehavior));
    public string[] ValidValues
    {
        get => (string[])GetValue(ValidValuesProperty);
        set => SetValue(ValidValuesProperty, value);
    }
    protected override void OnAttachedTo(Picker bindable)
    {
        bindable.SelectedIndexChanged += Bindable_SelectedIndexChanged;
    }
    protected override void OnDetachingFrom(Picker bindable)
    {
        bindable.SelectedIndexChanged -= Bindable_SelectedIndexChanged;
    }
    void Bindable_SelectedIndexChanged(object sender, EventArgs e)
    {
    }
}
Finally, implement the logic of Bindable_SelectedIndexChanged:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Bindable_SelectedIndexChanged(object sender, EventArgs e)
{
    // Bound and cast to a picker
    if (!(sender is Picker bindable))
        return;
    // Make sure the picker is data bound
    if (!(bindable.ItemDisplayBinding is Binding displayBinding))
        return;
    // Get the binding’s path
    var displayBindingPath = displayBinding.Path;
    // Use reflection to get the value of the selected item of the picker
    var selectedItem = bindable.SelectedItem.GetType().GetRuntimeProperty(displayBindingPath);
    var selectedText = selectedItem.GetValue(bindable.SelectedItem);
    // Check to see if everything is valid
    if (ValidValues != null && ValidValues.Contains(selectedText))
    {
        IsValid = true;
        bindable.BackgroundColor = Color.Default;
    }
    else
    {
        IsValid = false;
        bindable.BackgroundColor = Color.Salmon;
    }
}

Here’s what’s going on in the above event handler: because the behavior is checking to see whether the displayed value in a data-bound Picker is equal to a value in an array, you first need to get that value out. You can use reflection to get to the text displayed in a Picker‘s data binding.2

Once the value is in selectedText, check to see if that exists in the ValidValues array.

Adding Behaviors

The very last step is to add this behavior to a control. In XAML, it would look like this:

2
3
4
5
6
7
8
9
10
11
<Picker Title=“Rate Your Beard”
    ItemsSource=“{Binding BeardRatings}”
    SelectedItem=“{Binding SelectedBeardRating}”
    ItemDisplayBinding=“{Binding Description}”>
    <Picker.Behaviors>
        <local:PickerColorBehavior
            ValidValues=“{x:Static local:BehaviorsPageViewModel.ValidRatings}” />
    </Picker.Behaviors>
    
</Picker>

 

Note the property<Picker.Behaviors> is the collection where this (and any other Behaviors) are added, and that the local XAML namespace was defined elsewhere.

Reference and Sources: Xamarin Official Blog 

Comments

comments

LEAVE A REPLY

Please enter your comment!
Please enter your name here