2017-05-25 53 views
-1

我一直在爲此掙扎2天,而且現在我很困難。由於某些原因,片段的綁定根本無法啓動。頁面顯示正確,並且選項卡可以正常工作。我可以從選項卡1滑動到2,反之亦然。 TextView應該顯示來自視圖模型的一些文本。當我調試這兩個片段的構造函數時,viewmodel被執行,但是LoginNotificationViewModel(LoginDescription和LastLoginRequestReceivedOn)的屬性永遠不會觸發。TabLayout中的片段不綁定到viewmodel

我有一個持有TabLayout,你可以看到下面一個觀點:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:local="http://schemas.android.com/apk/res-auto" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 
    <include 
     layout="@layout/header" /> 
    <LinearLayout 
     android:orientation="vertical" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:id="@+id/main_content" 
     android:layout_below="@id/header"> 
     <android.support.design.widget.TabLayout 
      android:id="@+id/sliding_tabs" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      local:tabMode="fixed" /> 
     <android.support.v4.view.ViewPager 
      android:id="@+id/viewpager" 
      android:layout_width="match_parent" 
      android:layout_height="0px" 
      android:layout_weight="1" 
      android:background="@android:color/white" /> 
    </LinearLayout> 
</RelativeLayout> 

的TabView的代碼:

using Android.App; 
using Android.OS; 
using Android.Runtime; 
using Android.Support.Design.Widget; 
using Android.Support.V4.View; 
using Android.Support.V7.Widget; 
using Android.Views; 
using MvvmCross.Droid.Support.V4; 
using Notifier.Adapters; 
using Notifier.Android.Fragments; 
using Notifier.Classes; 
using Notifier.ViewModels; 
using System; 
using static MvvmCross.Droid.Support.V4.MvxCachingFragmentStatePagerAdapter; 

namespace Notifier.Android.Views 
{ 
    [Activity(Label = "HomeNotification", Theme = "@style/Theme.NatuurNetwerk.Main", NoHistory = true)] 
    public class HomeNotificationView : MvxFragmentActivity<HomeNotificationViewModel> 
    { 
     private HomeNotificationViewModel _HomeNotificationViewModel; 

     protected override void OnCreate(Bundle bundle) 
     { 
      base.OnCreate(bundle); 

      _HomeNotificationViewModel = this.ViewModel; 

      SetContentView(Resource.Layout.HomeNotificationView); 

      var fragments = new FragmentInfo[] 
      { 
       new FragmentInfo("Login", typeof(LoginNotificationFragment), typeof(LoginNotificationViewModel)), 
       new FragmentInfo("Tekst", typeof(TextNotificationFragment), typeof(TextNotificationViewModel)), 
      }; 

      var viewPager = FindViewById<ViewPager>(Resource.Id.viewpager); 
      viewPager.Adapter = new TabsFragmentPagerAdapter(this, SupportFragmentManager, fragments); 

      // Give the TabLayout to the ViewPager 
      var tabLayout = FindViewById<TabLayout>(Resource.Id.sliding_tabs); 
      tabLayout.SetupWithViewPager(viewPager, true); 
     } 

     public override bool OnCreateOptionsMenu(IMenu menu) 
     { 
      SetContentView(Resource.Layout.HomeNotificationView); 

      menu.Add(Menu.None, (int)Parameters.NotificationMenuItems.ResetPincode, 0, Resource.String.menuResetPincode); 
      menu.Add(Menu.None, (int)Parameters.NotificationMenuItems.AddApplication, 0, Resource.String.menuAddApplication); 
      menu.Add(Menu.None, (int)Parameters.NotificationMenuItems.RemoveApplication, 0, Resource.String.menuRemoveApplication); 

      return base.OnCreateOptionsMenu(menu); 
     } 

     public override bool OnOptionsItemSelected(IMenuItem item) 
     { 
      Parameters.NotificationMenuItems menuItemSelected = item.ItemId.GetEnum<Parameters.NotificationMenuItems>(); 

      switch (menuItemSelected) 
      { 
       case Parameters.NotificationMenuItems.ResetPincode: 
        _HomeNotificationViewModel.ResetPincode(); 
        break; 
       case Parameters.NotificationMenuItems.AddApplication: 
        break; 
       case Parameters.NotificationMenuItems.RemoveApplication: 
        break; 

       default: 
        throw new InvalidOperationException(string.Format("Notifier: Invalid menu {0}", menuItemSelected.ToString())); 
      } 

      return base.OnOptionsItemSelected(item); 
     } 

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

      Toolbar toolbar = FindViewById(Resource.Id.toolbar) as Toolbar; 

      if (toolbar != null) 
      { 
       toolbar.Title = _HomeNotificationViewModel.Title; 
       toolbar.Subtitle = _HomeNotificationViewModel.SubTitle; 
      } 
     } 
    } 
} 

..和它的視圖模型:

namespace Notifier.ViewModels 
{ 
    public class HomeNotificationViewModel : ViewModelBase 
    { 
     public override string SubTitle => "Notificatie"; 

     public override void InitView() 
     { 
     } 

     public override void InitData() 
     { 
      // TODO: Init Data 
     } 

     public override void ApplicationSelected() 
     { 
     } 

     public void ResetPincode() 
     { 
      DeviceRegistrationHelper.UpdatePincode(null,() => 
      { 
       DetermineAndStartHomeView(); 
      }); 
     } 
    } 
} 

涉及的片段之一:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:local="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 
    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_margin="30dp" 
     local:MvxBind="Text LoginDescription" /> 
    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_margin="30dp" 
     local:MvxBind="Text LastLoginRequestReceivedOn"/> 
</LinearLayout> 

登錄片段代碼:

using Android.OS; 
using Android.Views; 
using Notifier.ViewModels; 

namespace Notifier.Android.Fragments 
{ 
    public class LoginNotificationFragment : BaseFragment<LoginNotificationViewModel> 
    { 
     protected override int LayoutResource => Resource.Layout.LoginNotificationFragment; 

     public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
     { 
      return inflater.Inflate(Resource.Layout.LoginNotificationFragment, container, false); 
     } 
    } 
} 

..和它的基類:

using MvvmCross.Droid.Support.V4; 
using Notifier.Android.Views; 
using Notifier.ViewModels; 

namespace Notifier.Android.Fragments 
{ 
    public abstract class BaseFragment<TViewModel> : MvxFragment<TViewModel> 
     where TViewModel : ViewModelBase 
    { 
     protected abstract int LayoutResource { get; } 
    } 
} 

視圖模型:

using Notifier.Classes; 
using System; 
using System.Linq; 

namespace Notifier.ViewModels 
{ 
    public class LoginNotificationViewModel : ViewModelBase 
    { 
     public override string SubTitle => "Inlog notificatie"; 

     public String Status { get; set; } 

     public override void InitView() 
     { 
     } 

     public override void InitData() 
     { 
      // TODO: Init Data 
     } 

     public override void ApplicationSelected() 
     { 
     } 

     public string LoginDescription 
     { 
      get => Settings.HasNotification 
       ? string.Format("Er is een inlog verzoek ontvangen voor {0}", ApplicationShortName(Settings.Notification.ApplicationId)) 
       : "Geen openstaande inlogverzoeken"; 
     } 

     /// <summary> 
     /// Short name for the application 
     /// </summary> 
     private string ApplicationShortName(int applicationId) 
     { 
      return Applications.Where(app => app.ApplicationID == applicationId).FirstOrDefault()?.ApplicationEntity.ApplicationShortName; 
     } 

     public string LastLoginRequestReceivedOn 
     { 
      get => string.Format("Laatste inlogverzoek: {0}", 
       Settings.HasLastNotificationReceivedOn 
       ? string.Empty 
       : Settings.LastNotificationReceivedOn.ToString("DD-MM-YYYY HH:MM")); 
     } 
    } 
} 

和(部分)的基類:

namespace Notifier.ViewModels 
{ 
    /// <summary> 
    /// Base class for all view models. 
    /// </summary> 
    public abstract class ViewModelBase : MvxViewModel 
    { 
     private readonly IPlatformEntrance _platformEntrance; 
     private readonly IPlatformLog _platformLog; 

     public string Title => "nNotifier©"; 

     public ViewModelBase() 
     { 
      _platformEntrance = Mvx.Resolve<IPlatformEntrance>(); 
      _platformLog = Mvx.Resolve<IPlatformLog>(); 

      InitData(); 
     } 

     public abstract void InitData(); 

     public abstract string SubTitle { get; } 

     ... 
    } 
} 

這裏的PageAdapter:

using Android.Content; 
using Android.Support.V4.App; 
using MvvmCross.Droid.Support.V4; 

namespace Notifier.Adapters 

{ 
    public class TabsFragmentPagerAdapter : MvxCachingFragmentStatePagerAdapter 
    { 
     FragmentInfo[] _fragments; 

     public TabsFragmentPagerAdapter(Context context, FragmentManager fragmentManager, FragmentInfo[] fragments) 
      : base(context, fragmentManager, fragments) 
     { 
      _fragments = fragments; 
     } 

     // public override int Count => _fragments.Length; 

     //public override global::Android.Support.V4.App.Fragment GetItem(int position, 
     // global::Android.Support.V4.App.Fragment.SavedState fragmentSavedState = null) 
     //{ 
     // return _fragments[position]; 
     //} 

     //public override ICharSequence GetPageTitleFormatted(int position) 
     //{ 
     // return _titles[position]; 
     //} 
    } 
} 

回答

0

您需要使用BindingInflate(),而不是默認的Android吹氣,因爲它不知道如何處理MvxBind性能。

using MvvmCross.Binding.Droid.BindingContext; 

... 

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
{ 
    var ignored = base.OnCreateView(inflater, container, savedInstanceState); 

    var view = this.BindingInflate(Resource.Layout.MyFragmentLayout, container, false); 

    return view; 
} 
+0

啊,我以前在某個地方看過這個評論。我沒有在這個想法中找到它,並且從未意識到它是een擴展方法。 當我添加片段時,我得到一個NullReferenceException –

+0

看來我也需要base.OnCreateView,因爲它現在起作用了。非常感謝你 –