gpt4 book ai didi

xamarin - 如何在 Windows UWP 中实现自定义演示器(Xamarin、MvvmCross)

转载 作者:行者123 更新时间:2023-12-02 21:24:28 24 4
gpt4 key购买 nike

我的 Android 应用程序中有以下代码,它基本上使用一个页面(使用 NavigationDrawer)并将片段交换进/出中央 View 。这允许导航发生在一页而不是多页上:

安装.cs:

    protected override IMvxAndroidViewPresenter CreateViewPresenter()
{
var customPresenter = new MvxFragmentsPresenter();
Mvx.RegisterSingleton<IMvxFragmentsPresenter>(customPresenter);
return customPresenter;
}

ShellPage.cs

    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;
}

.
.
.
}

如何在 Windows UWP 应用中实现相同的行为?或者更确切地说,是否存在实现 CustomPresenter 的 Windows MvvmCross 应用程序的任何示例?这至少可以让我开始了解如何实现它。

谢谢!

更新:

我终于开始弄清楚如何与客户演示者一起解决这个问题:

    public class CustomPresenter : IMvxWindowsViewPresenter
{
IMvxWindowsFrame _rootFrame;

public CustomPresenter(IMvxWindowsFrame rootFrame)
{
_rootFrame = rootFrame;
}

public void AddPresentationHintHandler<THint>(Func<THint, bool> action) where THint : MvxPresentationHint
{
throw new NotImplementedException();
}

public void ChangePresentation(MvxPresentationHint hint)
{
throw new NotImplementedException();
}

public void Show(MvxViewModelRequest request)
{
if (request.ViewModelType == typeof(ShellPageViewModel))
{
//_rootFrame?.Navigate(typeof(ShellPage), null); // throws an exception

((Frame)_rootFrame.UnderlyingControl).Content = new ShellPage();
}
}
}

当我尝试导航到 ShellPage 时,它​​失败了。因此,当我将 Content 设置为 ShellPage 时,它​​可以工作,但是当我这样做时,ShellPage 的 ViewModel 不会自动初始化。我猜测 ViewModels 是使用 OnNavigedTo 在 MvvmCross 中初始化的???

最佳答案

我遇到了同样的问题,并为 UWP 构建了一个自定义演示器。它借鉴了我在某处找到的 Android 示例中的一些想法,该示例使用片段。思路如下。

我有一个容器 View ,它可以包含多个具有自己的 ViewModel 的 subview 。所以我希望能够在容器内呈现多个 View 。

注意:我使用的是 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();
}
}

区域属性

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; }
}
}

这些是您需要的三个基础类(class)。接下来您需要实现 IMvxMultiRegionHostMvxWindowsPage派生类。

这是我正在使用的:

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();
}
}
}

完成这项工作的最后一部分是 View 中实际 xaml 的设置方式。您会注意到我正在使用 SplitView控件,并且我将使用 ShowView 中出现的新 View 替换 Content 属性。 HomeView上的方法类。

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>
<小时/>

编辑:

扩展方法

我忘记发布两个扩展方法来确定 View 是否声明 [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;
}
}

希望这有帮助。

关于xamarin - 如何在 Windows UWP 中实现自定义演示器(Xamarin、MvvmCross),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33131034/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com