Reputation: 471
struggling quite a bit with some Fragment navigation and been going at this for a few days now without any progress.
I have a ViewModel called "NewsViewModel" which contains the property NewsItemWraps. This is the list of news in a wrapper model. This is just displayed in my view in a list, and i want users to be able to tab a news item and see the details for this news.
This works perfectly fine as long as the user only sees the same NewsDetail. But if you choose item 1, navigate back to the list, pick item 2 see the details and you navigate back again to the list i receive the following error: Contract failed - Fragment tag is null! Fragment tags are not set by default, you should add tag during FragmentTransaction or override UniqueImmutableCacheTag in your Fragment class.
public override void OnBackPressed()
{
var currentFragment = SupportFragmentManager.FindFragmentById(Resource.Id.content_frame) as MvxFragment;
if (currentFragment != null && SupportFragmentManager.BackStackEntryCount >= 1)
{
SupportFragmentManager.PopBackStackImmediate(); //<-- This guy tosses the error
return;
}
if (DrawerLayout != null && DrawerLayout.IsDrawerOpen(GravityCompat.Start))
DrawerLayout.CloseDrawers();
else
base.OnBackPressed();
}
I've tried modifying the tag on the fragmentInfo when I add the Fragment to the BackStack in OnFragmentCreated, but that didn't change anything. It doesnt matter if i add it to the backstack like this in OnFragmentCreated or let the 'addToBackstack' bool handle that like in the sample. It also doesn't care if its being cached or not.
public override void OnFragmentCreated(IMvxCachedFragmentInfo fragmentInfo, Android.Support.V4.App.FragmentTransaction transaction)
{
// You can do fragment + transaction based configurations here.
// Note that, the cached fragment might be reused in another transaction afterwards.
//Adding the fragment to the stack manually.
if (fragmentInfo.Tag.Contains(typeof(NewsDetailsViewModel).Name))
{
transaction.AddToBackStack(typeof(NewsDetailsViewModel).Name);
}
base.OnFragmentCreated(fragmentInfo, transaction);
var myCustomInfo = fragmentInfo as CustomFragmentInfo; //How the sample handles the backstack in the factory MainActivityFragmentCacheInfoFactory.
}
My type in the cacheFactory:
{
typeof (NewsDetailsViewModel).ToString(),
new CustomFragmentInfo(typeof (NewsDetailsViewModel).Name,
typeof (NewsDetailsFragment),
typeof (NewsDetailsViewModel), cacheFragment: false, addToBackstack: true, isRoot:false )
}
Property in NewsViewModel:
private List<NewsItemWrap> _newsItemWraps;
public List<NewsItemWrap> NewsItemWraps
{
get { return _newsItemWraps ?? (_newsItemWraps = new List<NewsItemWrap>()); }
set { _newsItemWraps = value; RaisePropertyChanged(() => NewsItemWraps); }
}
I've been playing around and modifying the sample here from Mvvmcross: https://github.com/MvvmCross/MvvmCross-AndroidSupport/tree/master/Samples
Any pointers and suggestions would be greatly appreciated
The full stack:
System.InvalidOperationException: Contract failed - Fragment tag is null! Fragment tags are not set by default, you should add tag during FragmentTransaction or override UniqueImmutableCacheTag in your Fragment class.
02-19 09:38:56.795 I/MonoDroid(30813): UNHANDLED EXCEPTION: 02-19 09:38:56.795 I/MonoDroid(30813): System.InvalidOperationException: Contract failed - Fragment tag is null! Fragment tags are not set by default, you should add tag during FragmentTransaction or override UniqueImmutableCacheTag in your Fragment class. 02-19 09:38:56.795 I/MonoDroid(30813): at MvvmCross.Droid.Support.V7.Fragging.Fragments.MvxFragmentExtensions.RegisterFragmentViewToCacheIfNeeded (IMvxFragmentView fragmentView) [0x0005a] in :0 02-19 09:38:56.795 I/MonoDroid(30813): at MvvmCross.Droid.Support.V7.Fragging.Fragments.MvxBindingFragmentAdapter.HandleCreateCalled (System.Object sender, MvvmCross.Platform.Core.MvxValueEventArgs
1 bundleArgs) [0x00024] in <filename unknown>:0 02-19 09:38:56.795 I/MonoDroid(30813): at MvvmCross.Platform.Core.MvxDelegateExtensionMethods.Raise[T] (System.EventHandler
1 eventHandler, System.Object sender, MvvmCross.Platform.Core.T value) [0x00000] in V:\Xamarin\MvvmCross\MvvmCross\Platform\Platform\Core\MvxDelegateExtensionMethods.cs:21 02-19 09:38:56.795 I/MonoDroid(30813): at MvvmCross.Droid.Support.V7.Fragging.Fragments.EventSource.MvxEventSourceFragment.OnCreate (Android.OS.Bundle savedInstanceState) [0x00014] in :0 02-19 09:38:56.795 I/MonoDroid(30813): at Android.Support.V4.App.Fragment.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00011] in :0 02-19 09:38:56.795 I/MonoDroid(30813): at (wrapper dynamic-method) System.Object:136761ed-d521-468a-9257-5d08a4df776b (intptr,intptr,intptr)
Upvotes: 3
Views: 672
Reputation: 3559
This is a bug in the current Nuget, and has been fixed in this commit: https://github.com/MvvmCross/MvvmCross-AndroidSupport/commit/72356791714795c9d711a0c491367fd5c5ebdb82
We will release an update soon.
Upvotes: 2