shuhelohelo’s blog

Xamarin.Forms多めです.

Xamarin.Formsでデザイン時の仮データを定義する方法

montemagno.com

docs.microsoft.com

techcommunity.microsoft.com

Design Time Dataとはアプリを実行せずに,XAMLでのUIデザイン時に表示させる仮のデータのこと.

これによってViewModelなどの表示させるデータが出来上がっていない段階でも,仮のデータを表示させることで実際に近い状態を確認しながらUIをデザインできる.

環境

準備

上のブログ記事では以下のxml名前空間を追加するように書かれていますが,最初から入っているのでOkです.

             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"

シンプルなプロパティの場合

これは例えばLabelのTextなどにあたります. Textの内容をデータバインディングによって実行時に表示するようにしているとします.

        <Label Text="{Binding Greeting}" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />

このとき,Visual Studioのデザイナーにはご存知のとおり何も表示されません.

f:id:shuhelohelo:20191025150728p:plain

デザイナー上に仮のデータを表示させたい場合は,以下のようにします.

    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="{Binding Greeting}" d:Text="Hello My Xamarin.Forms!" 
           HorizontalOptions="Center"
           VerticalOptions="CenterAndExpand" />
    </StackLayout>

d:Text="Hello My Xamarin.Forms!"という記述を追加しました.これがデザイン用に仮に表示させる内容になります.

デザイナーをみると,仮データが表示されていることが確認できます.

f:id:shuhelohelo:20191025150214p:plain

このように,仮データを指定したい属性にd名前空間をつけることでデザイナーに仮データを表示させることができます.

もちろん背景色も仮の指定ができます.

        <Label Text="{Binding Greeting}" d:Text="Hello My Xamarin.Forms!" 
               d:BackgroundColor="Orange"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

f:id:shuhelohelo:20191025151950p:plain

インジケータも出せます.

        <ActivityIndicator
            IsVisible="{Binding IsBusy}"
            IsRunning="{Binding IsBusy}"
            d:IsRunning="True"
            HorizontalOptions="Center"
            VerticalOptions="Center"/>

リスト

アプリケーションでは必須のUIです.

        <ListView>
            <d:ListView.ItemsSource>
                <x:Array Type="{x:Type x:String}">
                    <x:String>Item One</x:String>
                    <x:String>Item Two</x:String>
                    <x:String>Item Three</x:String>
                </x:Array>
            </d:ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ImageCell Text="{Binding .}"
                       Detail="{Binding Location}"
                       d:Detail="Location"
                       ImageSource="{Binding Image}"
                       d:ImageSource="icon.png"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

f:id:shuhelohelo:20191025160254p:plain

リスト2

上の例では<d:ListView.ItemsSource>で文字列の配列をItemsSourceとして指定しました.

しかし,実際にはListViewのItemsSourceとして指定するのはもう少し複雑なクラスであることがほとんどです.

任意のクラスを仮データとして指定する方法は以下のとおりです.

まずはModelとなるクラスを作ります.

namespace XFDesignTimeData.Models
{
    public class Person
    {
        public string Name { get; set; }
        public string Location { get; set; }
        public string Image { get; set; }
    }
}

次に,Xaml側でPersonクラスを参照できるようにします. ContentPage要素に以下の一行を追加します.

             xmlns:models="clr-namespace:XFDesignTimeData.Models"

ListViewではItemsSourceにPersonクラスの配列を指定します.

DataTemplateにもx:DataType="models:Person"としてPersonクラスを指定します.

        <ListView>
            <d:ListView.ItemsSource>
                <x:Array Type="{x:Type models:Person}">
                    <models:Person Name="田中一郎" Location="東京都江戸川区"/>
                    <models:Person Name="鈴木次郎" Location="東京都渋谷区"/>
                    <models:Person Name="高橋三郎" Location="東京都港区"/>
                </x:Array>
            </d:ListView.ItemsSource>
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="models:Person">
                    <ImageCell
                       Text="{Binding Name}"
                       Detail="{Binding Location}"
                       ImageSource="{Binding Image}"
                       d:ImageSource="icon.png"/>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

これで以下のように表示されます.

f:id:shuhelohelo:20191025164907p:plain

GitHub

Xaml側でインテリセンスを効かせる

Xaml側とデータバインドするオブジェクトはXamlかコードビハインドのどちらでも指定することができます.

Xaml側で指定する方法:

    <ContentPage.BindingContext>
        <viewmodels:MainPageViewModel />
    </ContentPage.BindingContext>

コードビハインドで指定する方法:

        public MainPage()
        {
            InitializeComponent();
            BindingContext = new MainPageViewModel();
        }

Xaml側で指定した場合,Xaml側でインテリセンスが効くので非常に便利です.

しかし,多くの場合はコードビハインドで指定するか,MVVMフレームワーク側でバインドしてくれるため,Xaml側で指定することは多くはないと思います.

そのため,Xaml編集時にはインテリセンスが効かずに不便を感じることがあります.

そんなときはd:名前空間を使ってデザイン用としてXaml側でも指定すると良いです.

    <d:ContentPage.BindingContext>
        <viewmodels:MainPageViewModel />
    </d:ContentPage.BindingContext>

すると,以下のようにインテリセンスによってプロパティがサジェストされます.

f:id:shuhelohelo:20191025215419p:plain

ViewModelがまだできていない場合にMockを突っ込んでも良いです.

GitHub