我的设置
我正在使用ListCollectionView
对ListBox
中的数据进行排序和分组。
我的模特:
public class Game
{
public string Name
{
get; set;
}
public List<string> Categories
{
get; set;
}
}
我想做的是按Categories
进行分组,其中视图中的组按字母顺序排序。并按Name
按组对所有项目进行排序。
此外,我希望在视图底部有代表null或空类别的组。
例如:
Category1
Name2
Name3
Category2
Name2
Name3
Name4
Name5
Null/Empty
Name1
Name6
由于Categories
为List<string>
,表示任何项目都可以在一个或多个组中,或者不包含任何项目。
问题
我不知道如何正确实现类别的排序。我知道我必须先设置多个SortDescriptions
,然后按Categories
排序,然后按Name
秒排序,但我该如何做?
WPF默认情况下不知道如何对List<string>
组进行排序,所以我尝试将其更改为自定义列表,该列表实现IComparable
,但是无法处理空值(如果不能调用比较器,则无法调用其中一个对象是null)。
我也尝试在我的观点上实现CustomSort
,但我认为以这种方式处理我的情况并非不可能(其中一个项目可以在多个组中)。
更新完整的代码
结果是:
Null
Game1
Category2
Game2
Game3
Category1
Game3
Game4
我希望它是:
Category1
Game3
Game4
Category2
Game2
Game3
Null
Game1
代码:
public partial class MainWindow : Window
{
public class Game
{
public string Name
{
get; set;
}
public List<string> Categories
{
get; set;
}
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var games = new List<Game>()
{
new Game()
{
Name = "Game1",
},
new Game()
{
Name = "Game2",
Categories = new List<string>() { "Category2" }
},
new Game()
{
Name = "Game3",
Categories = new List<string>() { "Category1", "Category2" }
},
new Game()
{
Name = "Game4",
Categories = new List<string>() { "Category1" }
}
};
var view = (ListCollectionView)CollectionViewSource.GetDefaultView(games);
view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
view.GroupDescriptions.Add(new PropertyGroupDescription("Categories"));
MainList.ItemsSource = view;
}
}
和XAML:
<Window x:Class="grouping.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:grouping"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<ListBox Name="MainList">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Header="{Binding Name, TargetNullValue='Null'}" IsExpanded="True">
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
答案 0 :(得分:2)
基本上,您的数据格式不适合在WPF中显示。您希望相同的条目出现在多个位置(每组一次),而典型的itemssource将显示每个项目一次,无论排序细节如何。
因此,您应该将数据转换为WPF更自然的表示形式。例如(使用自定义比较器进行排序):
public class GameListEntry : IComparable<GameListEntry>
{
public string Name { get; set; }
public string Category { get; set; }
public int CompareTo(GameListEntry other)
{
if (Category == other.Category)
{
return 0;
}
if (Category == "Null / Empty")
{
return 1;
}
if (other.Category == "Null / Empty")
{
return -1;
}
return Category.CompareTo(other.Category);
}
}
List<Game> games = ...;
var listedGameEntries = games.SelectMany(x => x.Categories.DefaultIfEmpty().Select(c => new GameListEntry { Name = x.Name, Category = string.IsNullOrEmpty(c) ? "Null / Empty" : c }));
var groupedGames = listedGameEntries.GroupBy(x => x.Category);
CompareTo可能需要增强或替换为不同的机制,以便按照应有的方式进行排序和分组。
编辑:添加了DefaultIfEmpty()
,以确保即使有一个空的类别列表也可以输入一个条目。