Value converters
Value converters can be described as simple translation tools that implement the IValueConverter interface. This interface provides two methods, which allow the translation of the source to the target, as well as from the target to the source to support various binding scenarios.
For instance, if we were to display the release date of an item from our inventory, we would need to bind to the respective property on ItemViewModel. However, once the page is rendered, the result is less than satisfactory:
In order to format the date, we can create a value converter, which is responsible for converting the DateTime value to a string:
public class DateFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object
parameter, CultureInfo culture)
{
if(value is DateTime date)
{
return date.ToShortDateString();
}
return null;
}
public object ConvertBack(object value, Type targetType, object
parameter, CultureInfo culture)
{
// No Need to implement ConvertBack for OneTime and OneWay
bindings.
throw new NotImplementedException();
}
}
And it is also responsible for declaring this converter in our XAML:
<ContentPage
...
xmlns:converters="using:FirstXamarinFormsApplication.Client.Converters"
x:Class="FirstXamarinFormsApplication.Client.ItemView">
<ContentPage.Resources>
<ResourceDictionary>
<converters:DateFormatConverter x:Key="DateFormatConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<!-- Removed for brevity -->
<Label Text="{Binding ReleaseDate, Converter={StaticResource DateFormatConverter}}" />
<!-- Removed for brevity -->
</ContentPage.Content>
</ContentPage>
Now, the display would use the short date format, which is culture-dependent (for example, M/d/yyyy for the EN-US region):
We can take this implementation one step further by using a binding to pass the date format string (for example, M/d/yyyy ) to use a fixed date format.
Xamarin.Forms also provides the use of formatted strings to handle simple string conversions, so that simple converters such as DateFormatConverter could be avoided. The same implementation with a fixed date format could have been set up as follows:
<Label Text="{Binding ReleaseDate, StringFormat='Release {0:M/d/yyyy}'}}" />
The outcome would look like this:
Additionally, we may like to handle scenarios where the release date is set to null (that is, when the ReleaseDate property is set to Nullable<DateTime> or simply DateTime). For this scenario, we can resort to the use of TargetNullValue:
<Label Text="{Binding ReleaseDate, StringFormat='Release {0:M/d/yyyy}', TargetNullValue='Release Unknown'}" />
TargetNullValue, as the name suggests, is a replacement value when the binding target is resolved but the value found was null. Similarly, FallbackValue could be used when the runtime cannot resolve the target property on the binding context.
Expanding this implementation, we may want to display the Label with a different color if the release date is unknown. In order to achieve this, we could potentially create a converter to return a certain color depending on the release value, but we could also use a property trigger to set the font color depending on the label's Text property value. In this situation, the use of a trigger is a better choice, since using the converter would mean hardcoding the color value, whereas the trigger can use dynamic or static resources and can be applied with styles for the target view.