Xamarin.Forms セル(Formsを使用した追加の1歩)

2015.11.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Xamarin.Formsの画面作成では、「ページ」を使用して全体をどういう形式にするのか決め、その上で、前回の「レイアウト」を使用しながら、「コントロール」を散りばめていくと紹介したのですが、実は、後1つだけ重要な要素があります。

[参考リンク]
Xamarin.Forms ページ(Formsを使用したアプリ作成の第1歩)
Xamarin.Forms レイアウト(Formsを使用したアプリ作成の次の1歩)
Xamarin.Forms コントロール① (Formsを使用した最後の1歩)
Xamarin.Forms コントロール② (Formsを使用した最後の1歩)

それは、セルです。

セルとは、ListView と TableView における1つ1つのアイテムに使用されるビューです。

Xamarin.FormsのCellクラスには、「TextCell」「ImageCell」「EntryCell」「SwitchCel」という4つの定型(テンプレート)と、すべて自前で設計する「ViewCell」があります。

サンプルは、ListViewにデータリソース(データとテンプレート)を設定するというパターンで作成してみました。

2 セル

(1) TextCell

プライマリ(TextProperty)及び、セカンダリ(DetailProperty)の2つのテキストを表示するテンプレートであり、テキスト色の指定が可能です。

以前、TextCell.StylePropertyと言うプロパティでテキストの配置(Vertical/horizontal)が指定できたのですが、廃止されたようです。横に並べたい場合は、ViewCellを使用せよということでしょう。

App.cs

// データの型定義
class Data {
    public string Text { get; set; }
    public string Detail { get; set; }
}

class MyPage :ContentPage {
    public MyPage() {
        // iOSだけ、上部に余白をとる
        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);

        //データの生成
        var ar = new List<Data>();
        foreach(var n in Enumerable.Range(0, 100)) {
            ar.Add(new Data { Text = "Text-"+n, Detail = "Detail-" + n });
        }
        // ListViewを生成する
        var listView = new ListView {
            ItemsSource = ar,//データソースの指定
            ItemTemplate = new DataTemplate(typeof(TextCell))//テンプレートの指定
        };
        //バインディング指定
        listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Text");
        listView.ItemTemplate.SetBinding(TextCell.DetailProperty, "Detail");
        // テキスト色の指定
        listView.ItemTemplate.SetValue(TextCell.TextColorProperty, Color.Red);
        //ListViewのみをコンテンツとして配置する
        Content = listView;
    }
}
iOS Android WindowsPhone
001 002 003

(2) ImageCell

TextCellに画像を1つ追加したテンプレートです。画像のサイズは自動調整されます。

App.cs

// データの型定義
class Data {
    public string Text { get; set; }
    public string Detail { get; set; }
    public string Icon { get; set; }
}

class MyPage : ContentPage {
    public MyPage() {
        // iOSだけ、上部に余白をとる
        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);

        //データの生成
        var ar = new List<Data>();
        foreach (var n in Enumerable.Range(0, 100)) {
            ar.Add(new Data { Text = "Text-" + n, Detail = "Detail-" + n , Icon ="icon.png"});
        }
        // ListViewを生成する
        var listView = new ListView {
            ItemsSource = ar,//データソースの指定
            ItemTemplate = new DataTemplate(typeof(ImageCell))//テンプレートの指定
        };
        //バインディング指定
        listView.ItemTemplate.SetBinding(ImageCell.TextProperty, "Text");
        listView.ItemTemplate.SetBinding(ImageCell.DetailProperty, "Detail");
        listView.ItemTemplate.SetBinding(ImageCell.ImageSourceProperty, "Icon");
        // テキスト色の指定
        listView.ItemTemplate.SetValue(ImageCell.TextColorProperty, Color.Green);
        //ListViewのみをコンテンツとして配置する
        Content = listView;
    }
}
iOS Android WindowsPhone
004 005 006

(3) EntryCell

ラベルと1行テキスト入力のテンプレートです。 EntryCell.TextPropertyは、入力された値を取得するため、双方向でバインディングする必要があります。

App.cs

// データの型定義
class Data {
    public string Label { get; set; }
    public string Placeholder { get; set; }
    public string Text { get; set; }
}

class MyPage : ContentPage {
    public MyPage() {
        // iOSだけ、上部に余白をとる
        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);

        //データの生成
        var ar = new List<Data>{
            new Data{Label = "名前", Placeholder = "YAMADA TARO"},
            new Data{Label = "メールアドレス", Placeholder = "user@example.com"},
            new Data{Label = "電話番号", Placeholder = "090-000-0000"},
        };

        // ListViewを生成する
        var listView = new ListView {
            ItemsSource = ar,//データソースの指定
            ItemTemplate = new DataTemplate(typeof(EntryCell))//テンプレートの指定
        };
        //バインディング指定
        listView.ItemTemplate.SetBinding(EntryCell.LabelProperty, "Label");
        listView.ItemTemplate.SetBinding(EntryCell.PlaceholderProperty, "Placeholder");
        //BindingModeでarに戻すように指定しないと設定された値を取り出せない
        listView.ItemTemplate.SetBinding(EntryCell.TextProperty, new Xamarin.Forms.Binding("Text", BindingMode.TwoWay));
        //キーボードを指定する場合
        //listView.ItemTemplate.SetValue(EntryCell.KeyboardProperty, Keyboard.Email);

         //ListViewのみをコンテンツとして配置する
        Content = listView;
    }
}
iOS Android WindowsPhone
007 008 009

(4) SwitchCell

ラベルとON/OFFのスイッチのテンプレートです。 OnPropertyは、自動的に双方向でバインディングされます。

App.cs

class Data {
    public string Label { get; set; }
    public bool Sw { get; set; }
}

class MyPage : ContentPage {
    public MyPage() {
        // iOSだけ、上部に余白をとる
        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);

        //データの生成
        var ar = new List<Data>{
            new Data{Label = "AAA", Sw = true},
            new Data{Label = "BBB", Sw = false}
        };

        var listView = new ListView {
            ItemsSource = ar,//データソースの指定
            ItemTemplate = new DataTemplate(typeof(SwitchCell))//テンプレートの指定
        };
        //バインディング指定
        listView.ItemTemplate.SetBinding(SwitchCell.TextProperty, "Label");
        listView.ItemTemplate.SetBinding(SwitchCell.OnProperty, "Sw");//双方向でバインディングされる

        //ListViewのみをコンテンツとして配置する
        Content = listView;
    }
}
iOS Android WindowsPhone
010 011 012

(5) ViewCell

ViewCellでは、すべてのレイアウト(Xamarin.Forms.View)を作成します。 以前に紹介した「レイアウト」などを駆使することで、完全に自由に画面を作成することが可能です。

App.cs

class Data {
    public string Icon { get; set; }
    public string No { get; set; }
    public string Message { get; set; }
}

class MyPage : ContentPage {
    public MyPage() {
        // iOSだけ、上部に余白をとる
        Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);

        //データの生成
        var ar = new List<Data>();
        foreach (var n in Enumerable.Range(0, 100)) {
            ar.Add(new Data { No = "No. " + n, Message = "Message-" + n, Icon = "icon.png" });
        }

        var listView = new ListView {
            ItemsSource = ar,//データソースの指定
            RowHeight = 60
        };
        listView.ItemTemplate = new DataTemplate(() => {
            var icon = new Image();
            icon.SetBinding( Image.SourceProperty, "Icon");
           var no = new Label() { FontSize = 12 };
            no.SetBinding(Label.TextProperty, "No");
            var message = new Label() { FontSize = 20};
            message.SetBinding(Label.TextProperty, "Message");

            //No Messageを縦に並べたテキストレイアウトを作成する
            var textLayout = new StackLayout {
                Children = { no, message }
            };

            return new ViewCell {
                View = new StackLayout {
                    Orientation = StackOrientation.Horizontal,//Iconとテキストレイアウトを横に並べる
                    Padding = new Thickness(20, 10, 0, 0),//パディング
                    Spacing = 10,//スペース
                    Children = {  textLayout,icon }
                }
            };
        });

        //ListViewのみをコンテンツとして配置する
        Content = listView;
    }
}
iOS Android WindowsPhone
013 014 015

3 まとめ

今回は、追加の1歩ということで、セルを紹介しました。 Xamarin.Formsで画面を作成する際に必要な概念は、これですべてです。 2015年11月現在、Xamarin.Formsには、iOSやAndroidのようにビジュアルに画面を設計する環境がありませんが・・・・近々登場するのでは?という予感はします。

githubサンプルコード(https://github.com/furuya02/Xamarin.Forms.CellSample)

本記事は、2015年11月08日現在で最新の Xamarin.Forms 1.5.1.6471 を使用して作成されています。

4 参考リンク

Xamarin Developers Guide 「Xamarin.Forms Cells」
Xamarin.Forms ページ(Formsを使用したアプリ作成の第1歩)
Xamarin.Forms レイアウト(Formsを使用したアプリ作成の次の1歩)
Xamarin.Forms コントロール① (Formsを使用した最後の1歩)
Xamarin.Forms コントロール② (Formsを使用した最後の1歩)
この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015
Xamarin記事一覧(SAPPOROWORKSの覚書)