How to display row numbers in a ListView?
Solution 1:
I think you have the elegant solution, but this works.
XAML:
<ListView Name="listviewNames">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn
Header="Number"
DisplayMemberBinding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}},
Converter={StaticResource IndexConverter}}" />
<GridViewColumn
Header="Name"
DisplayMemberBinding="{Binding Path=Name}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
ValueConverter:
public class IndexConverter : IValueConverter
{
public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
{
ListViewItem item = (ListViewItem) value;
ListView listView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
int index = listView.ItemContainerGenerator.IndexFromContainer(item);
return index.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Solution 2:
If you have a dynamic list where items are added, deleted or moved, you can still use this very nice solution and simply let the currentview of your listview refresh itself after the changements in your source list are done. This code sample removes the current item directly in the data source list "mySourceList" (which is in my case an ObservableCollection) and finally updates the line numbers to correct values .
ICollectionView cv = CollectionViewSource.GetDefaultView(listviewNames.ItemsSource);
if (listviewNames.Items.CurrentItem != null)
{
mySourceList.RemoveAt(cv.CurrentPosition);
cv.Refresh();
}
Solution 3:
First you need to set the AlternationCount
to items count
+1, for instance:
<ListView AlternationCount="1000" .... />
Then AlternationIndex
will show the real index, even during the scrolling:
<GridViewColumn
Header="#" Width="30"
DisplayMemberBinding="{Binding (ItemsControl.AlternationIndex),
RelativeSource={RelativeSource AncestorType=ListViewItem}}" />
Solution 4:
This will work like a charm, I don't know about performance, Still we can give it a try
Create a Multi Value Converter
public class NumberingConvertor : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (values != null && values.Any() && values[0] != null && values[1] != null)
{
//return (char)(((List<object>)values[1]).IndexOf(values[0]) + 97);
return ((List<object>)values[1]).IndexOf(values[0]) + 1;
}
return "0";
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
}
and your Xaml like this
<ItemsControl ItemsSource="{Binding ListObjType}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label>
<MultiBinding Converter="{StaticResource NumberingConvertor}">
<Binding Path="" />
<Binding Path="ItemsSource"
RelativeSource="{RelativeSource AncestorType=ItemsControl}" />
</MultiBinding>
</Label>
<TextBlock Text="{Binding }" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Idea is to send Object and list both to the converter and let converter decide the number. You can modify converter to display ordered list.