3

I have to show a list of suggestions to the end user. I want the 1. item on the list to be easiest to read, the 2. item should be a bit smaller and 3. item even smaller.

  • Item at index 0 have to be big and all the text is all black
  • Item at index 1 have to be a bit smaller and all the text is mainly black but with some gray in it
  • Item at index 2 and higher have to be smallish and all the text is grayish

Example

Like this

I am using WPF but have not found a way to do this yet.

Currently I have:

<ListView ItemsSource="{Binding MyList}" Height="auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Transparent">
<ListView.ItemTemplate>
    <DataTemplate>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="75"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Content="{Binding SomeText}"/>
            <Label Grid.Column="1" Content="{Binding MoreText}"/>
        </Grid>
    </DataTemplate>
</ListView.ItemTemplate>

This only generates a flat list were each element is the same size.

I have been looking at AlternationCount + ItemsControl.AlternationIndex, but those will alternate, which is not what I want, I want a special 1. and 2. row, and the rest of the rows are the same.

EDIT SOLUTION Thanks to @Adrian Faciu for the solution.

It looks like this:

<ItemsControl ItemsSource="{Binding MyList}" AlternationCount="1000" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Transparent">
<ItemsControl.Resources>
    <Style TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="Red"></Setter>
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource TemplatedParent}}" Value="0">
                <Setter Property="Foreground" Value="Green"></Setter>
                <Setter Property="FontSize" Value="20" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource TemplatedParent}}" Value="1">
                <Setter Property="Foreground" Value="Yellow"></Setter>
                <Setter Property="FontSize" Value="15" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="75"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Content="{Binding MyText}"/>
            <Label Grid.Column="1" Content="{Binding AnotherText}"/>
        </Grid>
    </DataTemplate>
</ItemsControl.ItemTemplate>

Mr. JWolf
  • 1,375
  • 2
  • 14
  • 33

2 Answers2

3

You're on the right track. You can bind the AlternationCount to the length of your collection then create a style for the default items, and change it for first the rows:

<Style x:Key="differentItemsStyle" TargetType="{x:Type Label}">
    <Setter Property="Foreground" Value="Red"></Setter>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource TemplatedParent}}" Value="0">
            <Setter Property="Foreground" Value="Green"></Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource TemplatedParent}}" Value="1">
            <Setter Property="Foreground" Value="Yellow"></Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

In your example you would have a default style for Option C, D, E which you can overwrite as you wish for Option A and Option B.

Edit In order to make this work for ListBox the binding needs to be changed:

<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex), RelativeSource={RelativeSource AncestorType=ListBoxItem}}" Value="1">
     <Setter Property="Foreground" Value="Yellow"></Setter>
</DataTrigger>

See this answer for more info.

Community
  • 1
  • 1
Adrian Fâciu
  • 12,414
  • 3
  • 53
  • 68
  • I cannot get this to work. They are all green (like they are all AlternationIndex = 0). I have set the Listview to have a AlternationCount="1000" – Mr. JWolf Jun 16 '16 at 10:52
  • It looks like there is an issue with AlternationIndex and ListView. See here: http://stackoverflow.com/questions/19491318/why-does-listbox-alternationindex-always-return-0 – Adrian Fâciu Jun 16 '16 at 11:10
  • Using the link, and using the ItemsController instead of listview worked! : ) – Mr. JWolf Jun 16 '16 at 11:18
1

I think you can add a property to your class and bind it with label's font size.

Xaml:

  <ListView ItemsSource="{Binding MyList}" Height="auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" Background="Transparent">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="75"/>
                        </Grid.ColumnDefinitions>
                        <Label Grid.Column="0" FontSize="{Binding FontSize}" Foreground="{Binding Foreground}" Content="{Binding Name}"/>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

ViewModel:

  MyList = new List<ListItems>();
        MyList.Add(new ListItems() { Name = "Option A", FontSize = 20, Foreground = Brushes.Black });
        MyList.Add(new ListItems() { Name = "Option B", FontSize = 15, Foreground = Brushes.Black });
        MyList.Add(new ListItems() { Name = "Option C", FontSize = 8, Foreground = Brushes.Gray });
        MyList.Add(new ListItems() { Name = "Option D", FontSize = 8, Foreground = Brushes.Gray });
        MyList.Add(new ListItems() { Name = "Option E", FontSize = 8, Foreground = Brushes.Gray });
Justin CI
  • 2,693
  • 1
  • 16
  • 34