Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9703

Prism.Forms で Shell みたいな画面作りたい

$
0
0

Xamarin.Forms でアプリ作るときには結構な人がお世話になる Prism !!
この Prism ですが、現状 Shell には対応していません。Shell が割とバギーな雰囲気があるせいもあるのかもしれませんが、Shell で作れる以下のような画面作りたいっていうのはよくある話ですよね。

image.png

じゃぁ Prism を使った状態でこんな雰囲気のページを作るには?ということになるのですが、大体以下のような感じです。

  • MasterDetailPage でフライアウトメニューを作る
  • MasterDetailPage の中に NavigationPage と表示させたいページを表示するようにナビゲーションする
  • タブにしたい場合は MasterDetailPage の中に TabbedPage を置いて、その中に NavigationPage でラップしたページを表示させる

大体こんな感じです。

やってみた

とりあえずやってみた。

shelllike2.gif

登録しているページは以下のような感じです

containerRegistry.RegisterForNavigation<NavigationPage>();containerRegistry.RegisterForNavigation<MainPage,MainPageViewModel>();// MasterDetailPagecontainerRegistry.RegisterForNavigation<ViewA,ViewAViewModel>();// ただの PagecontainerRegistry.RegisterForNavigation<ViewB,ViewBViewModel>();// ただの PagecontainerRegistry.RegisterForNavigation<ViewC,ViewCViewModel>();// ただの PagecontainerRegistry.RegisterForNavigation<MyTabbedPage,MyTabbedPageViewModel>();// TabbedPage

今回は初期状態では MasterDetailPage の中に 空の NavigationPage を表示しておきました。

protectedoverrideasyncvoidOnInitialized(){InitializeComponent();awaitNavigationService.NavigateAsync("MainPage/NavigationPage");}

MasterDetailPage を継承した MainPage では以下のように CollectionView でフライアウトメニューの項目を表示するようにしています。

MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?><MasterDetailPagex:Class="ShallEmulation.Views.MainPage"xmlns="http://xamarin.com/schemas/2014/forms"xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"xmlns:local="clr-namespace:ShallEmulation.ViewModels"xmlns:prism="http://prismlibrary.com"Title="{Binding Source={RelativeSource Mode=Self}, Path=Detail.CurrentPage.Title}"prism:ViewModelLocator.AutowireViewModel="True"Visual="Material"><MasterDetailPage.Master><ContentPageTitle="Menu"><StackLayout><LabelMargin="5"FontSize="Large"Text="Pages"/><CollectionViewx:Name="collectionView"ItemsSource="{Binding MasterMenuItems}"SelectedItem="{Binding SelectedMenuItem}"SelectionChangedCommand="{Binding NavigateCommand}"SelectionMode="Single"><CollectionView.ItemTemplate><DataTemplatex:DataType="local:MasterMenuItem"><GridPadding="15"><LabelText="{Binding Text}"/></Grid></DataTemplate></CollectionView.ItemTemplate></CollectionView></StackLayout></ContentPage></MasterDetailPage.Master></MasterDetailPage>

MainPageViewModel で実際にメニューに表示する項目の管理やメニューの項目が選択されたときに画面遷移を行うようにしています。

MainPageViewModel.cs
usingPrism.Commands;usingPrism.Navigation;usingSystem.Linq;usingstaticPrism.Navigation.KnownNavigationParameters;namespaceShallEmulation.ViewModels{publicclassMainPageViewModel:ViewModelBase{privateMasterMenuItem_selectedMenuItem;publicMasterMenuItemSelectedMenuItem{get{return_selectedMenuItem;}set{SetProperty(ref_selectedMenuItem,value);}}privateDelegateCommand_navigateCommand;publicDelegateCommandNavigateCommand=>_navigateCommand??=newDelegateCommand(NavigateExecute);privateasyncvoidNavigateExecute(){if(SelectedMenuItemisnull)return;awaitNavigationService.NavigateAsync(SelectedMenuItem.Path);}publicMasterMenuItem[]MasterMenuItems{get;}=newMasterMenuItem[]{new("ViewA","NavigationPage/ViewA"),new("ViewB","NavigationPage/ViewB"),new("ViewC","NavigationPage/ViewC"),new("Tab",$"MyTabbedPage?{CreateTab}=NavigationPage|ViewA&"+$"{CreateTab}=NavigationPage|ViewB&"+$"{CreateTab}=NavigationPage|ViewC&"+$"{SelectedTab}=ViewB"),};publicMainPageViewModel(INavigationServicenavigationService):base(navigationService){Title="Menues";}publicoverridevoidOnNavigatedTo(INavigationParametersparameters){if(SelectedMenuItemisnull){SelectedMenuItem=MasterMenuItems.First();NavigateExecute();}}}publicrecordMasterMenuItem(stringText,stringPath);}

タブのページのところだけ以下のように画面遷移の文字列がちょっと複雑になっています。これでタブの中に3ページ作って ViewB を初期表示にしています。

new("Tab",$"MyTabbedPage?{CreateTab}=NavigationPage|ViewA&"+$"{CreateTab}=NavigationPage|ViewB&"+$"{CreateTab}=NavigationPage|ViewC&"+$"{SelectedTab}=ViewB"),

戻るボタンで一旦トップに戻りたい

Shell でも先日やった戻るボタンで一旦トップに戻る実装ですが、今回の場合は MainPage でやれば OK です。

MainPage.xaml.cs
protectedoverrideboolOnBackButtonPressed(){varvm=(MainPageViewModel)BindingContext;vartopPage=vm.MasterMenuItems.First();if(vm.SelectedMenuItem.Path==topPage.Path){returnbase.OnBackButtonPressed();}else{vm.SelectedMenuItem=topPage;returntrue;}}

今回は、お試しで愚直に View に書いてますが OnBackButtonPressed のハンドリングは View でするとしても中身の処理は ViewModel に突っ込んだ方がいいと思います。

これで ViewA 以外で戻るボタンを押したら ViewA に行きます。

まとめ

とりあえず Prism 使うと Shell は諦めることになるので、こんな感じで Prism の強力なナビゲーション機能を使って実現することになるかなと思います。

ソースは GitHub に上げてます。

https://github.com/runceel/Prism.Forms.ShellLike


Viewing all articles
Browse latest Browse all 9703

Trending Articles