1

目标 MvvmCross,Android

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

简化的应用程序结构:

  • MyApp.Core
    • 视图模型
    • 主视图模型
    • IAnimalGroupViewModel
    • 两栖动物ViewModel
    • BirdsBViewModel
    • 鱼视图模型
  • MyApp.Droid
    • 布局
      • 主视图
      • 两栖动物片段
      • 鸟片段
      • 鱼片
    • 意见
      • 主视图
      • 两栖动物片段
      • 鸟片段
      • 鱼片

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

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

我怎么能在 Droid 中实现这样的目标?

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

有什么建议/想法吗?

4

1 回答 1

1

目前,MvvmCross 没有像为活动提供任何类型的自动导航机制一样为 Fragment 提供自动导航机制。

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

为此,最简单的开发者根可能是使用反射来查找所有片段的查找字典

 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 请求并将它们传递给活动(类似于片段示例) - 例如

    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机制更加通用并在多个地方使用它。
于 2013-06-03T16:10:48.877 回答