Search code examples
c#windows-runtimewindows-store-appsmicrosoft-metrowinrt-xaml

Modify last (or individual) item inside GridView


I have a GridView which is populated (through binding) by an ObservableCollection. How do I set it up so that every time a new item is added to the ObservableCollection, the last item in the GridView always has a button on top of it ?

This is the XAML of the GridView's ItemTemplate

<GridView.ItemTemplate>
<DataTemplate>
    <Grid HorizontalAlignment="Left" Width="250" Height="250">
        <Border Background="White">
            <Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
        </Border>
        <StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
            <TextBlock Text="{Binding Title}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
            <TextBlock Text="{Binding DateMade}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
        </StackPanel>
    </Grid>
</DataTemplate>
</GridView.ItemTemplate>

My problem lies in this template being applied for all items in the GridView. I want it so that if it's the last item (and the last item would keep changing every time a new item is added), the above StackPanel should be replaced by another control (say, a button). How would I go about doing this ?


Solution

  • I would extend the template of all elements but hide the additional element and only show it if it's the latest element (specified by some bool property that is set to true on the last element). Something like this.

    <GridView.ItemTemplate>
    <DataTemplate>
        <Grid HorizontalAlignment="Left" Width="250" Height="250">
            <Border Background="White">
                <Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
            </Border>
            <Button Visibility="{Binding IsLastElement, Converter={StaticResource BoolToVisibilityConverter}}"/>
            <StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
                <TextBlock Text="{Binding Title}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
                <TextBlock Text="{Binding DateMade}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
            </StackPanel>
        </Grid>
    </DataTemplate>
    </GridView.ItemTemplate>
    

    I think another option is to change the DataTemplate dynamically using TemplateSelecting event, on changing content of elements, but it would be a little bit more work.

    There might be better solutions though.

    Edit

    Decided to share some links for the aforementioned idea (Which I've used in WinRT) and another one available in WPF

    WPF Based Dynamic DataTemplateSelector - used similar approach in WinRT

    DataTemplateSelector - tried slightly modified example and works fine