片段视图的选择取决于所选项目ViewModel类型

时间:2013-06-03 15:26:38

标签: android android-fragments xamarin.android xamarin mvvmcross

目标MvvmCross,Android

目标:用户可以选择动物组(两栖动物,鸟类,鱼类,无脊椎动物,哺乳动物,爬行动物)的屏幕(ViewModel / View)。选择组后,片段视图将显示该动物组的信息。每个动物群的田地和布局不同(例如鱼没有翅膀)。 虽然对于这个问题,我选择了动物组(这是非常静态的),但希望列表动物组灵活。

简化的应用结构:

  • MyApp.Core
    • 的ViewModels
    • MainViewModel
    • IAnimalGroupViewModel
    • AmphibiansViewModel
    • BirdsBViewModel
    • FishViewModel
  • MyApp.Droid
    • 布局
      • 的MainView
      • AmphibiansFragment
      • BirdsFragment
      • FishFragment
      • 的MainView
      • AmphibiansFragment
      • BirdsFragment
      • FishFragment

MainView.axml布局文件将包含(占位符)显示的动物组的片段。

在WPF或WP8应用程序中,我可以使用ContentPresenter和Style来自动显示所选ViewModel及其View。

我怎么能在Droid中实现类似的东西?

我可以在MainView.cs中使用Switch / Case,根据所选ViewGroup的类型设置Fragment。但这意味着每次添加新视图时都必须修改MainView。

有任何建议/想法吗?

1 个答案:

答案 0 :(得分:1)

目前,MvvmCross没有为Fragments提供任何类型的自动导航机制。

但是,在您的用例中,如果您想使用导航方法,那么您可以自动构建类似类型的自动查找/导航机制。

要做到这一点,最简单的开发人员root可能是使用反射来查找所有片段的查找字典

 var fragments = from type in this.GetType().Assembly.GetTypes()
                 where typeof(IAnimalGroupView)..sAssignableFrom(type)
                 where type.Name.EndsWith("Fragment")
                 select type;
 var lookup = fragments.ToDictionary(
                  x => x.Name.Substring(0, x.Name.Length - "Fragment".Length) 
                              + "ViewModel",
                  x => x);

有了这个,你可以在需要时创建片段 - 例如

  • 假设您通过ViewModel上的ICommand将Selection事件转换为ShowViewModel<TViewModel>调用
  • 并假设您有一个自定义Mvx演示者,它拦截这些ShowViewModel请求并将它们传递给活动(类似于Fragment sample) - 例如。

    public class CustomPresenter
        : MvxAndroidViewPresenter
    {
        // how this gets set/cleared is up to you - possibly from `OnResume`/`OnPause` calls within your activities.
        public IAnimalHostActivity AnimalHost { get; set; }
    
        public override void Show(MvxViewModelRequest request)
        {
            if (AnimalHost != null && AnimalHost.Show(request))
                 return;
    
            base.Show(request);
        }
    }
    
  • 然后您的活动可以使用以下内容实现Show

    if (!lookup.ContainsKey(request.ViewModelType.Name))
         return false;
    
    var fragmentType = lookup[request.ViewModelType.Name];
    var fragment = (IMvxFragmentView)Activator.Create(fragmentType);
    fragment.LoadViewModelFrom(request);
    
    var t = SupportFragmentManager.BeginTransaction();
    t.Replace(Resource.Id.my_selected_fragment_holder, fragment);
    t.Commit();
    return true;
    

注意:

  • 如果你没有在这里使用ShowViewModel那么显然可以调整同样的方法......但这个答案必须提出一些建议......
  • 在一个更大的多页面应用中,您可能希望使这个IAnimalHostActivity机制更通用,并在多个地方使用它。