かずきのBlog@hatena

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

Tileっぽい見た目をWPFでも

本日、ついにWindows Phone 7 Mangoの発売に関する日本での公式な発表がありました!auさんから出るということなので、docomoからauに乗り換えようかともんもんとしてる今日この頃です。発表前では8月22日に発売されるのでは?という情報も飛び交ってたりして、そんなに早いならauに乗り換え決定だ!と思ってたのですが、実際の発売は9月以降ということで、少し乗り換えどうしようかなと言う感じです。


そんなMangoがアツイときにタイムリーに@ITに以下の記事があがってました。

Tile UIをWP7のアプリ内で、どうやって再現するかということが書かれています。ということで見た目だけですが、WPFでも同じようなものをさくっとでっちあげてみました。XAML的には上記連載のものを、そのまま手書きでがりっと書いただけになります。
因みに、アプリ内の画像はWindows Azureのマスコット「クラウディア・窓辺 (Claudia Madobe)」の素材を利用させていただきました。

アプリの見た目は以下のような感じです。

ソリューションは、下記からダウンロードできます。

ソリューション内にはプロジェクトが2つ用意してあります。TileSampleプロジェクトはWindowのContent内にWrapPanelを置いて、タイルっぽいものを1つ1つ手書きで書いたものです。

<Window x:Class="TileSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <ScrollViewer>
        <WrapPanel>
            <StackPanel Background="{StaticResource {x:Static SystemColors.HotTrackBrushKey}}" Margin="0,0,10,10" Width="200" Height="200">
                <Image Source="クラウディアSD1.psd" Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" />
                <TextBlock Text="クラウディアSD1" Margin="5,-35,0,0" />
            </StackPanel>
            <StackPanel Background="{StaticResource {x:Static SystemColors.HotTrackBrushKey}}" Margin="0,0,10,10" Width="200" Height="200">
                <Image Source="クラウディアSD2.psd" Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" />
                <TextBlock Text="クラウディアSD2" Margin="5,-35,0,0" />
            </StackPanel>
            <StackPanel Background="{StaticResource {x:Static SystemColors.HotTrackBrushKey}}" Margin="0,0,10,10" Width="200" Height="200">
                <Image Source="クラウディアSD3.psd" Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" />
                <TextBlock Text="クラウディアSD3" Margin="5,-35,0,0" />
            </StackPanel>
            <StackPanel Background="{StaticResource {x:Static SystemColors.HotTrackBrushKey}}" Margin="0,0,10,10" Width="200" Height="200">
                <Image Source="クラウディアSD4.psd" Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" />
                <TextBlock Text="クラウディアSD4" Margin="5,-35,0,0" />
            </StackPanel>
        </WrapPanel>
    </ScrollViewer>
</Window>

静的なコンテンツなら、こんな感じでいいかもしれません。

TileSample2プロジェクトは、WindowのDataContextにデータを入れて、ItemsControlにそのデータをタイルっぽく表示しています。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        // NameとSourceプロパティを持ったオブジェクトの配列を元に
        // タイルっぽいものの生成を行う。
        this.DataContext =
            new[]
            {
                "クラウディアSD1.psd",
                "クラウディアSD2.psd",
                "クラウディアSD3.psd",
                "クラウディアSD4.psd",
            }
            .Select(s => new
            {
                Name = System.IO.Path.GetFileNameWithoutExtension(s),
                Source = new Uri(s, UriKind.Relative)
            })
            .ToArray();
    }

XAMLではScrollViewerに置いたItemsControl内でItemPanelをWrapPanelにして、ItemTemplateにTileSampleプロジェクトで書いたものをテンプレートに設定しています。

<Window x:Class="TileSample2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ScrollViewer>
            <ItemsControl ItemsSource="{Binding}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Background="{StaticResource {x:Static SystemColors.HotTrackBrushKey}}" Margin="0,0,10,10" Width="200" Height="200">
                            <Image Source="{Binding Source}" Width="200" Height="200" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" />
                            <TextBlock Text="{Binding Name}" Margin="5,-35,0,0" />
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </ScrollViewer>
    </Grid>
</Window>

こちらは、データに応じてタイルっぽいものを動的に作り出す時や、数が多くて1つ1つ書いてられないときにいいと思います。


今回はやっていませんが、WP7用Silverlightではなく、素のSilverlightでも、同様のことが出来ると思います。ただ、このサンプルはタイルっぽいもので、本物のタイルインターフェースのようにクリックやタッチした部分におうじて動いたりしません。そこらへんは地道に作りこみが必要になりそうです。

WP7ではToolkitに素敵なものがある
WP7にはTiltEffect.IsTiltEnabledという添付プロパティがToolkitで提供されているので、それを使って@ITの記事内では動きのあるタイルを作成しています。
個人的な感想では何故Toolkitは添付プロパティとして、この機能を定義しているのだろう?というのが少し疑問です。Behaviorとして定義していればBlendでぽとぺたで作れたはずなのに。
以上駄文でした。

将来的(Windows 8とか!?)では、これらのUIを作りこむための機能がWPFSilverlightにも提供されることを切に願ってやまない今日この頃でした。