This chapter will deal with the interaction between UI elements and potential business logic. In order to react on UI events like a changed text of an entry field or a new slider position, we usually have to subscribe an event handler to the corresponding events. And in some cases it is important to unsubscribe afterwards in order to prevent the potentially long-living event handler from holding on to the UI element.
In the following sections, we will discuss three advanced concepts to link properties of one or multiple objects and to act or react in a certain way depending on other properties. While data binding has always been a feature of Xamarin.Forms, behaviors and triggers entered the stage in version 1.3.
17.1 Bindings
Let’s start with bindings, a concept to link different properties like a slider position and a label text or the background color. To create a very simple binding example, we start with exactly those UI elements: a Slider with a default range from 0.0 to 1.0 as well as a Label with centered text alignment.
var slider = new Slider();
var label = new Label{ HorizontalTextAlignment = TextAlignment.Center };We place them into a Stacklayout and add it to the content page.
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
slider,
label,
},
},
};
The label is meant to display the value of the slider. We could subscribe an event handler to the latter’s ValueChanged event and set the text accordingly. Alternatively, we can bind the label text to the slider value. First, we need to set the label’s BindingContext, i.e. the object which all bindings are referring to. And we set the binding of the label’s TextProperty to the slider’s ValueProperty. In this case, we might want to specify the stringFormat with two decimal places. (Otherwise the default format will contain up to 15 decimal places.)
label.BindingContext = slider;
label.SetBinding(Label.TextProperty, new Binding(Slider.ValueProperty.PropertyName, stringFormat: "{0:0.00}"));
You often see the second line like label.SetBinding(Label.TextProperty, new Binding("Value", ...)).
We recommend using Slider.ValueProperty.PropertyName instead of "Value", because this way you can’t have any typos within the string and both the compilier and the code completion help you to avoid mistakes. Furthermore – when creating your own bindable objects with bindable properties – you can easily refactor property names.
So, whenever we move the slider, the text is updated.
As a second, slightly more complex example, we want to bind the background color of the content page to the slider’s position. Since the conversion between a floating point value and an RGB color is obviously nontrivial, we need to implement a converter.
public class DoubleToColorConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Color.FromHsla((double)value, 0.7, 0.7);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
It implements the IValueConverter interface with methods, Convert and ConvertBack. The Convertmethod takes a double value and creates a color from hue (the value), saturation (always 0.7) and luminosity (always 0.7). As long as our binding will only convert the slider position into a background color and not vice versa, we don’t need to implement the second method.
Using this DoubleToColorConverter we can define the binding similarly to the one above. Instead of specifying a stringFormat, we pass an instance of the converter class.
MainPage.BindingContext = slider;
MainPage.SetBinding(VisualElement.BackgroundColorProperty, new Binding(Slider.ValueProperty.PropertyName, converter: new DoubleToColorConverter()));
So the slider not only controls the label text, but the background color as well. The screenshot below shows three example states.