xamarin.forms 导航封装

 

xamarin.forms导航的实现,MS提供了多种方法(参考链接), 再此不赘述。

说一下导航封装,以便于在anywhere都能使用。

 

面向接口编程单一职责原则,将导航拆分为页面的跳转(navigation)与页面的激活(Active)两个接口并实现。

 

导航服务interface

    public interface IContentNavigationService
    {
        /// <summary>
        /// 导致到page
        /// </summary>
        /// <param name="StrPagekey">页面键</param>
        /// <returns></returns>
        /// 基于页面名字进行导航,摆脱页面类型
        Task NavigationToAsync(Type type);
        Task NavigationToAsync(string StrPagekey,TabbedPage tabbedPage,Page[] pages, string strTitle);
    }

 

导航服务实现

class ContentNavigationService : IContentNavigationService
    {
        /// <summary>
        /// 导航到页面type
        /// </summary>
        /// <param name="type">页面type</param>
        /// <returns></returns>
        public async Task NavigationToAsync(Type type)
        {
            //throw new NotImplementedException();
            await MainPage.Navigation.PushAsync(_contentPageActivationService.Activate(type));
          
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="StrPagekey">页面键,不能重复</param>
        /// <param name="tabbedPage">TabbedPage 实例</param>
        /// <param name="pages">tabbed page的子页面</param>
        /// <param name="strTitle">此主要针对的为FBin中的情况,有好想法后可优化</param>
        /// <returns></returns>
        public async Task NavigationToAsync(string StrPagekey,TabbedPage tabbedPage,Page[] pages,string strTitle)
        {
            await MainPage.Navigation.PushAsync(_contentPageActivationService.Activate(StrPagekey, tabbedPage,pages, strTitle));
        }


        private Page mainPage;//当前主页
        public  Page MainPage => mainPage ?? (mainPage = Application.Current.MainPage);//get mainpage

        private IContentPageActivationService _contentPageActivationService;//激活页面

        public ContentNavigationService(IContentPageActivationService contentPageActivationService)
        {
            _contentPageActivationService = contentPageActivationService;
        }
    }

 

 

 

内容页激活interface

    public interface IContentPageActivationService
    {
        Page Activate(Type type);
        Page Activate(string pageKey,TabbedPage tabbedPage,Page[] pages,String name);
    }

 

导航激活实现——激活服务中最开始按学习的方法,但在使用过程中发现其对不同的页面需要在switch中去增加相应的代码,太垃圾,于是用反射对不同type进行首次实例化。

class ContentPageActivationService : IContentPageActivationService
    {
        public Page Activate(Type pageKey)
        {
            string strPageKey = pageKey.Name;
            if (cacheNavigationPages.ContainsKey(strPageKey))
            {
                return cacheNavigationPages[strPageKey];
            }
            else
            {
                /*                switch (pageKey)
                                {
                                    case ConstParameter.FgBinManagement:
                                        cacheNavigationPages[strPageKey] = new ChooseType();
                                        break;
                                    case ConstParameter.FpbMain:
                                        cacheNavigationPages[strPageKey] = new FpbMainPage();
                                        break;

                                }*/
                cacheNavigationPages[strPageKey] = (Page)Activator.CreateInstance(pageKey);
          
                var titleView = new Label { Text = strPageKey, TextColor = Color.White };
                NavigationPage.SetTitleView(cacheNavigationPages[strPageKey], titleView);
                return cacheNavigationPages[strPageKey];
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pageKey"></param>
        /// <param name="pages"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public Page Activate(string pageKey, TabbedPage tabbedPage,Page[] pages, string name)
        {
            if (cacheNavigationTabbedPage.ContainsKey(pageKey))
            {return cacheNavigationTabbedPage[pageKey];
            }
            else
            {
                cacheNavigationTabbedPage[pageKey] = tabbedPage;//导航栏设置标题
                //var titleView = new Label { Text=pageKey,TextColor=Color.White};
                //NavigationPage.SetTitleView(tabbedPage,titleView);foreach (var item in pages)
                {
                    cacheNavigationTabbedPage[pageKey].Children.Add(item);
                }
                return cacheNavigationTabbedPage[pageKey];
            }
        }

        
        /// <summary>
        /// 缓存页面,避免重复实例化,导致内存耗损严重——单例
        /// </summary>
        private Dictionary<string, Page> cacheNavigationPages = new Dictionary<string, Page>();

        private Dictionary<string, TabbedPage> cacheNavigationTabbedPage = new Dictionary<string, TabbedPage>();
    }

 

 

 

调用tabbedpage 导航

        Transfer transfer = new Transfer();
        Status status = new Status();
        Inventory inventory = new Inventory();
        PartialBox partial = new PartialBox();
        private ContentNavigationService cns;
        FgMainPage fgMainPageTransfer;
        Page[] pagesTransfer;

        Page[] pagesPartial;
        FgMainPage fgMainPagePartial;
        public async void TransferPageAsync(string strTitle)
        {
            cns= cns ?? new ContentNavigationService(new ContentPageActivationService());
            
            if (strTitle.ToLower()!=nameof(partial).ToLower())
            {
                pagesTransfer =pagesTransfer??new Page[]{ transfer, status, inventory };
                await cns.NavigationToAsync(ConstantNavigationConstants.FgMainTransferPage, fgMainPageTransfer??new FgMainPage(), pagesTransfer, strTitle);
            }
            else
            {
                NavigateToPartial(strTitle);
            }
           
        }

 

ViewModel中调用  page导航,注意此红色字体的 command参数,此片指定为type,以方便在前端的xml中引入不同的page class

public ICommand MenuCommand { get; set; }
        private ContentNavigationService cns;
        public MenuViewModel()
        {
            /*    MenuCommand = new Command<View>(async (view)=>{
                    //var p = ((Button)view).Text;
                    //var id= ((Button)view).Id;
                    cns = cns ?? new ContentNavigationService(new ContentPageActivationService());
                    await cns.NavigationToAsync(((Button)view).Text);
                });*/
            MenuCommand = new Command<Type>(async (type) => {
                cns = cns ?? new ContentNavigationService(new ContentPageActivationService());
                await cns.NavigationToAsync(type);
            });
        }

 

MenuCommand = new Command<Type>中的Type从前端xml中通过 CommandParameter={x:Type local:ChooseType} 传递其类型。如下代码,注意其传递不同class时需要contentPage中先引入并命名,然后在CommandParameter中才能进行正常的引用。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamrinScanner.Views.MenuPage"
              xmlns:local="clr-namespace:XamrinScanner.Views.FgBinManagement"
             xmlns:Fpb="clr-namespace:XamrinScanner.Views.FiredPalletBoxMap"
             xmlns:vModel="clr-namespace:XamrinScanner.ViewModel"
            > 
    <NavigationPage.TitleView>     <!--navigation title-->
        <Label Style="{x:StaticResource  LabelWhiteFont}">Home Page</Label>
    </NavigationPage.TitleView>
    <ContentPage.BindingContext>
        <vModel:MenuViewModel/>
    </ContentPage.BindingContext>
    <ContentPage.Content>
        <StackLayout VerticalOptions="Center" Margin="10,10">
            <Button Text="Management" Style="{StaticResource BtnMargin20}"/>
            <Button Text="hipping" Style="{StaticResource BtnMargin20}"/>
            <Button Text="Bin Management" Style="{StaticResource BtnMargin20}"  x:Name="ChooseType" Command="{Binding MenuCommand}" CommandParameter="{x:Type local:ChooseType }"/>
            <Button Text="Pallet Box Map" Style="{StaticResource BtnMargin20}" x:Name="FpbMain" Command="{Binding MenuCommand}" CommandParameter="{x:Type Fpb:FpbMainPage}"/>
            <!--CommandParameter="{x:Type local:FpbMainPage}"-->
            <Button Text="RM Management" Style="{StaticResource BtnMargin20}" />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

 



posted @ 2022-01-12 15:20  盛沧海  阅读(85)  评论(0编辑  收藏  举报