かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Blendのクラスのサンプルデータをプログラムで機械的に作りたい

Blend for VS2013からWindows ストア アプリでもサンプルデータがサポートされるようになりました。これでWPF, Silverlight(何で切られてしまったん…), Windows Phone(何で日本で出ないの…), Windows ストア アプリで同じようにデザイナ画面でデータを見ながら画面のデザインが出来るようになります。

ViewModelを定義している場合は、クラスを元にしたサンプルデータを作ると思うのですが、このデータがなんとXAMLで書かれています。例えば、以下のようなクラスがあるとします。

using System.Collections.ObjectModel;

namespace SampleDataGenApp
{
    public class ApplicationModel
    {
        public ObservableCollection<Person> People { get; set; }
    }

    public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

このクラスを元にBlendでサンプルデータを作ります。

f:id:okazuki:20131026230517p:plain

そうすると、プロジェクトの下にSampleDataというフォルダが作られ、ApplicationModelSampleData.xamlというXAMLが作られます。このXAMLの中は以下のようになっています。

<SampleDataGenApp:ApplicationModel xmlns:SampleDataGenApp="using:SampleDataGenApp">
    <SampleDataGenApp:ApplicationModel.People>
        <SampleDataGenApp:Person Age="22" Id="24" Name="Cras class"/>
        <SampleDataGenApp:Person Age="83" Id="62" Name="Aenean maecenas curabitur"/>
        <SampleDataGenApp:Person Age="23" Id="96" Name="Praesent duis nam"/>
        <SampleDataGenApp:Person Age="16" Id="43" Name="Vestibulum mauris nunc amet"/>
        <SampleDataGenApp:Person Age="93" Id="54" Name="Phasellus ante adipiscing curae aliquam"/>
        <SampleDataGenApp:Person Age="11" Id="37" Name="Integer parturient nullam donec"/>
        <SampleDataGenApp:Person Age="17" Id="20" Name="Sed arcu"/>
        <SampleDataGenApp:Person Age="86" Id="25" Name="Consequat vestibulum"/>
        <SampleDataGenApp:Person Age="20" Id="92" Name="Vestibulum accumsan diam quisque dis"/>
        <SampleDataGenApp:Person Age="91" Id="87" Name="Aptent vivamus est"/>
    </SampleDataGenApp:ApplicationModel.People>
</SampleDataGenApp:ApplicationModel>

とても文字列とか英語チックです。メールアドレスや、URLなんかをサンプルデータに使うようにすると、それっぽくなりますが、それ以外の文字列はとても英語です。はい。

そして、このサンプルデータをいじろうとしたとしても、Personクラスは100件くらい機械的なデータがとりあえずあればいいや!みたいな状態でも、XAMLをちまちまコピペしないといけません。これは怠い。

そうだT4を使おう

未だにVisual Studioの標準機能でシンタックスハイライトすらされてないT4テンプレートですが、こいつを使うと、このサンプルデータをいい具合にできます。まず、サンプルデータのXAMLと同じ名前の.ttファイルを作成します。

f:id:okazuki:20131026230957p:plain

そして、オリジナルのAppliationModelSampleData.xamlの中身をコピーして.ttのファイルに貼り付けます。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".txt" #>

<SampleDataGenApp:ApplicationModel xmlns:SampleDataGenApp="using:SampleDataGenApp">
    <SampleDataGenApp:ApplicationModel.People>
        <SampleDataGenApp:Person Age="22" Id="24" Name="Cras class"/>
        <SampleDataGenApp:Person Age="83" Id="62" Name="Aenean maecenas curabitur"/>
        <SampleDataGenApp:Person Age="23" Id="96" Name="Praesent duis nam"/>
        <SampleDataGenApp:Person Age="16" Id="43" Name="Vestibulum mauris nunc amet"/>
        <SampleDataGenApp:Person Age="93" Id="54" Name="Phasellus ante adipiscing curae aliquam"/>
        <SampleDataGenApp:Person Age="11" Id="37" Name="Integer parturient nullam donec"/>
        <SampleDataGenApp:Person Age="17" Id="20" Name="Sed arcu"/>
        <SampleDataGenApp:Person Age="86" Id="25" Name="Consequat vestibulum"/>
        <SampleDataGenApp:Person Age="20" Id="92" Name="Vestibulum accumsan diam quisque dis"/>
        <SampleDataGenApp:Person Age="91" Id="87" Name="Aptent vivamus est"/>
    </SampleDataGenApp:ApplicationModel.People>
</SampleDataGenApp:ApplicationModel>

そして、ApplicationModelSampleData.xamlを削除します。最後に、.ttファイルの中の<#@ output extesion=".txt" #>となっている箇所を<#@ output extesion=".xaml" #>に変更します。

これで、ソリューションエクスプローラは以下のようになります。

f:id:okazuki:20131026231305p:plain

.ttファイルから生成された.xamlファイルを選択してプロパティのビルドアクションをPageからDesignDataに変更します。

f:id:okazuki:20131026231426p:plain

ビルドして、Visual StudioからBlendに戻ってエラーが無ければ成功です。

データを作ろう

今は固定のデータをT4テンプレートに貼り付けただけなので、以下のようにテンプレートを書き換えてサンプルデータを適当に100件作ってみました。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".xaml" #>

<#
var r = new Random();
#>

<SampleDataGenApp:ApplicationModel xmlns:SampleDataGenApp="using:SampleDataGenApp">
    <SampleDataGenApp:ApplicationModel.People>
    <#
    foreach (var i in Enumerable.Range(0, 100))
    {
    #>
        <SampleDataGenApp:Person Age="<#= r.Next(100) #>" Id="<#= i #>" Name="サンプル 太郎<#= i #>"/>
    <#
    }
    #>
    </SampleDataGenApp:ApplicationModel.People>
</SampleDataGenApp:ApplicationModel>

生成されるXAMLは長いので省略します。BlendでサンプルデータのApplicationModelのPeopleを画面にドロップしてみると、ちゃんとT4テンプレートで生成されたサンプルデータが使われていることが確認できます。

f:id:okazuki:20131026231950p:plain

まとめ

サンプルデータを生成するのにT4テンプレートを活用してもよさそうな雰囲気を感じました。どうでしょう。