Reputation: 443
I have the following two List Views defined like this :
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Grid.Row="0" ItemsSource="{Binding Categories}"/>
<ListView Grid.Row="1" ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding CategoryName}" Foreground="Red"/>
<TextBlock Text="{Binding ItemName}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
and the ViewModel code :
public class MainWindowViewModel
{
static Random random = new Random();
private static string RandomString(int length)
{
const string pool = "abcdefghijklmnopqrstuvwxyz0123456789";
var chars = Enumerable.Range(0, length)
.Select(x => pool[random.Next(0, pool.Length)]);
return new string(chars.ToArray());
}
public ObservableCollection<string> Categories => new ObservableCollection<string> {"yy","asdf","test1"};
public ObservableCollection<Item> Items
{
get {
var list = new List<Item>();
Enumerable.Range(0, 10).ToList().ForEach(_ => list.Add(
new Item { CategoryName = Categories[random.Next(0, Categories.Count)],
ItemName = RandomString(10) }));
return new ObservableCollection<Item>(list);
}
}
}
public class Item
{
public string CategoryName { get; set; }
public string ItemName { get; set; }
}
I would like to sort my "Items" list view by CategoryName, but following the order that is present in the "Categories" ListView. So, if the order will suffer changes in the "Categories" ListView, I would like to re-sort the "Items" list view,to follow the new order. Also, if there's a WPF built-in mechanism that can handle this kind of situations I would like the use it.
Upvotes: 0
Views: 555
Reputation: 1461
You can implement a custom sort logic by creating a new comparer class which implements IComparer
interface and use it in ListCollectionView
which will be bound to ListView
instead of binding it directly ObservableCollection
.
For example this is your custom comparer which implements sorting logic based on Categories
collection:
public class CategoryComparer : IComparer
{
private readonly List<string> _categories;
public int Compare(object x, object y)
{
Item item1 = x as Item;
Item item2 = y as Item;
int index1 = _categories.IndexOf(item1.CategoryName);
int index2 = _categories.IndexOf(item2.CategoryName);
return index1 - index2;
}
public CategoryComparer(List<string> categories)
{
_categories = categories;
}
}
Then in your ViewModel you will create a new property which will expose Items
collection view and use custom comparer:
private ListCollectionView _itemsCollectionView = null;
public ListCollectionView ItemsCollectionView
{
get
{
_itemsCollectionView = (ListCollectionView)CollectionViewSource.GetDefaultView(Items);
_itemsCollectionView.CustomSort = new CategoryComparer(Categories.ToList());
return _itemsCollectionView;
}
}
Finally you will bind items ListView
to the new collection view:
<ListView Grid.Row="1" ItemsSource="{Binding ItemsCollectionView}">
...
</ListView>
Also if your Categories
collection is dynamic and elements can be added or removed from it you should remember to update ItemsCollectionView
by giving it a new instance of CategoryComparer
and call OnPropertyChanged
in the ViewModel to notify the View about the change.
Upvotes: 1