• 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)
            {
                //throw new NotImplementedException();
                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)
            {
                //throw new NotImplementedException();
                if (cacheNavigationTabbedPage.ContainsKey(pageKey))
                {
                    if (!(pages[pages.Length - 1] is PartialBox))
                    {
                        cacheNavigationTabbedPage[pageKey].Children[0].Title = name;
                    }
                
                    return cacheNavigationTabbedPage[pageKey];
                }
                else
                {
                    cacheNavigationTabbedPage[pageKey] = tabbedPage;//new FgMainPage();
                    //导航栏设置标题
                    //var titleView = new Label { Text=pageKey,TextColor=Color.White};
                    //NavigationPage.SetTitleView(tabbedPage,titleView);
                    if (pages[0].Title == nameof(Transfer) )
                    {
                        pages[0].Title = name;
                    }
                    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)
            {
                //if (cns == null)
                //{
                //    cns = new ContentNavigationService(new ContentPageActivationService());
                //}
                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);
                }
                
                //await cns.NavigationToAsync(ConstantNavigationConstants.FgMainTransferPage);
                
            }

    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>


    有道无术,术尚可求;有术无道,止于术。
  • 相关阅读:
    Linux上Blogilo连接博客园账户
    字符串模式匹配KMP算法
    回溯法之n皇后问题
    回溯法之k着色问题
    动态规划之最短路径(Floyd算法)
    动态规划之最长公共子序列
    动态规划之矩阵链乘
    New home
    POJ 2478:Farey Sequence
    Codeforces Round #416 (Div. 2)
  • 原文地址:https://www.cnblogs.com/chengcanghai/p/15792799.html
Copyright © 2020-2023  润新知