Question

I've been playing around with this for a while and I'm just wondering the best way to go about adding in an app-wide NavigationDrawer.

  1. From what I can gather, the best way would be to implement the v4 widget system and have each view as a Fragment and put that into the 'HomeView' (which is just the main view containing the NavigationDrawer and the fragment to programatically overwrite). This approach seems the cleanest in theory but then I lose all of the niceties that come along with using MvvmCross and seem to render using it pointless. By this I mean I'll lose the use of the ICommand binding on the viewmodel to navigate from within a fragment to go to another child page/fragment. (unless I'm mistaken?)
  2. An alternative I was thinking was to effectively have a 'master' base view that all my views inherit from which houses a custom NavigationDrawer that doesn't use Fragments. But finding an example of this sort of setup seems impossible and I'm fairly new to Xamarin/MvvmCross to attempt this type of structure just yet.

Does anyone have any advice or ideas on best practices for this? Ideally I want option 1, but I want to keep and maintain the ICommand bindings in the ViewModel for cross platform compatibility.

Was it helpful?

Solution

I ended up going for option 1, using http://motzcod.es/post/60427389481/effective-navigation-in-xamarin-android-part-1 as a base point of reference.

I now have one main view (HomeView) and every other page is now a Fragment that gets put into the content_frame Fragment.

All of my pages inherit from BaseFrag which has GoToView method. It does mean I've lost the cross platform ICommand binding in the view model which is a shame. I might try and revisit the issue in future.

public abstract class BaseFrag : MvxFragment
    {
        protected abstract int ViewId { get; }

        public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Bundle savedInstanceState)
        {
            var ignored = base.OnCreateView(inflater, container, savedInstanceState);
            return this.BindingInflate(ViewId, null);
        }

        protected void GoToView<TFrag, TModel>(TFrag fragment, TModel viewModel) where TFrag : MvxFragment where TModel : MvxViewModel
        {
            var activity = (HomeView)Activity;
            fragment.ViewModel = viewModel;
            var trans = activity.SupportFragmentManager.BeginTransaction();
            trans.Replace(Resource.Id.content_frame, fragment);
            trans.AddToBackStack(null);
            trans.Commit();
        }
    }

I will also try and revisit having to pass in the view models and look at the Dependency Injection that MvvmCross does under the hood to make this process a bit less manual. In my page fragments I just have to bind the click event to a ListViewItem and call the GoToView method

public class NowShowingView : BaseFrag
    {
        protected override int ViewId
        {
            get { return Resource.Layout.NowShowingView; }
        }

        public override void OnViewCreated(Android.Views.View view, Bundle savedInstanceState)
        {
            var grid = view.FindViewById<MvxGridView>(Resource.Id.now_showing_grid);
            grid.ItemClick = new MvxCommand<RankedMovie>(item => 
                {
                    var viewModel = new MovieDetailsViewModel(new MovieService());
                    viewModel.Init(item.Title, item.MoviePosterImage, item.Id);
                    GoToView(new MovieDetailsView(), viewModel);
                });

            base.OnViewCreated(view, savedInstanceState);
        }
    }

But this will do me for now until I have a bit more time to invest in abstract it out a bit more.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top