I have a DataGrid (on the View) bound to an ObservableCollection (on the ViewModel).
To this ObservableCollection, I am programmatically adding a "magic row", since the selected item will be used to sort another collection elsewhere, and I add this dummy row to "clear" the filtering.
Currently, when the View loads, my magic string always appears on top (since I insert it at index 0
), but as soon as I click on the header to change sorting order, the rows rearrange alphabetically and my magic row is lost in the rubble.
What I want is that the magic row to always appear on top, even when I click on the header to change the sorting order.
ViewModel:
// (...)
public ObservableCollection<FilteringItem> ItemTypes
{
get
{
var result = new ObservableCollection<FilteringItem>(_setups.Select(n => n.ItemType)
.Distinct()
.Select(s => new FilteringItem(s, s))
.OrderBy(v => v.Name));
// Magic Happens Here: adding a "magic" row to remove filtering
// (that is, "allow all") when used by some filtering method elsewhere;
string allString = String.Format("All ({0})", result.Count);
var filteringAll = new FilteringItem(allString, "");
result.Insert(0, filteringAll);
return result;
}
}
// (...)
public class FilteringItem
{
public string Name { get; private set; }
public string Value { get; private set; }
public FilteringItem(string name, string val)
{
Name = name;
Value = val;
}
}
View:
<DataGrid ItemsSource="{Binding ItemTypes}">
<DataGrid.Columns>
<DataGridTextColumn Header="Tipo" Width="*" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
I've got it to work thanks to this blog post.
The "secret" was to intercept the
Sorting
event (settinge.Handled
totrue
), then casting the DataGrid.ItemsSource toListCollectionView
, and then assigning a customIComparer
toListCollectionView.CustomSort
property.Then, while sorting, you somehow identify your fixed row (by null value, in my case), and make it always go to the top (which in turn depends on
ListSortDirection
).