Skip to content

Instantly share code, notes, and snippets.

@HenKun
Last active Apr 25, 2019
Embed
What would you like to do?
MarkupExtension for Xamarin.Forms to have simple XAML inline converter

This is a simple MarkupExtension for Xamarin.Forms that imitates an if-else-statement. It was inspired by Thomas Levesque on https://stackoverflow.com/a/841894/6884587

Usage:

  1. Include xmlns:ext="clr-namespace:Xamarin.Forms.Extensions"
  2. Use on a bindable property: <Label Text="{ext:SwitchBinding IsLoggedIn, True=Log out, False=Log in}" />

You can also add a StringFormat: <Label Text="{ext:SwitchBinding IsLoggedIn, StringFormat='Action: {0}', True=Log out, False=Log in}" />

You can even add your own Converter and ConverterParameter within the markup, which get applied after the switch condition has been evaluated.

It is also possible to use this extension as an inverter like: <Label IsVisible="{ext:SwitchBinding IsLoggedIn, True=False, False=True}" />

The extension supports - identically to standard binding - the Path and Source property, where Path is set as the content property also like in the standard binding.

Prepared but not working is the feature to also bind the True and False property to a Property in your ViewModel. But this is not working due to a bug (True and False property always get assigned null):

https://bugzilla.xamarin.com/show_bug.cgi?id=25189 https://stackoverflow.com/questions/42648334/xamarin-forms-imarkupextension-with-bindable-property-does-not-work

So this is currently NOT working: <Label Text="{ext:SwitchBinding IsLoggedIn, True={Binding LogoutString}, False={Binding LoginString}}" />

using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Xamarin.Forms.Extensions
{
// credits to: https://stackoverflow.com/a/841894/6884587
[ContentProperty("Path")]
[AcceptEmptyServiceProvider]
public class SwitchBindingExtension : BindableObject, IMarkupExtension<BindingBase>
{
private readonly BindingMode _mode = BindingMode.Default;
private BindingMode Mode => _mode;
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public string Path { get; set; }
public string StringFormat { get; set; }
public object Source { get; set; }
public object True
{
get { return (object)this.GetValue(TrueProperty); }
set { this.SetValue(TrueProperty, value); }
}
public static readonly BindableProperty TrueProperty =
BindableProperty.Create(
propertyName: nameof(True),
returnType: typeof(object),
declaringType: typeof(SwitchBindingExtension),
defaultValue: null,
defaultBindingMode: BindingMode.TwoWay
);
public object False
{
get { return (object)this.GetValue(FalseProperty); }
set { this.SetValue(FalseProperty, value); }
}
public static readonly BindableProperty FalseProperty =
BindableProperty.Create(
propertyName: nameof(False),
returnType: typeof(object),
declaringType: typeof(SwitchBindingExtension),
defaultValue: null,
defaultBindingMode: BindingMode.TwoWay
);
public BindingBase ProvideValue(IServiceProvider serviceProvider)
{
var converter = new SwitchConverter(this, Converter);
return new Binding(Path, Mode, converter, ConverterParameter, StringFormat, Source);
}
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return ProvideValue(serviceProvider);
}
private class SwitchConverter : IValueConverter
{
private SwitchBindingExtension _switchExtension;
private IValueConverter _decoratee;
public SwitchConverter(SwitchBindingExtension switchExtension, IValueConverter decoratee)
{
_switchExtension = switchExtension;
_decoratee = decoratee;
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
bool b = System.Convert.ToBoolean(value);
var switchedValue = b ? _switchExtension.True : _switchExtension.False;
return _decoratee == null ? switchedValue : _decoratee.Convert(switchedValue, targetType, parameter, culture);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment