在我最近的一篇文章之后,我建议使用A PRESENTER

时间:2014-03-05 20:59:51

标签: wpf mvvm mvvmcross

在我大约一周前发布的一个问题WPF application using MVVMCROSS之后,我开始阅读主持人的工作原理。有很多关于如何使用移动应用程序执行某些操作的文档和视频,尤其是IOS,但对于DESKTOP Windows WPF应用程序来说却不是很多。根据N = 24视频,我创建了一个演示者,我从MvxSimpleWpfViewPresenter派生出来并继续覆盖 函数Present(System.Windows.FrameworkElement frameworkElement),主窗口将显示我的主视图和我将调用的所有其他视图,将在我的主视图下显示其内容:

  public class MyPresenter : Cirrious.MvvmCross.Wpf.Views.MvxSimpleWpfViewPresenter
  {
    private Window _mainWindow = null;
    private MvxWpfView _firstView = null;

    public MyPresenter(Window mainWindow)
      : base(mainWindow)
    {
      _mainWindow = mainWindow;
    }

    public override void Present(System.Windows.FrameworkElement frameworkElement)
    {
      //_mainWindow.DisplayGrid

      if(_firstView == null &&
         frameworkElement is FirstView)
      {
        _firstView = frameworkElement as FirstView;
        _mainWindow.Content = _firstView;
      }
      else if(_firstView != null)
      {
        if ((_firstView as FirstView).DisplayGrid.Children.Count > 0)
        {
          (_firstView as FirstView).DisplayGrid.Children.RemoveAt(0);
        }

        (_firstView as FirstView).DisplayGrid.Children.Add(frameworkElement);
      }
    }

我的主视图(称为FirstViewModel)如下所示:

  public class FirstViewModel : MvxViewModel
  {
    public ICommand BlueCommand
    {
      get { return new MvxCommand(() => ShowViewModel<BlueViewModel>()); }
    }

    public ICommand RedCommand
    {
      get { return new MvxCommand(() => ShowViewModel<RedViewModel>()); }
    }
  }

我的FirstView看起来像这样(在Xaml中):

    <views:MvxWpfView 
             x:Class="WpfApplication1.Views.FirstView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:views="clr-namespace:Cirrious.MvvmCross.Wpf.Views;assembly=Cirrious.MvvmCross.Wpf"
             mc:Ignorable="d" Height="Auto" Width="Auto">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Menu Grid.Row="0">
      <MenuItem Name="RedCommandMenuItem" Header="Red command" Command="{Binding Path=RedCommand}" />
      <MenuItem Name="BlueCommandMenuItem" Header="Blue command" Command="{Binding Path=BlueCommand}" />
    </Menu>
    <Grid Name="DisplayGrid" Grid.Row="1">
    </Grid>
  </Grid>
</views:MvxWpfView>

之后,我让我的演示者使用的是一个而不是默认的,并且能够显示红色背景的视图和我的主视图中包含MENUS的蓝色背景的视图。所以这基本上与我想做的事情非常吻合。

那么我要去哪里?我想知道的是,这与我见过的所有其他示例非常不同,我会看到使用演示者的SHOW METHOD,你需要一个Model,你需要使用Mvx.Resolve来创建视图.. Show方法是不能用MvxSimpleWpfViewPresenter和MvxSimpleWpfViewPresenter类重写。通过调用这些命令,ShowViewModel调用Presenter(我推测)来显示我的新视图,但是当我得到FrameworkElement时,我不需要在这里调用Resolve。那么解决方法在哪里完成以及由谁完成?我试图理解背后的机制,以便在我遇到问题时更好地调试这个。并且是否有与前一篇文章中提到的CONTAINER的链接?

由于

1 个答案:

答案 0 :(得分:0)

  

那么决心在哪里以及由谁完成?

这是在基地MvxWpfViewPresenter

中完成的
public abstract class MvxWpfViewPresenter
    : IMvxWpfViewPresenter
{
    public void Show(MvxViewModelRequest request)
    {
        try
        {
            var loader = Mvx.Resolve<IMvxSimpleWpfViewLoader>();
            var view = loader.CreateView(request);
            Present(view);
        }
        catch (Exception exception)
        {
            MvxTrace.Error("Error seen during navigation request to {0} - error {1}", request.ViewModelType.Name,
                           exception.ToLongString());
        }
    }

    public abstract void Present(FrameworkElement frameworkElement);

    public virtual void ChangePresentation(MvxPresentationHint hint)
    {
        MvxTrace.Warning("Hint ignored {0}", hint.GetType().Name);
    }
}

https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Wpf/Views/MvxWpfViewPresenter.cs

Show在本课程中应该是virtual - 但这是一个非常简单的类,我一直希望WPF用户只编写自己的IMvxWpfViewPresenter版本

  

上一篇文章中提到的CONTAINER是否有任何链接?

WPF的默认容器是:

public class MvxWpfViewsContainer
    : MvxViewsContainer
    , IMvxWpfViewsContainer
{
    public FrameworkElement CreateView(MvxViewModelRequest request)
    {
        var viewType = GetViewType(request.ViewModelType);
        if (viewType == null)
            throw new MvxException("View Type not found for " + request.ViewModelType);

        // , request
        var viewObject = Activator.CreateInstance(viewType);
        if (viewObject == null)
            throw new MvxException("View not loaded for " + viewType);

        var wpfView = viewObject as IMvxWpfView;
        if (wpfView == null)
            throw new MvxException("Loaded View does not have IMvxWpfView interface " + viewType);

        var viewControl = viewObject as FrameworkElement;
        if (viewControl == null)
            throw new MvxException("Loaded View is not a FrameworkElement " + viewType);

        var viewModelLoader = Mvx.Resolve<IMvxViewModelLoader>();
        wpfView.ViewModel = viewModelLoader.LoadViewModel(request, null);

        return viewControl;
    }
}

来自https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Wpf/Views/MvxWpfViewsContainer.cs

它继承自https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross/Views/MvxViewsContainer.cs - 在所有平台上共享。

在安装过程中,使用反射向容器填充了查看Type - 请参阅https://github.com/MvvmCross/MvvmCross/wiki/Customising-using-App-and-Setup#wiki-overriding-view-viewmodel-associations中的InitalizeViewLookup信息