1

What I am trying to achieve here is a global loading indicator with MvvmCross.

From what I gathered so far it appears that I can implement this by using a BaseView and BaseViewModel. The BaseViewModel should contain an IsLoading property that the BaseView can Bind to. Therefore, I can set IsLoading to true in any of my ViewModels to cause the indicator to be displayed.

The BaseViewModel looks like this:

public abstract class BaseViewModel : MvxViewModel
{
    private bool _isLoading = false;
    public bool IsLoading
    {
        get { return _isLoading; }
        set { _isLoading = value; RaisePropertyChanged(() => IsLoading); }
    }

    private string _loadingMessage = "Loading...";
    public string LoadingMessage
    {
        get { return _loadingMessage; }
        set { _loadingMessage = value; RaisePropertyChanged(() => LoadingMessage); }
    }
}

As for binding to the ViewModel, this issue was addressed here: https://stackoverflow.com/a/10930788

I was successfully able to listen to IsLoading by attaching to the PropertyChanged event, however, since this is not a "real" binding it will not fire if IsLoading is set to true before you attach to the event (Such as before the view is loaded).

Next I attempted to call AddBindings to attach to my BaseViewModel in order to create a real binding between the two properties, although this does not appear to work (no errors).

Here is what my BaseView currently looks like for iOS:

public abstract class BaseView<TViewModel> : MvxViewController where TViewModel : BaseViewModel
{
    public TViewModel ViewModel
    {
        get { return (TViewModel)base.ViewModel; }
        set { base.ViewModel = value; }
    }

    protected BaseView(string nib, NSBundle bundle) : base(nib, bundle)
    {
    }

    private LoadingOverlay _loadingOverlay;

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        _loadingOverlay = new LoadingOverlay(View.Frame);
        this.AddBindings(new Dictionary<object, string>()
        {
            {this, "{'IsLoading':{'Path':'IsLoading'}}"},
            {_loadingOverlay, "{'LoadingMessage':{'Path':'LoadingMessage'}}"}
        });
    }

    public bool IsLoading
    {
        set
        {
            if (value)
                View.Add(_loadingOverlay);
            else
                _loadingOverlay.Hide();
        }
    }
}

Are there any pitfalls to AddBindings that I may be unaware of? or is there a newer method altogether that I should be using?

I Appreciate the help, Thanks.

Community
  • 1
  • 1
noxryan
  • 13
  • 3

1 Answers1

0

If you are using v3, then by default you must change over to the new 'Swiss' style bindings.

These change Json text like:

 "{'LoadingMessage':{'Path':'LoadingMessage'}}"

Into simpler text like:

 "LoadingMessage LoadingMessage"

For more on this, see http://blog.ostebaronen.dk/2013/01/awesome-mvvmcross-swiss-bindings-for.html


One further option you can use in v3 is 'fluent bindings'. To see these in action, see all the iOS samples in the N+1 series - http://mvvmcross.wordpress.com/, or questions like Fluent Bindings and UIButton titles

Eg something like:

 this.CreateBinding().For("LoadingMessage").To("LoadingMessage").Apply();

It may also help for debugging if you enable additional trace - see MvvmCross Mvx.Trace usage

Community
  • 1
  • 1
Stuart
  • 66,722
  • 7
  • 114
  • 165