前回の「[Xamarin.CrossPlatform] マスタ/詳細アプリのプロジェクトを理解する2」では、実行時の画面とApp.xamlのコードについて見てきました。
今回は、共通プロジェクトが持つViewsフォルダにある以下のファイルを見ていきます。そのほかのファイルについては、この連載の別の回で紹介します。
- MainPage.cs
- ItemPage.xaml
MainPage.cs
アプリ実行時に最初に実行されるのがこのファイルです。
ソースコードは以下のようになっています。
using System;
using Xamarin.Forms;
namespace MasterDetailSample
{
public class MainPage : TabbedPage
{
public MainPage()
{
Page itemsPage, aboutPage = null;
switch (Device.RuntimePlatform)
{
case Device.iOS:
itemsPage = new NavigationPage(new ItemsPage())
{
Title = "Browse"
};
aboutPage = new NavigationPage(new AboutPage())
{
Title = "About"
};
itemsPage.Icon = "tab_feed.png";
aboutPage.Icon = "tab_about.png";
break;
default:
itemsPage = new ItemsPage()
{
Title = "Browse"
};
aboutPage = new AboutPage()
{
Title = "About"
};
break;
}
Children.Add(itemsPage);
Children.Add(aboutPage);
Title = Children[0].Title;
}
protected override void OnCurrentPageChanged()
{
base.OnCurrentPageChanged();
Title = CurrentPage?.Title ?? string.Empty;
}
}
}
MainPageクラスはTabbedPageを継承して作られています。実行結果からもわかる通り、アプリの画面はタブで切り替えることができるようになっています。
続いて11行目ですが、タブページに表示するためのページを格納する変数を宣言しています。itemsPageはリスト表示をするためのページを、AboutPageはアプリ情報を表示するためのページを格納する変数です。
13行目のswitch文は、OSの判定を行うためのものです。15行目でiOSを、28行目でiOS以外(AndroidやUWPが対象)を判定します。
iOSの場合はNavigationPageクラスを使用してitemPageとaboutPageをそれぞれ作成しています。また、iOSはタブにアイコンを表示することができるので、作成したページのIconプロパティに表示するイメージ画像を設定しています(25行目と26行目)。これらのイメージ画像はiOS側のプロジェクトのResourcesフォルダに格納されています。
iOS以外の場合はItemPageクラスを使用してitemsPageとaboutPageを作成しています。
ページ作成後はChildrenクラスが持つAddメソッドで追加をします(41行目と42行目)。
最後にTitleプロパティに最初に追加したページ(itemsPage)のタイトルを設定します(44行目)。
ItemsPage.xaml
ItemsPage.xamlはリスト表示を担当するファイルです。
前回も掲載しましたがItemsViewが表示された時のアプリ画面を以下に示します。
Xamlのコードは以下の通りです。
<?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="MasterDetailSample.ItemsPage" Title="{Binding Title}" x:Name="BrowseItemsPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Clicked="AddItem_Clicked" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView x:Name="ItemsListView" ItemsSource="{Binding Items}" VerticalOptions="FillAndExpand" HasUnevenRows="true" RefreshCommand="{Binding LoadItemsCommand}" IsPullToRefreshEnabled="true" IsRefreshing="{Binding IsBusy, Mode=OneWay}" CachingStrategy="RecycleElement" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding Text}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" FontSize="16" />
<Label Text="{Binding Description}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
画面そのものはContentPageを使用して作られています(2行目)。ContentPageはツールバーと1つのコントロールを配置することができ、ツールバーには、[Add]ボタンが1つ配置されています(3〜5行目)。またコントロール配置部分(6〜21行目)ではStackLayoutコントロールの中にListViewコントロールを配置して、リスト表示を行うようにしています。
リスト表示部分は、バインディングでデータを表示するようにしています(8行目)。表示するデータは「 ItemsSource=“{Binding Items}“」でバインディング(連結)しています。
また、リスト表示部分を下に引っ張って離すと最新のデータが表示されるようにするために「 IsPullToRefreshEnabled=“true“」という記述があります。データの更新は「 RefreshCommand=“{Binding LoadItemsCommand}“」で行なっています。
「HasUnevenRows=“true“」は重要なプロパティです。このプロパティがあることで項目のサイズを動的に変えることができるようになります。
リストにはテンプレートがあります(9行目)。テンプレートは、コレクション内の各要素を表示する方法を指示します。テンプレート内に置いたViewCell(11行目)は1つの項目をどのような要素で表示するかを自由に表現するためのものです。ここではStackPanelにフォントサイズが異なるLabelを2つ縦に並べて配置しています。これによりリストに表示される1つの項目は2つのテキストから構成されることになります。
続いてコードビハインドのItemPages.xaml.csファイルを見てみましょう。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace MasterDetailSample
{
public partial class ItemsPage : ContentPage
{
ItemsViewModel viewModel;
public ItemsPage()
{
InitializeComponent();
BindingContext = viewModel = new ItemsViewModel();
}
async void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
var item = args.SelectedItem as Item;
if (item == null)
return;
await Navigation.PushAsync(new ItemDetailPage(new ItemDetailViewModel(item)));
// Manually deselect item
ItemsListView.SelectedItem = null;
}
async void AddItem_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new NewItemPage());
}
protected override void OnAppearing()
{
base.OnAppearing();
if (viewModel.Items.Count == 0)
viewModel.LoadItemsCommand.Execute(null);
}
}
}
Xamlのコード説明の中でも触れましたが、ItemsPageはContentPageで作られています。よって、ContentPageクラスを継承しています(9行目)。
コンストラクタでは、表示するデータをBindingContextに設定しています(17行目)。これによりItemsPageが持つデータがセットされ、ListViewに連携されるようになります。
20行目のOnItemSelectedは、リストに表示された項目が選択された時に発生するイベントです。
項目が選択されると、26行目のNavigation.PushAsyncメソッドによって、その項目の詳細ページへと移動します。このとき引数には現在選択されている項目が渡されています。
32行目の AddItem_Clickedは、ツールバーの[Add]ボタンがタップされたときに発生するイベントで、アプリ情報を表示するページへと移動します。
37行目の OnAppearingは、アプリ内にItemsPageが表示された時に発生するイベントです。viewModdelのデータが0件の場合は、 viewModel.LoadItemsCommand.Execute(null);でデータを読み込みます。
今回は、主としてリストの表示部分について見てきました。次回は、実際のデータを作成する部分について見ていきたいと思います。

コメント