Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make the first item in a xaml ListView different?

What it looks like and what I need

This is for a Universal Windows App.

Please can you tell me how to modify only the first element of a ListView? I tried to use a header template, but I couldn't work out how to bind it to the first element in my Steps list.

The only difference between the first element and the other elements is that the shape of the first edge will be straight. The first element will not have this styling: Data="M0,0 10,0 10,30 0,30 10,15"

UPDATE: I've got it working using a template selector (DataTemplateSelector). This means I have to give every item a position number. Any better solutions much appreciated!

Here is my XAML:

<Page
    x:Class="CloserCrumbs.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:CloserCrumbs"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.DataContext>
        <local:SuperVM />
    </Page.DataContext>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView ItemsSource="{Binding Steps}" SelectedItem="{Binding Steps.SelectedItem, Mode=TwoWay}" Height="40" FocusVisualPrimaryThickness="0" FocusVisualSecondaryThickness="0">
            <ListView.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ListView.ItemsPanel>

            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel x:Name="t1" Orientation="Horizontal" Margin="-12" Height="30">

                        <Grid Height="30">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30" >
                                <Path Data="M0,0 10,0 10,30 0,30 10,15" Fill="#d0d0d0" />
                                <Grid>
                                    <Rectangle Fill="#d0d0d0" />
                                    <TextBlock Text="{Binding ShortDescription}" Margin="10,5" VerticalAlignment="Center" Foreground="White" MinWidth="60"/>
                                </Grid>
                                <Path Data="M0,0 10,15 0,30" Fill="#d0d0d0" />
                            </StackPanel>
                        </Grid>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>
like image 710
Gail Foad Avatar asked Jan 30 '23 14:01

Gail Foad


1 Answers

Your best option here to use here is DataTemplateSelector. You can get the Index of the item that you are applying template to and apply specific DataTemplate to it.

So in this case you need 2 DataTemplates. First without the Arrow ( For the first item) and Second for all other items. You can add them in Page.Resources on the Page. So in this case its something like below.

<Page.Resources>
    <DataTemplate x:Name="OtherItem">
        <StackPanel x:Name="t1" Orientation="Horizontal" Margin="-12" Height="30">
            <Grid Height="30">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30" >
                    <Path Data="M0,0 10,0 10,30 0,30 10,15" Fill="#d0d0d0" />
                    <Grid>
                        <Rectangle Fill="#d0d0d0" />
                        <TextBlock Text="{Binding }" Margin="10,5" VerticalAlignment="Center" Foreground="White" MinWidth="60"/>
                    </Grid>
                    <Path Data="M0,0 10,15 0,30" Fill="#d0d0d0" />
                </StackPanel>
            </Grid>
        </StackPanel>
    </DataTemplate>
    <DataTemplate x:Name="FirstItem">
        <StackPanel x:Name="t1" Orientation="Horizontal" Margin="-12" Height="30">
            <Grid Height="30">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30" >
                    <Grid>
                        <Rectangle Fill="#d0d0d0" />
                        <TextBlock Text="{Binding }" Margin="10,5" VerticalAlignment="Center" Foreground="White" MinWidth="60"/>
                    </Grid>
                    <Path Data="M0,0 10,15 0,30" Fill="#d0d0d0" />
                </StackPanel>
            </Grid>
        </StackPanel>
    </DataTemplate>
</Page.Resources>

If you notice the FirstItem DataTemplate does not contain First Path to make it look like a starting arrow.

Below is the code for DataTemplateSelector

public class ItemsDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate FirstItem { get; set; }
    public DataTemplate OtherItem { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
        return (itemsControl.IndexFromContainer(container) == 0) ? FirstItem : OtherItem;
    }
}

In the above code, all i am saying is if the index is 0 then apply FirstItem DataTemplate else OtherItem.

Now change your ListView Like below.

<ListView x:Name="listView" VerticalAlignment="Top">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <ListView.ItemTemplateSelector>
        <local:ItemsDataTemplateSelector FirstItem="{StaticResource FirstItem}" 
                                         OtherItem="{StaticResource OtherItem}" />
    </ListView.ItemTemplateSelector>
</ListView>

Here I am assigning the DataTemplates in Selector to assign FirstItem to First Item in the List and others will get OtherItem Template.

Below is the output from temp data.

enter image description here

Hope this helps

Good Luck.

like image 130
AVK Avatar answered Feb 08 '23 22:02

AVK