我的Android应用程序中有以下代码,它基本上使用一个页面(使用NavigationDrawer)并将片段交换到中心视图中。这允许导航在一页而不是多页上进行:
Setup.cs:
$('#submit_btn').on('click', function(event) {
event.preventDefault();
var str = $('#code').val();
var acode = str.substr(6);
// change form action attribute and submit the form:
$(this).closest('form').attr('action', location.href + "?ref=" + acode).submit();
});
ShellPage.cs
protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var customPresenter = new MvxFragmentsPresenter();
Mvx.RegisterSingleton<IMvxFragmentsPresenter>(customPresenter);
return customPresenter;
}
如何在Windows UWP应用中实现相同的行为?或者更确切地说,是否存在实现CustomPresenter的Windows MvvmCross应用程序的任何示例?这至少可以让我了解如何实现它。
谢谢!
更新
我终于开始弄清楚如何与客户主持人讨论这个问题:
public class ShellPage : MvxCachingFragmentCompatActivity<ShellPageViewModel>, IMvxFragmentHost
{
.
.
.
public bool Show(MvxViewModelRequest request, Bundle bundle)
{
if (request.ViewModelType == typeof(MenuContentViewModel))
{
ShowFragment(request.ViewModelType.Name, Resource.Id.navigation_frame, bundle);
return true;
}
else
{
ShowFragment(request.ViewModelType.Name, Resource.Id.content_frame, bundle, true);
return true;
}
}
public bool Close(IMvxViewModel viewModel)
{
CloseFragment(viewModel.GetType().Name, Resource.Id.content_frame);
return true;
}
.
.
.
}
当我尝试导航到ShellPage时,它失败了。因此,当我将内容设置为ShellPage时,它可以工作,但是当我这样做时,ShellPage的ViewModel不会自动初始化。我猜测使用OnNavigatedTo在MvvmCross中初始化ViewModel ???
答案 0 :(得分:7)
我遇到了同样的问题,并为UWP构建了一个自定义演示者。它从我在某个地方发现的Android样本中提供了一些想法,它使用了片段。这个想法如下。
我有一个容器视图,它可以包含多个具有自己的ViewModel的子视图。所以我希望能够在容器中呈现多个视图。
注意: 我正在使用MvvmCross 4.0.0-beta3
<强>演示强>
using System;
using Cirrious.CrossCore;
using Cirrious.CrossCore.Exceptions;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.Views;
using Cirrious.MvvmCross.WindowsUWP.Views;
using xxxxx.WinUniversal.Extensions;
namespace xxxxx.WinUniversal.Presenters
{
public class MvxWindowsMultiRegionViewPresenter
: MvxWindowsViewPresenter
{
private readonly IMvxWindowsFrame _rootFrame;
public MvxWindowsMultiRegionViewPresenter(IMvxWindowsFrame rootFrame)
: base(rootFrame)
{
_rootFrame = rootFrame;
}
public override async void Show(MvxViewModelRequest request)
{
var host = _rootFrame.Content as IMvxMultiRegionHost;
var view = CreateView(request);
if (host != null && view.HasRegionAttribute())
{
host.Show(view as MvxWindowsPage);
}
else
{
base.Show(request);
}
}
private static IMvxWindowsView CreateView(MvxViewModelRequest request)
{
var viewFinder = Mvx.Resolve<IMvxViewsContainer>();
var viewType = viewFinder.GetViewType(request.ViewModelType);
if (viewType == null)
throw new MvxException("View Type not found for " + request.ViewModelType);
// Create instance of view
var viewObject = Activator.CreateInstance(viewType);
if (viewObject == null)
throw new MvxException("View not loaded for " + viewType);
var view = viewObject as IMvxWindowsView;
if (view == null)
throw new MvxException("Loaded View is not a IMvxWindowsView " + viewType);
view.ViewModel = LoadViewModel(request);
return view;
}
private static IMvxViewModel LoadViewModel(MvxViewModelRequest request)
{
// Load the viewModel
var viewModelLoader = Mvx.Resolve<IMvxViewModelLoader>();
return viewModelLoader.LoadViewModel(request, null);
}
}
}
<强> IMvxMultiRegionHost 强>
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.WindowsUWP.Views;
namespace xxxxx.WinUniversal.Presenters
{
public interface IMvxMultiRegionHost
{
void Show(MvxWindowsPage view);
void CloseViewModel(IMvxViewModel viewModel);
void CloseAll();
}
}
<强> RegionAttribute 强>
using System;
namespace xxxxx.WinUniversal.Presenters
{
[AttributeUsage(AttributeTargets.Class)]
public sealed class RegionAttribute
: Attribute
{
public RegionAttribute(string regionName)
{
Name = regionName;
}
public string Name { get; private set; }
}
}
这些是您需要的三个基础课程。接下来,您需要在IMvxMultiRegionHost
派生类中实现MvxWindowsPage
。
这是我正在使用的那个:
<强> HomeView.xaml.cs 强>
using System;
using System.Diagnostics;
using System.Linq;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.MvvmCross.WindowsUWP.Views;
using xxxxx.Shared.Controls;
using xxxxx.WinUniversal.Extensions;
using xxxxx.WinUniversal.Presenters;
using xxxxx.Core.ViewModels;
namespace xxxxx.WinUniversal.Views
{
public partial class HomeView
: MvxWindowsPage
, IMvxMultiRegionHost
{
public HomeView()
{
InitializeComponent();
}
// ...
public void Show(MvxWindowsPage view)
{
if (!view.HasRegionAttribute())
throw new InvalidOperationException(
"View was expected to have a RegionAttribute, but none was specified.");
var regionName = view.GetRegionName();
RootSplitView.Content = view;
}
public void CloseViewModel(IMvxViewModel viewModel)
{
throw new NotImplementedException();
}
public void CloseAll()
{
throw new NotImplementedException();
}
}
}
使这项工作的最后一件事是设置视图中的实际xaml的方式。您会注意到我正在使用SplitView
控件,并且我正在使用ShowView
类HomeView
方法中的新视图替换Content属性。
<强> HomeView.xaml 强>
<SplitView x:Name="RootSplitView"
DisplayMode="CompactInline"
IsPaneOpen="false"
CompactPaneLength="48"
OpenPaneLength="200">
<SplitView.Pane>
// Some ListView with menu items.
</SplitView.Pane>
<SplitView.Content>
// Initial content..
</SplitView.Content>
</SplitView>
修改强>
扩展方法
我忘了发布两个扩展方法来确定视图是否声明了[Region]
属性。
public static class RegionAttributeExtentionMethods
{
public static bool HasRegionAttribute(this IMvxWindowsView view)
{
var attributes = view
.GetType()
.GetCustomAttributes(typeof(RegionAttribute), true);
return attributes.Any();
}
public static string GetRegionName(this IMvxWindowsView view)
{
var attributes = view
.GetType()
.GetCustomAttributes(typeof(RegionAttribute), true);
if (!attributes.Any())
throw new InvalidOperationException("The IMvxView has no region attribute.");
return ((RegionAttribute)attributes.First()).Name;
}
}
希望这有帮助。
答案 1 :(得分:1)
由于@Stephanvs的博客链接已不再有效,我可以将内容从Web存档中删除,我会在此处发布,以便有人找到它:
为Windows 10 UWP和MvvmCross实现多区域Presenter 2015年10月18日,MvvmCross,Xamarin,UWP,Windows 10,Presenter 通用Windows平台
我将Windows应用商店应用升级到新的Windows 10通用Windows平台。 MvvmCross在v4.0-beta2中增加了对UWP的支持。
UWP中的新控件是SplitView控件。基本上它起到容器视图的作用,它由两个子视图组成,并排显示。它主要用于实现着名的汉堡包菜单。
默认情况下,MvvmCross不知道如何处理SplitView,只是在ViewModels之间导航时用新视图替换整个屏幕内容。但是,如果我们想要以不同方式布置视图并在一个窗口中显示多个视图,我们需要一个不同的解决方案。幸运的是,我们可以插入一个自定义演示器,它将负责处理每个平台的布局。 注册MultiRegionPresenter
在UWP项目的Setup.cs文件中,您可以使用以下实现覆盖CreateViewPresenter方法。
`protected override IMvxWindowsViewPresenter CreateViewPresenter(IMvxWindowsFrame rootFrame)
{
return new MvxWindowsMultiRegionViewPresenter(rootFrame);
}`
使用区域
我们可以通过声明一个元素来定义一个区域。此时它必须是Frame类型,因为我们还可以在切换视图时显示一个漂亮的过渡动画。
`<mvx:MvxWindowsPage ...>
<Grid>
<!-- ... -->
<SplitView>
<SplitView.Pane>
<!-- Menu Content as ListView or something similar -->
</SplitView.Pane>
<SplitView.Content>
<Frame x:Name="MainContent" />
</SplitView.Content>
</SplitView>
</Grid>
</mvx:MvxWindowsPage> `
现在我们希望能够在ShowViewModel(...)出现时换出MainContent框架中显示的当前视图。 在区域中显示视图
在View的代码隐藏中,我们现在可以声明一个MvxRegionAttribute,定义我们希望在哪个区域呈现此View。此名称必须与视图中的Frame元素匹配。
`[MvxRegion("MainContent")]
public partial class PersonView
{
// ...
}`
也可以在同一视图中声明多个区域。这将允许您将UI拆分为更多可重用的部分。 动画内容视图之间的过渡
如果想要在Frame中的视图之间进行转换时想要一个漂亮的动画,可以将以下代码段添加到Frame声明中。
`<Frame x:Name="MainContent">
<Frame.ContentTransitions>
<TransitionCollection>
<NavigationThemeTransition>
<NavigationThemeTransition.DefaultNavigationTransitionInfo>
<EntranceNavigationTransitionInfo />
</NavigationThemeTransition.DefaultNavigationTransitionInfo>
</NavigationThemeTransition>
</TransitionCollection>
</Frame.ContentTransitions>
</Frame>`
导航时,内容现在可以很好地动画。
希望这有帮助, Stephanvs