TabLayout中的片段不会绑定到viewmodel [英] Fragments in TabLayout do not bind to viewmodel

查看:68
本文介绍了TabLayout中的片段不会绑定到viewmodel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经为此苦苦挣扎了2天了,很容易陷入困境.出于某些原因,片段的绑定根本无法启动.该页面正确显示,并且选项卡可以正常工作.我可以从选项卡1滑动到2,反之亦然. TextView应该显示视图模型中的一些文本.当我调试两个片段视图模型的构造函数时,都将执行,但是LoginNotificationViewModel的属性(LoginDescription和LastLoginRequestReceivedOn)永远不会触发.

I've been struggling with this for 2 days now and am quite simply stuck. The binding of the fragments simply will not kick in for some reason. The page is shown correctly and the tabs do work fine. I can swipe from tab 1 to 2 and vice versa. The TextView should show some text from the viewmodel. When I debug the constructors of both fragment viewmodels are executed but the properties on the LoginNotificationViewModel (LoginDescription and LastLoginRequestReceivedOn) never fire.

我有一个包含TabLayout的视图,如下所示:

I've got a view that holds a TabLayout as you can see below:

<?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的代码:

The tabview's code:

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;
            }
        }
    }
}

..它是viewmodel:

.. and it's viewmodel:

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:

Here's the 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];
        //}
    }
}

推荐答案

您需要使用BindingInflate()代替默认的Android充气器,因为它不知道如何处理 MvxBind 属性.

You need to use BindingInflate()instead of the default Android inflater since it doesn't know how to process the MvxBind properties.

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;
}

这篇关于TabLayout中的片段不会绑定到viewmodel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆