I used the interited DataGrid from kat to create a Behavior for the WPF DataGrid.
The behavior saves the initial SortDescriptions and applies them on every change of ItemsSource
.
You can also provide a IEnumerable<SortDescription>
which will cause a resort on every change.
Behavior
public class DataGridSortBehavior : Behavior<DataGrid>
{
public static readonly DependencyProperty SortDescriptionsProperty = DependencyProperty.Register(
"SortDescriptions",
typeof (IEnumerable<SortDescription>),
typeof (DataGridSortBehavior),
new FrameworkPropertyMetadata(null, SortDescriptionsPropertyChanged));
/// <summary>
/// Storage for initial SortDescriptions
/// </summary>
private IEnumerable<SortDescription> _internalSortDescriptions;
/// <summary>
/// Property for providing a Binding to Custom SortDescriptions
/// </summary>
public IEnumerable<SortDescription> SortDescriptions
{
get { return (IEnumerable<SortDescription>) GetValue(SortDescriptionsProperty); }
set { SetValue(SortDescriptionsProperty, value); }
}
protected override void OnAttached()
{
var dpd = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof (DataGrid));
if (dpd != null)
{
dpd.AddValueChanged(AssociatedObject, OnItemsSourceChanged);
}
}
protected override void OnDetaching()
{
var dpd = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof (DataGrid));
if (dpd != null)
{
dpd.RemoveValueChanged(AssociatedObject, OnItemsSourceChanged);
}
}
private static void SortDescriptionsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is DataGridSortBehavior)
{
((DataGridSortBehavior) d).OnItemsSourceChanged(d, EventArgs.Empty);
}
}
public void OnItemsSourceChanged(object sender, EventArgs eventArgs)
{
// save description only on first call, SortDescriptions are always empty after ItemsSourceChanged
if (_internalSortDescriptions == null)
{
// save initial sort descriptions
var cv = (AssociatedObject.ItemsSource as ICollectionView);
if (cv != null)
{
_internalSortDescriptions = cv.SortDescriptions.ToList();
}
}
else
{
// do not resort first time - DataGrid works as expected this time
var sort = SortDescriptions ?? _internalSortDescriptions;
if (sort != null)
{
sort = sort.ToList();
var collectionView = AssociatedObject.ItemsSource as ICollectionView;
if (collectionView != null)
{
using (collectionView.DeferRefresh())
{
collectionView.SortDescriptions.Clear();
foreach (var sorter in sort)
{
collectionView.SortDescriptions.Add(sorter);
}
}
}
}
}
}
}
XAML with optional SortDescriptions parameter
<DataGrid ItemsSource="{Binding View}" >
<i:Interaction.Behaviors>
<commons:DataGridSortBehavior SortDescriptions="{Binding SortDescriptions}"/>
</i:Interaction.Behaviors>
</DataGrid>
ViewModel ICollectionView Setup
View = CollectionViewSource.GetDefaultView(_collection);
View.SortDescriptions.Add(new SortDescription("Sequence", ListSortDirection.Ascending));
Optional: ViewModel Property for providing changable SortDescriptions
public IEnumerable<SortDescription> SortDescriptions
{
get
{
return new List<SortDescription> {new SortDescription("Sequence", ListSortDirection.Ascending)};
}
}