加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

如何在Windows UWP中实现自定义演示者(Xamarin,MvvmCross)

发布时间:2020-12-14 02:06:09 所属栏目:Windows 来源:网络整理
导读:我的 Android应用程序中有以下代码,它基本上使用一个页面(使用NavigationDrawer)并将片段交换到中心视图中.这允许导航在一个页面而不是许多页面上进行: Setup.cs: protected override IMvxAndroidViewPresenter CreateViewPresenter() { var customPresent
我的 Android应用程序中有以下代码,它基本上使用一个页面(使用NavigationDrawer)并将片段交换到中心视图中.这允许导航在一个页面而不是许多页面上进行:

Setup.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时,它失败了.因此,当我将内容设置为ShellPage时,它可以工作,但是当我这样做时,ShellPage的ViewModel不会自动初始化.我猜想使用OnNavigatedTo在MvvmCross中初始化ViewModel ???

解决方法

我遇到了同样的问题,并为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; }
    }
}

这些是您需要的三个基础课程.接下来,您需要在MvxWindowsPage派生类中实现IMvxMultiRegionHost.

这是我正在使用的那个:

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控件,并且我正在使用HomeView类中的ShowView方法中的新View替换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;
    }
}

希望这可以帮助.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读