编号列表框

我有一个已排序的列表框,需要显示每个项目的行号。 在这个演示中,我有一个带有Name字符串属性的Person类。 列表框显示按名称排序的人员列表。 如何在列表框的datatemplate中添加行号???

XAML:

         

代码背后:

 using System; using System.Collections.ObjectModel; using System.Windows.Data; using System.Windows; using System.ComponentModel; namespace NumberedListBox { public partial class Window1 : Window { public Window1() { InitializeComponent(); Persons = new ObservableCollection(); Persons.Add(new Person() { Name = "Sally"}); Persons.Add(new Person() { Name = "Bob" }); Persons.Add(new Person() { Name = "Joe" }); Persons.Add(new Person() { Name = "Mary" }); PersonsListCollectionView = new ListCollectionView(Persons); PersonsListCollectionView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); DataContext = this; } public ObservableCollection Persons { get; private set; } public ListCollectionView PersonsListCollectionView { get; private set; } } public class Person { public string Name { get; set; } } } 

这应该让你开始:

http://weblogs.asp.net/hpreishuber/archive/2008/11/18/rownumber-in-silverlight-datagrid-or-listbox.aspx

它说它适用于Silverlight,但我不明白为什么它不能用于WPF。 基本上,您将TextBlock绑定到数据并使用自定义值转换器输出当前项的编号。

最后! 如果找到一种更优雅的方式,也可能具有更好的性能。 (另请参阅添加时访问ItemsControl项 )

我们为此“滥用”属性ItemsControl.AlternateIndex 。 最初它旨在以不同方式处理ListBox每个其他行。 (请参阅http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.alternationcount.aspx )

1.将AlternatingCount设置为ListBox中包含的项目数

  

2.绑定到AlternatingIndex您的DataTemplate

    ...   

所以这没有转换器,额外的CollectionViewSource ,最重要的是没有暴力搜索源集合。

David Brown的链接中的想法是使用一个有效的值转换器。 以下是完整的工作样本。 列表框包含行号,可以按名称和年龄进行排序。

XAML:

                              

代码背后:

 using System; using System.Collections.ObjectModel; using System.Windows.Data; using System.Windows; using System.ComponentModel; using System.Windows.Controls; namespace NumberedListBox { public partial class Window1 : Window { public Window1() { InitializeComponent(); Persons = new ObservableCollection(); Persons.Add(new Person() { Name = "Sally", Age = 34 }); Persons.Add(new Person() { Name = "Bob", Age = 18 }); Persons.Add(new Person() { Name = "Joe", Age = 72 }); Persons.Add(new Person() { Name = "Mary", Age = 12 }); CollectionViewSource view = FindResource("sortedPersonList") as CollectionViewSource; view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); DataContext = this; } public ObservableCollection Persons { get; private set; } private void SortButton_Click(object sender, RoutedEventArgs e) { Button button = sender as Button; string sortProperty = button.Tag as string; CollectionViewSource view = FindResource("sortedPersonList") as CollectionViewSource; view.SortDescriptions.Clear(); view.SortDescriptions.Add(new SortDescription(sortProperty, ListSortDirection.Ascending)); view.View.Refresh(); } } public class Person { public string Name { get; set; } public int Age { get; set; } } } 

价值转换器:

 using System; using System.Windows.Data; namespace NumberedListBox { public class RowNumberConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { CollectionViewSource collectionViewSource = parameter as CollectionViewSource; int counter = 1; foreach (object item in collectionViewSource.View) { if (item == value) { return counter.ToString(); } counter++; } return string.Empty; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } } } 

又一个答案。 我尝试了上面的,它在WPF( AlternationCount解决方案)中工作,但我需要Silverlight的代码,所以我做了以下。 这比其他蛮力方法更优雅。

                  

在后面

  using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; namespace RowNumber { public class ListItemIndexConverter : IValueConverter { // Value should be ListBoxItem that contains the current record. RelativeSource={RelativeSource AncestorType=ListBoxItem} public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var lbi = (ListBoxItem)value; var listBox = lbi.GetVisualAncestors().OfType().First(); var index = listBox.ItemContainerGenerator.IndexFromContainer(lbi); // One based. Remove +1 for Zero based array. return index + 1; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public partial class MainPage : UserControl { public MainPage() { // Required to initialize variables InitializeComponent(); } public List Test { get { return new[] { "Foo", "Bar", "Baz" }.ToList(); } } } } 

这是Silverlight 5中新增的,引入了RelativeSource绑定。

为什么不绑定到列表框的count属性。