mvvmcross导航问题,得到异常:无法找到[ViewModelName]的视图

本文关键字:ViewModelName 视图 问题 导航 mvvmcross 异常 | 更新日期: 2023-09-27 17:50:47

我似乎很困惑,如何使MvvmCross检测我的ViewModels是与视图在Mono Android。我试着按照TwitterSearch来实现导航,但它就是不起作用。

RequestNavigate<LoginViewModel>();

这是我的观点:

[Activity(Label = "Login")]
public class LoginActivity : MvxBindingActivityView<LoginViewModel>
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        App.InitializeRestConnection(this);
    }
    protected override void OnViewModelSet()
    {
        SetContentView(Resource.Layout.LoginBindable);
    }
}

这里有一个例外:

I/ActivityManager(  307): Displayed com.desco.pendulum/pendulum.androidapp.SplashScreenActivity: +1s373ms (total +4s420ms)
I/Navigation( 8643):   0.50 Navigate to LoginViewModel with args
I/mono-stdout( 8643): Navigation:Diagnostic:  0.50 Navigate to LoginViewModel with args
I/MonoDroid( 8643): UNHANDLED EXCEPTION: System.Collections.Generic.KeyNotFoundException: Could not find view for dESCO.Mobile.ViewModels.LoginViewModel
I/MonoDroid( 8643): at Cirrious.MvvmCross.Views.MvxViewsContainer.GetViewType (System.Type) <0x001a4>
I/MonoDroid( 8643): at Cirrious.MvvmCross.Droid.Views.MvxAndroidViewsContainer.GetIntentFor (Cirrious.MvvmCross.Views.MvxShowViewModelRequest) <0x00023>
I/MonoDroid( 8643): at Cirrious.MvvmCross.Droid.Views.MvxAndroidViewPresenter.Show (Cirrious.MvvmCross.Views.MvxShowViewModelRequest) <0x00037>
I/MonoDroid( 8643): at Cirrious.MvvmCross.Droid.Views.MvxAndroidViewDispatcher/<>c__DisplayClass1.<RequestNavigate>b__0 () <0x0002f>
I/MonoDroid( 8643): at Java.Lang.Thread/RunnableImplementor.Run () <0x0003f>
I/MonoDroid( 8643): at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) <0x00037>
I/MonoDroid( 8643): at (wrapper dynamic-method) object.7060b187-418d-4bca-ad4f-8b9cae936501 (intptr,intptr) <0x0003b>

有什么建议吗?

mvvmcross导航问题,得到异常:无法找到[ViewModelName]的视图

我看不出你的设置有什么明显的问题。

默认的Droid框架设置查找在ExecutingAssembly中使用以下逻辑实现IMvxAndroidView的类:https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/Platform/MvxBaseSetup.cs#L200

所以我看不出任何明显的原因为什么你的LoginActivity视图没有被捡起来。

你可以做的一件事是在Setup.cs中添加一些调试代码,以查看正在检测的视图:

  protected override IDictionary<Type, Type> GetViewModelViewLookup()
  {
      var toReturn = base.GetViewModelViewLookup();
      MvxTrace.Trace("Tracing viewModels and views");
      foreach (var kvp in toReturn)
      {
          MvxTrace.Trace("Seen pair {0} : {1}", kvp.Key.Name, kvp.Value.Name);
      }
      return toReturn;
  }

如果这显示列表是空的或缺少你的活动,那么恐怕我们需要通过反射逻辑来找出为什么它不拾取你的活动。


在真正绝望的时候,你也可以伪造结果:

  protected override IDictionary<Type, Type> GetViewModelViewLookup()
  {
      return new Dictionary<Type,Type>() { { typeof(LoginViewModel), typeof(LoginActivity) } };
  }

但这可能不是你的长期解决方案


如果这是由某种"解决方案设置"的差异引起的——例如,如果你把你的setup .cs放在不同的项目中,那么可能以某种方式重写默认约定会帮助你。

要实现这一点,在Setup.cs中,重写代码:
    public virtual Assembly ExecutableAssembly
    {
        get { return GetType().Assembly; }
    }
    protected override IDictionary<System.Type, System.Type> GetViewModelViewLookup()
    {
        return GetViewModelViewLookup(ExecutableAssembly, typeof (IMvxAndroidView));
    }

中的基本设置类- https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Droid/Platform/MvxBaseAndroidSetup.cs

这可以通过重写ExecutingAssembly属性(尽管给定它的名称似乎有点错误)或重写GetViewModelViewLookup方法来完成。例如,如果您想查看几个单独的程序集,您可以使用:

    public List<Assembly> MyViewAssemblies { get; set; }
    protected override IDictionary<System.Type, System.Type> GetViewModelViewLookup()
    {
        var toReturn = new Dictionary<Type, Type>();
        foreach (var assembly in MyViewAssemblies)
        {
            var contributions = base.GetViewModelViewLookup(assembly, typeof (IMvxAndroidView));
            foreach (var kvp in contributions)
            {
                toReturn[kvp.Key] = kvp.Value; 
            }
        }
        return toReturn;
    }