Skip to content

Instantly share code, notes, and snippets.

@softlion
Last active January 4, 2018 08:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save softlion/3a5026477c90d853e806f4ed9ff1af8d to your computer and use it in GitHub Desktop.
Save softlion/3a5026477c90d853e806f4ed9ff1af8d to your computer and use it in GitHub Desktop.
Mvvmcross tricks

Abstract

Mvvmcross includes a convert which translates a boolean into an MvxVisibility enumerable, and a target binding on each platform which translates an MvxVisibility to either a View.Visibility on Android, or an inverted boolean for UIView.Hidden on iOS.

Its usage requires to use a magic string ("Visibility") 2 times in the binding description. And it supports only boolean values in the viewmodel.

And last, it is distributed as a Mvvmcross plugin, which slows down the app's startup time, and crashes the app when the "link all" build option is activated", unless you add special code to prevent it. If you forget to add the plugin, it won't crash, it won't log, and you may search for your error a long time before remembering to add the plugin.

Introducing Visibility2

The name is derived from the mvvmcross one, but it differs in many ways:

  • needs only one target binding, no more converter. The target binding will do the conversion for you.
  • supports any type as source. bool? is translated to Gone/Visible/Invisible. bool is translated to Gone/Visible. other objects are compared to null. Also supports MvxVisibility in case you still used the visibility converter.
  • no more magic string: use the name property on the class instead (see example below)
  • just works in many professional projects !

Usage

Viewmodel:

var set = this.CreateBindingSet<StreamFlightCell, StreamFlightCellViewModel>();
set.Bind(MenuButton).For(Visibility2TargetBinding.Name).To(vm => vm.IsMenuButtonVisible);
set.Apply();

View:

    public abstract class StreamBaseCellViewModel : BaseViewModel
    {
        /// <summary>
        /// True if current user is owner of this flight
        /// </summary>
        public bool IsMenuButtonVisible { get; set; }

        protected StreamBaseCellViewModel() : base(false)
        {
        }
    }

See Also Using SVG autoscaling images for all your icons

using System;
using Foundation;
using MvvmCross.Binding;
using MvvmCross.Binding.Bindings.Target;
using MvvmCross.Binding.Bindings.Target.Construction;
using MvvmCross.Platform.UI;
using UIKit;
namespace Vapolia.Ios.Lib.MvxUi
{
[Preserve]
public class Visibility2TargetBinding : MvxConvertingTargetBinding
{
public const string Name = "Visibility2";
[Preserve]
public Visibility2TargetBinding(UIView target) : base(target)
{
}
public static void Register(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterCustomBindingFactory<UIView>(Name, view => new Visibility2TargetBinding(view));
registry.RegisterCustomBindingFactory<UIView>("Visibility", view => new Visibility2TargetBinding(view));
}
[Preserve]
public override Type TargetType => typeof(UIView);
[Preserve]
public override MvxBindingMode DefaultMode => MvxBindingMode.OneWay;
[Preserve]
protected override void SetValueImpl(object target, object value)
{
if (!(target is UIView view))
return;
var visible = ConvertToBool(value);
view.Hidden = !visible;
}
public static bool ConvertToBool(object o)
{
if (o == null)
return false;
if (o is MvxVisibility visibility)
return visibility == MvxVisibility.Visible;
return Convert.ToBoolean(o);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment