首先,here是上一篇文章,它处理ListBox
来自ObservableCollection<Account>
类的AccountsCollection.cs
帐户的<Window.Resources>
<controller:AccountsWindowController x:Key="AccountsCollection" />
<DataTemplate x:Key="AccountTemplate">
<DockPanel>
<Button Name="EditButton"
DockPanel.Dock="Right"
Margin="3 0 3 0"
VerticalAlignment="Center"
Content="Edit" />
<Button Name="DeleteButton"
DockPanel.Dock="Right"
Margin="3 0 3 0"
VerticalAlignment="Center"
Content="Delete" />
<TextBlock Name="AccountName"
VerticalAlignment="Center"
Text="{Binding Name}"
TextWrapping="NoWrap"
TextTrimming="CharacterEllipsis" />
</DockPanel>
</DataTemplate>
<Window.Resources>
AccountListBox数据。
所以现在我有一个绑定对象AccountsCollection和一个名为AccountTemplate的DataTemplate,用于资源中定义的ListBox:
<ListBox Name="AccountsListBox"
Margin="12,38,12,41"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Accounts,
Source={StaticResource ResourceKey=AccountsCollection}}"
ItemTemplate="{StaticResource ResourceKey=AccountTemplate}"
MouseDoubleClick="AccountsListBox_MouseDoubleClick">
</ListBox>
以下是与LisBox本身相关的代码:
<Window x:Class="Gui.Wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:entities="clr-namespace:Entities.Accounts;assembly=Entities"
xmlns:contollers="clr-namespace:Gui.Wpf.Controllers"
xmlns:converters="clr-namespace:Gui.Wpf.Converters"
xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Title="MainWindow"
Width="525"
Height="350" >
<Window.Resources>
<!-- Main window controller -->
<contollers:MainWindowController
x:Key="MainWindowController" />
<!-- Converter for first letter extraction from the account name -->
<converters:FirstLetterConverter x:Key="FirstLetterConv" />
<!-- View source for the AccountsListBox -->
<CollectionViewSource
x:Key="AccountsView"
Source="{Binding Accounts, Source={StaticResource ResourceKey=MainWindowController}}">
<!-- Sorting -->
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="AccountName" />
</CollectionViewSource.SortDescriptions>
<!-- Grouping -->
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="AccountName" Converter="{StaticResource ResourceKey=FirstLetterConv}" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
<!-- Data template for the type Account -->
<DataTemplate
DataType="{x:Type entities:Account}">
<DockPanel>
<Button
Name="DeleteButton"
DockPanel.Dock="Right"
Margin="3, 1, 3, 1"
VerticalAlignment="Center"
Content="Delete" />
<Button
Name="EditButton"
DockPanel.Dock="Right"
Margin="3, 1, 3, 1"
VerticalAlignment="Center"
Content="Edit" />
<TextBlock
Name="AccountNameTextBlock"
VerticalAlignment="Center"
Text="{Binding AccountName}"
TextWrapping="NoWrap"
TextTrimming="CharacterEllipsis" />
</DockPanel>
</DataTemplate>
<!-- Data template for AccountListBox grouping -->
<DataTemplate x:Key="GroupingHeader">
<TextBlock Text="{Binding Path=Name}" Background="Black" Foreground="White" />
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox
Name="AccountsListBox"
Width="300"
Height="200"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ItemsSource="{Binding Source={StaticResource ResourceKey=AccountsView}}"
HorizontalContentAlignment="Stretch" >
<ListBox.GroupStyle>
<GroupStyle
HeaderTemplate="{StaticResource ResourceKey=GroupingHeader}" />
</ListBox.GroupStyle>
</ListBox>
</Grid>
我希望我的列表能够通过起始字母对所有帐户进行分组并在列表中显示该字母(我也想将一些设计应用于该字母标题)。最终结果应该是这样的:
感谢您的帮助!
更新:以下是成功实施分组的代码。
{{1}}
答案 0 :(得分:15)
您可以使用CollectionViewSource
和转换器来提取第一个字母:
<local:FirstLetterConverter x:Key="firstLetterConverter" />
<CollectionViewSource x:Key="cvs" Source="{Binding Accounts, Source={StaticResource AccountsCollection}}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="AccountName" />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="AccountName" Converter="{StaticResource firstLetterConverter}" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
...
<ItemsControl ItemsSource="{Binding Source={StaticResource cvs}}">
...
转换器:
public class FirstLetterConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string s = value as string;
if (s != null && s.Length > 0)
return s.Substring(0, 1);
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
如果要将样式应用于组,可以使用GroupStyle
属性:
...
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="15" Text="{Binding Path=Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="White" />
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ItemsControl.GroupStyle>
...
答案 1 :(得分:2)
以下是一个非常相似的解决方案示例:
首先,我们需要为您的DataContext
生成更好的收藏 - 这是一个您可以轻松修改的示例 -
public Window1()
{
InitializeComponent();
var s = new[] { "Dave", "Adam", "Jeny", "Nick", "James" };
DataContext = s
.Select(n => n[0])
.Distinct()
.ToDictionary(l => l.ToString(), l => s
.Where(w => w
.StartsWith(l.ToString())));
}
然后我们只需要UI的嵌套ItemsControls -
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Foreground="Red" Text="{Binding Key}" FontSize="12" Margin="5" />
<ItemsControl ItemsSource="{Binding Value}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="5">
<Button Content ="View" Margin="0,0,5,0" />
<Button Content ="Delete" Margin="0,0,5,0" />
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
我们得到了这个: