MVVMCross从嵌套视图控制器中更改选定的选项卡栏项

时间:2014-03-13 13:16:44

标签: xamarin.ios mvvmcross

我们在我们的应用程序中使用MVVMCross,并且我遇到了一些我不确定我是否已经以最佳方式解决的问题。

我们的ViewModel之一包含3个其他视图模型 - 仪表板和2个列表。在iOS中,这是使用MvxTabBarViewController呈现的,它非常有效。 Android和WP以类似的方式呈现此视图。对象模型的一个例子如下:

public class ProjectViewModel : MvxViewModel
{
    public DashboardViewModel Dashboard {get;set;}
    public FirstListViewModel FirstList {get;set;}
    public SecondListViewModel SecondList {get;set;}
}

我们现在处于这样的情况:如果在DashboardViewModel中发生某个动作,我们想指示导航改变iOS中的选项卡,并在其他平台上发生同样的事情。

我能够在iOS上更改标签的唯一方法是使用this.SelectedIndex = 1;来自iOS ProjectView。

此刻,我设法触发此更改的唯一方法是从DashboardViewModel触发事件,然后ProjectViewModel订阅此事件并触发另一个由ProjectView订阅的事件,以指示它以任何特定于设备的方式更改选项卡。我无能为力,但认为有更好的方法可以做到这一点。

我试过看看自定义ViewPresenter for iOS并从DashboardViewModel中调用ShowViewModel FirstListViewModel,但是演示者似乎没有被使用,所以我们只是正常转换。我的想法是我可以进入中间,取消导航请求,然后翻转ProjectView上的活动标签。

如果我们能够以更好的跨平台方式使用MVVMCross来处理变更,那么任何建议都会受到赞赏。

1 个答案:

答案 0 :(得分:2)

您应该可以通过以下几种方式执行此操作:

  • 使用自定义的演示者,如您所建议的那样覆盖Show
  • 使用具有重写的ChangePresentation的自定义演示者 - 并使用自定义提示
  • 使用自定义绑定或绑定到ProjectView中的属性来驱动转换
  • 使用自定义IMvxInteraction属性
  • 使用VM中的自定义事件查看
  • 使用信使从ViewModels向视图发送消息。

最终,很多这些都可行,我可能会选择哪一个取决于哪一个有效,哪个团队满意 - 运送应用程序始终是最终目标。


鉴于我在MvvmCross的经历,我今天可能会选择尝试尝试自定义IMvxInteraction属性的方法。但这可能不适合所有人......对于这个样本来说肯定可能矫枉过正 ......

然而,要做到这一点,我会尝试:

  • public enum Display { Dash, First, Second }添加到Core项目
  • 添加ProjectViewModel属性:

    private MvxInteraction<Display> _display = new MvxInteraction< Display >();
    public IMvxInteraction<Display> DisplayChange { get { return _display; } }
    
  • 每当此ViewModel想要触发更改时,它都可以使用例如_display.Raise(Display.First)

  • ProjectView然后可以将Display绑定到自己的属性,该属性可以实现为:

    private IDisposable _subscription;
    private IMvxInteraction<Display> _displayInteraction;
    public IMvxInteraction<Display> ChangeDisplay
    {
        get { return _displayInteraction; }
        set
        {
            if (_subscription != null)
            {
                _subscription.Dispose();
                _subscription = null;
            }
            _displayInteraction = value;
            if (_displayInteraction != null)
            {
                _subscription = _displayInteraction.WeakSubscribe(DoDisplayChange);
            }
        }
    }
    
    private void DoDisplayChange(Display which)
    {
       // change the tab display here
    }
    
  • 绑定将添加到ViewDidLoad中,如:

    set.Bind(this).For(v => v.ChangeDisplay).To(vm => vm.DisplayChange);