【更新】Visual Studio 2017 の場合
-
MasterDetailPage
とその他諸々をソリューションに追加してくれるテンプレート Forms MasterDetail Page Xaml が VS2017 で追加されました。 - 説明は以上です。ありがとうございました
- 【注意】VS2017 のプロジェクト テンプレート クロスプラットフォーム アプリ (Xamarin.Forms またはネイティブ) で マスター/詳細 を選択しても
MasterDetailPage
クラスは使用されません。 (Bug 53141)
方針
- Xamarin 公式ページになるべく従って
- C# コードではなく xaml の方で
- Droid と iOS
- 私が引っかかったところを補足していきます
- 自分で作るクラスがどれか分かりにくいので
My
を付けていきます
公式
developer.xamarin.com/guides/xamarin-forms/user-interface/navigation/master-detail-page/
環境
- Visual Studio 2015 update 3
- Xamarin 4.2.x.x
プロジェクト
-
Blank Xaml App (Xamarin.Forms Portable)
MyApp
を作成 - Windows と WinPhone プロジェクトを削除(ゴメンナサイ)
最初のビルド
Welcome to Xamarin Forms!
MyMasterDetailPage.xaml
Forms Xaml Page MyMasterDetailPage
を追加
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp;assembly=MyApp"
x:Class="MyApp.MyMasterDetailPage">
<MasterDetailPage.Master>
<local:MyMasterPage />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:MainPage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
- .cs で派生親を
ContentPage
からMasterDetailPage
に変更するのを忘れないこと - MasterDetailPage を作るテンプレートがあってもいいのに
- デザインの情報がほとんど無いのに xaml で作るのって回りくどくないですか...
- Detail 役は
MainPage
(Welcome to Xamarin Forms! のページ)で済ませました - Master 役はこのあと作ります
MyMasterPage.xaml
-
Forms Xaml Page
MyMasterPage
を追加
<?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="MyApp.MyMasterPage"
Padding="0,40,0,0"
Icon="hanburger.png"
Title="メニュー">
<StackLayout VerticalOptions="FillAndExpand">
<ListView x:Name="listView" VerticalOptions="FillAndExpand" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell Text="{Binding Title}" ImageSource="{Binding IconSource}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
- Master 役
- 派生親は
ContentPage
のままで OK -
hamnurger.png
を Sample Code から落としてきて Droid と iOS の両方に追加する -
Padding="0,40,0,0"
をサボると1番上のアイテムが画面上部の OS の操作と干渉する -
ContentPage.Content
は省略できると思います
MyMasterPage.xaml.cs
using System.Collections.Generic;
using Xamarin.Forms;
namespace MyApp
{
public partial class MyMasterPage : ContentPage
{
public MyMasterPage()
{
InitializeComponent();
var myMasterPageItems = new List<MyMasterPageItem>();
myMasterPageItems.Add(new MyMasterPageItem
{
Title = "ようこそ",
IconSource = "icon.png",
TargetType = typeof(MainPage)
});
listView.ItemsSource = myMasterPageItems;
}
}
}
- リストの中身を準備するところ
- 画像は Droid にある icon.png でゴマカす(iOS 側にも icon.png を追加する)
-
x:Name="listView"
と書けば .cs でlistView
が使えるようになるのはうれしい -
MyMasterPageItem
はこのあと作る
MyMasterPageItem.cs
-
クラス
MyMasterPageItem
を追加 - Sample Code の MasterPageItem.cs からメンバーの定義をコピペ
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyApp
{
public class MyMasterPageItem
{
public string Title { get; set; }
public string IconSource { get; set; }
public Type TargetType { get; set; }
}
}
- ListView のアイテム
- public にするのを忘れない
- 自分で作らないといけないクラスなのに説明が無いのはちょっと不親切では...
-
Type
型とかスラスラ出てきません...
App.xaml.cs
- 最初に開く画面を変える
- これを変えないと Welcome to Xamarin Forms! のまま
public App()
{
InitializeComponent();
//MainPage = new MyApp.MainPage();
MainPage = new MyMasterDetailPage();
}
一旦ビルド
- ここで一旦ビルドが通る
- 実行すると Master は出てくるけど、タップしても何も起きない状態
タップの実装
MyMasterPage.xaml.cs
- Master の ListView を公開
public partial class MyMasterPage : ContentPage
{
public ListView ListView { get { return listView; } }
...
MyMasterDetailPage.xaml
- Master に名前を付ける
<MasterDetailPage ...>
<MasterDetailPage.Master>
<local:MyMasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
...
</MasterDetailPage>
MyMasterDetailPage.xaml.cs
- MasterDetailPage にイベント処理を記述
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace MyApp
{
public partial class MyMasterDetailPage : MasterDetailPage
{
public MyMasterDetailPage()
{
InitializeComponent();
masterPage.ListView.ItemSelected += OnItemSelected;
}
void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MyMasterPageItem;
if (item != null)
{
Detail = new NavigationPage((Page)Activator.CreateInstance(item.TargetType));
masterPage.ListView.SelectedItem = null;
IsPresented = false;
}
}
}
}
- MasterDetailPage から Master の中に手を突っ込むのは気持ち悪くないですか...
最後のビルド
- 動くぞ :o
- ついでに ListView の書き方も分かった
- 公式の最後の
MasterBehavior
をいじる話はオマケ