Skip to content

Instantly share code, notes, and snippets.

@HenKun
Last active January 8, 2025 23:54
Show Gist options
  • Select an option

  • Save HenKun/c5fa795fa53ac75a7ecee57bd09a225e to your computer and use it in GitHub Desktop.

Select an option

Save HenKun/c5fa795fa53ac75a7ecee57bd09a225e to your computer and use it in GitHub Desktop.

Revisions

  1. HenKun revised this gist Mar 5, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Readme.md
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,7 @@ You can even add your own Converter and ConverterParameter within the markup, wh
    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.
    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):
  2. HenKun revised this gist Mar 5, 2018. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -5,15 +5,15 @@ 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}" />
    &lt;Label Text="{ext:SwitchBinding IsLoggedIn, True=Log out, False=Log in}" /&gt;

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

    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}" />
    &lt;Label IsVisible="{ext:SwitchBinding IsLoggedIn, True=False, False=True}" /&gt;

    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.

    @@ -24,4 +24,4 @@ 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}}" />
    &lt;Label Text="{ext:SwitchBinding IsLoggedIn, True={Binding LogoutString}, False={Binding LoginString}}" /&gt;
  3. HenKun created this gist Mar 5, 2018.
    27 changes: 27 additions & 0 deletions Readme.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,27 @@
    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}}" />
    87 changes: 87 additions & 0 deletions SwitchBindingExtension.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,87 @@
    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();
    }
    }
    }
    }