如何让 WPF 中 ListBox 列表项前自动加上序号
有时候我们可以希望在 ListBox 列表项前面加上序号,这样看起来更清楚,还可以配合使用快捷键等。
希望达到如下图的效果:
显然我们可以通过修改 ListBox 的模板来实现,只要在 Item 中加上数字这一项即可,利用 MultiBinding 和 IMultiValueConverter 即可实现。
示例
首先,我们创建一个 Person 类:
public class Person { public string Name { get; set; } }
然后创建一个 Converter,继承自 IMultiValueConverter:
注意第 5~6 行,使用了 dynamic 类型,所以必须保证 list 有 IndexOf 这个扩展方法,IEnumerable<T> 是不行的。
public class IndexConverter : IMultiValueConverter { public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture) { dynamic item = values[0]; dynamic list = values[1]; return list.IndexOf(person) + 1; } public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotImplementedException (); } }
XAML 如下:
关键在于 17~20 行,分别绑定了单项数据和 ListBox 本身。
<Window x:Class="ListBoxIndex.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:listBoxIndex ="clr-namespace:ListBoxIndex" Title="MainWindow" Height ="350" Width="525"> <Window.Resources> <listBoxIndex: IndexConverter x:Key="IndexConverter"/> </Window.Resources> <StackPanel > <Button Name="BtnDemo" Content="Add" Click="BtnDemo_OnClick"/> <ListBox Name="LbxDemo"> <ListBox.ItemTemplate> <DataTemplate DataType="listBoxIndex:Person"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding}"> <TextBlock.DataContext> <MultiBinding Converter="{StaticResource IndexConverter }"> <Binding/> <Binding ElementName="LbxDemo" Path="ItemsSource"/> </MultiBinding> </TextBlock.DataContext> </TextBlock> <TextBlock Text="{Binding Name}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel > </Window>
代码如下:
namespace ListBoxIndex { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { readonly ObservableCollection <Person> _personList = new ObservableCollection <Person>(); public MainWindow() { InitializeComponent(); InitSource(); } private void InitSource() { _personList.Add(new Person() {Name = "刘备" }); _personList.Add(new Person() {Name = "关羽" }); LbxDemo.ItemsSource = _personList; } private void BtnDemo_OnClick( object sender, RoutedEventArgs e) { _personList.Add(new Person() {Name = "张飞" }); LbxDemo.ItemsSource = _personList; } } }