Roosmaa/MvxMod — pull request #2 by Roosmaa (2013-02-19 10:36:15+00:00)
Title: Add fragment support for the framework

Instead of deriving from regular `Activity` (which does not have fragment support on older devices) we use the Android support library and derive from `FragmentActivity` instead. This allows everyone to enjoy fragments. (In the future when there is no more need for a support library we will need to revert the base class back to `Activity`.)

I also introduced `MvxFragmentDataStore` to pass data from `MvxActivityView` to `MvxFragment` easily. The overall idea is to keep fragments as reusable as possible and not have them worry about where they get their data/view model.

The `MvxFragment` is a base class that every fragment should derive from if they want to seamlessly get data from the `MvxFragmentDataStore`.

For people who use the binding project there is the `MvxBoundFragment` class, which eliminates the need to create custom fragment classes all of the time. It construct the layout you specify automatically and binds the data to it, so if there is no custom logic needed other than databinding there is no need to override the `MvxFragment` class.

## Custom Fragment Example

To create a custom fragment which shows the content only when data is available, otherwise it hides it, we would create something like this:

```C#
using System;
using Android.Views;
using Android.OS;
using Cirrious.MvvmCross.Droid.Views;
using Sample.Core.ViewModels;

namespace Sample.Droid
{
public class HomeFragment : MvxFragment
{
public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedState)
{
var root = inflater.Inflate (Resource.Layout.FragmentHome, container, false);
root.Visibility = Data == null ? ViewStates.Gone : ViewStates.Visible;
return root;
}

protected override void OnDataChanged ()
{
base.OnDataChanged ();
if (View != null) {
View.Visibility = Data == null ? ViewStates.Gone : ViewStates.Visible;
}
}
}
}
```

To use that in your `MvxActivityView` and set data for it, we would have to have something like this:

```C#
using System;
using Android.App;
using Android.OS;
using Cirrious.MvvmCross.Droid;
using Cirrious.MvvmCross.Droid.Views;
using Sample.Core.ViewModels;

namespace Sample.Android.Views
{
[Activity(Exported = false)]
public class HomeView : MvxActivityView
{
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);

SetContentView (Resource.Layout.ActivityHome);

// Regular Android way of creating/adding the fragment:
if (savedInstanceState == null) {
SupportFragmentManager.BeginTransaction ()
.Add (Resource.Id.FragmentMain, new HomeFragment ())
.Commit ();
}
}

protected override void OnViewModelSet ()
{
base.OnViewModelSet ();

// Set the data for the fragment, so it would show the content:
FragmentDataStore.SetValue (Resource.Id.FragmentMain, ViewModel);
}
}
}
```

## Bound Fragment Example

If you use the binding project using fragments is even simpler. You just need to have the following in your Activity view:

```C#
using System;
using Android.App;
using Android.OS;
using Cirrious.MvvmCross.Binding.Droid.Views;
using Cirrious.MvvmCross.Droid;
using Cirrious.MvvmCross.Droid.Views;
using Sample.Core.ViewModels;

namespace Sample.Android.Views
{
[Activity(Exported = false)]
public class HomeView : MvxBindingActivityView
{
protected override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);

SetContentView (Resource.Layout.ActivityHome);

if (savedInstanceState == null) {
SupportFragmentManager.BeginTransaction ()
.Add (Resource.Id.FragmentMain,
new MvxBoundFragment (Resource.Layout.FragmentMain))
.Commit ();
}
}

protected override void OnViewModelSet ()
{
base.OnViewModelSet ();
FragmentDataStore.SetValue (Resource.Id.FragmentMain, ViewModel);
}
}
}
```