3

我似乎对如何让 MvvmCross 检测与 Mono for Android 中的视图相关联的 ViewModel 感到困惑。我试图按照 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>

有什么建议么?

4

1 回答 1

6

我看不出您的设置有任何明显错误。

默认的 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;
    }
于 2013-01-03T21:55:36.760 回答