しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

リスト項目のデザインを交互に切り替える

Windows ランタイムアプリにはリスト項目の背景色を交互に切り替えるオプションはありませんが、ItemTemplateSelector を利用すればそういったことは実現できます

なにはなくとも ItemTemplateSelector

/// <summary>
/// 交互にテンプレートを切り替えるテンプレートセレクタ
/// </summary>
public class AlternativeTemplateSelector : DataTemplateSelector
{
    /// <summary>
    /// 奇数行のテンプレート
    /// </summary>
    public DataTemplate NormalTemplate { get; set; }

    /// <summary>
    /// 偶数行のテンプレート
    /// </summary>
    public DataTemplate AlternateTemplate { get; set; }

    /// <summary>
    /// アイテムに対応する DataTemplate を返却します
    /// </summary>
    /// <param name="item">アイテム</param>
    /// <returns>DataTemplate</returns>
    protected override DataTemplate SelectTemplateCore(object item)
    {
        return base.SelectTemplateCore(item, null);
    }

    /// <summary>
    /// アイテムに対応する DataTemplate を返却します
    /// </summary>
    /// <param name="item">アイテム</param>
    /// <param name="container">コンテナ</param>
    /// <returns>DataTemplate</returns>
    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        var vm = item as ItemContainerViewModel;
        if (vm == null)
        {
            return null;
        }

        int index = 0;
        if (int.TryParse(vm.UniqueId, out index))
        {
            // 奇数行の場合
            if(index % 2 == 1)
            {
                return this.AlternateTemplate;
            }
        }

        // 奇数行以外の場合
        return this.NormalTemplate;
    }
}

UniqueId を int 型に Parse して奇数行、偶数行でテンプレートを切り替えているだけです

ViewModel の生成の部分は次のような感じ

/// <summary>
/// 画面に遷移したときの処理
/// </summary>
/// <param name="navigationParameter">遷移パラメータ</param>
/// <param name="navigationMode">遷移モード</param>
/// <param name="viewModelState">画面状態データ</param>
public override void OnNavigatedTo(object navigationParameter, NavigationMode navigationMode, Dictionary<string, object> viewModelState)
{
    base.OnNavigatedTo(navigationParameter, navigationMode, viewModelState);

    if (this.ViewModel.Items.Count > 0)
    {
        return;
    }

    int i = 0;
    foreach (var photo in App.AppSettings.Settings.Items)
    {
        var item = PhotoViewModel.Convert(photo);

        this.ViewModel.Items.Add(
            new ItemContainerViewModel()
            {
                UniqueId = i.ToString(),
                ContentId = item.UniqueId,
                Content = item,
                ColumnSpan = 1,
                RowSpan = 1,
                IsActive = true,
            });

        i++;
    }
}

UniquieId に連番を設定しています

あとは画面側の XAML

<Page.Resources>
    <!--  このページで表示されるアイテムのコレクション  -->
    <CollectionViewSource x:Name="itemsViewSource" Source="{Binding Items}" />

    <selector:AlternativeTemplateSelector x:Key="GridViewItemTemplateSelector">
        <!-- 奇数行のテンプレート -->
        <selector:AlternativeTemplateSelector.NormalTemplate>
            <DataTemplate>
                <Grid Background="#FF3D3D3D">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Image HorizontalAlignment="Center"
                            VerticalAlignment="Top"
                            Source="{Binding Content.ImageUri}"
                            Stretch="UniformToFill" />
                    <TextBlock Grid.Column="1"
                                Margin="20,10"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Center"
                                FontSize="24"
                                Foreground="White"
                                Text="{Binding Content.Title}" />
                </Grid>
            </DataTemplate>
        </selector:AlternativeTemplateSelector.NormalTemplate>
        <!-- 偶数行のテンプレート -->
        <selector:AlternativeTemplateSelector.AlternateTemplate>
            <DataTemplate>
                <Grid Background="Black">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="80" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <Image HorizontalAlignment="Center"
                            VerticalAlignment="Top"
                            Source="{Binding Content.ImageUri}"
                            Stretch="UniformToFill" />
                    <TextBlock Grid.Column="1"
                                Margin="20,10"
                                HorizontalAlignment="Left"
                                VerticalAlignment="Center"
                                FontSize="24"
                                Foreground="White"
                                Text="{Binding Content.Title}" />
                </Grid>
            </DataTemplate>
        </selector:AlternativeTemplateSelector.AlternateTemplate>
    </selector:AlternativeTemplateSelector>

</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <Grid.ChildrenTransitions>
            <TransitionCollection>
                <EntranceThemeTransition />
            </TransitionCollection>
        </Grid.ChildrenTransitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="140" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <!--  交互に背景色が切り替わるグリッド  -->
        <GridView x:Name="itemGridView"
            Grid.RowSpan="2"
            IsItemClickEnabled="True"
            IsSwipeEnabled="false"
            ItemTemplateSelector="{StaticResource GridViewItemTemplateSelector}"
            ItemsSource="{Binding Source={StaticResource itemsViewSource}}"
            Padding="116,186,116,0"
            SelectionMode="Multiple">
            <GridView.ItemsPanel>
                <ItemsPanelTemplate>
                    <VariableSizedWrapGrid ItemHeight="120"
                                    ItemWidth="500"
                                    Orientation="Vertical" />
                </ItemsPanelTemplate>
            </GridView.ItemsPanel>
            <GridView.ItemContainerStyle>
                <Style TargetType="GridViewItem">
                    <Setter Property="Margin" Value="0,0,20,20" />
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                    <Setter Property="VerticalContentAlignment" Value="Stretch" />
                </Style>
            </GridView.ItemContainerStyle>
        </GridView>

        ~ 中略 ~

    </Grid>
</Grid>

するとこの通り

f:id:matatabi_ux:20140705101451p:plain

ItemTemplateSelector を利用すれば背景色だけでなく大きさなどその他のデザインも柔軟に変更できるので応用が利きますね