The GroupByEvaluator needs to be logically consistent with the sorted order of the DataRecords which can be controlled via the FieldSettings.GroupByComparer or FieldSettings.SortComparer properties.
Refer to the About Grouping topic in the Developer's Guide for an explanation of how this property is used.
Imports Infragistics.Windows.DataPresenter Partial Public Class Window1 Inherits System.Windows.Window Public Sub New() InitializeComponent() Me.InitializeGroupByGrid() End Sub Private Sub InitializeGroupByGrid() ' example data... Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(10)) Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(5)) Me.xamDataGrid1.DataItems.Add(DateTime.Today) Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(-2)) Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(-5)) Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddMonths(-1)) Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddMonths(-1).AddDays(-5)) Me.xamDataGrid1.DataItems.Add(DateTime.Today.AddMonths(-1).AddDays(-2)) ' create a field layout that matches the data structure ' in this case we're just binding to simple types like datetime ' so the field name will be value. Dim fl As FieldLayout = New FieldLayout() Dim field As Field = New Field() field.Name = "Value" ' use our custom groupby evaluator field.Settings.GroupByEvaluator = New CustomDateTimeEvaluator() ' add the fields to the field layout and the field layout to the grid fl.Fields.Add(field) Me.xamDataGrid1.FieldLayouts.Add(fl) ' show the group by area Me.xamDataGrid1.GroupByArea.IsExpanded = True ' group by the data field Dim fsd As FieldSortDescription = New FieldSortDescription() fsd.Field = field fsd.Direction = System.ComponentModel.ListSortDirection.Descending fsd.IsGroupBy = True fl.SortedFields.ClearNonGroupByFields() fl.SortedFields.Add(fsd) End Sub End Class Friend Class CustomDateTimeEvaluator Implements IGroupByEvaluator Private Const PastDue As String = "Past Due" Private Const DueToday As String = "Due Today" Private Const NotDueYet As String = "Not Due Yet" Public Function DoesGroupContainRecord(ByVal groupByRecord As GroupByRecord, ByVal record As DataRecord) As Boolean Implements IGroupByEvaluator.DoesGroupContainRecord Dim cellValue As Object = record.GetCellValue(groupByRecord.GroupByField) Dim desc As String = groupByRecord.Description ' handle null values specially If cellValue Is Nothing Or TypeOf cellValue Is DBNull Then Return desc = PastDue End If ' if the value is not a date time, just group them together If TypeOf cellValue Is DateTime = False Then Return True End If Return desc = GetDateLabel(CType(cellValue, DateTime)) End Function Public Function GetGroupByValue(ByVal groupByRecord As GroupByRecord, ByVal record As DataRecord) As Object Implements IGroupByEvaluator.GetGroupByValue Dim cellValue As Object = record.GetCellValue(groupByRecord.GroupByField) Dim desc As String = String.Empty Dim targetDate As DateTime = DateTime.MinValue If cellValue Is Nothing Or TypeOf cellValue Is DBNull Then desc = "None" ElseIf TypeOf cellValue Is DateTime Then targetDate = CType(cellValue, DateTime) desc = GetDateLabel(targetDate) End If groupByRecord.Description = desc Return targetDate End Function Public ReadOnly Property SortComparer() As System.Collections.IComparer Implements IGroupByEvaluator.SortComparer Get Return Nothing End Get End Property Private Function GetDateLabel(ByVal dt As DateTime) As String Dim comparison As Integer = dt.Date.CompareTo(DateTime.Today.Date) Dim desc As String If comparison < 0 Then desc = "Past Due" ElseIf comparison = 0 Then desc = "Due Today" Else desc = "Not Due Yet" End If Return desc End Function End Class
using Infragistics.Windows.DataPresenter; /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window1 : System.Windows.Window { public Window1() { InitializeComponent(); this.InitializeGroupByGrid(); } private void InitializeGroupByGrid() { // example data... this.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(10)); this.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(5)); this.xamDataGrid1.DataItems.Add(DateTime.Today); this.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(-2)); this.xamDataGrid1.DataItems.Add(DateTime.Today.AddDays(-5)); this.xamDataGrid1.DataItems.Add(DateTime.Today.AddMonths(-1)); this.xamDataGrid1.DataItems.Add(DateTime.Today.AddMonths(-1).AddDays(-5)); this.xamDataGrid1.DataItems.Add(DateTime.Today.AddMonths(-1).AddDays(-2)); // create a field layout that matches the data structure // in this case we're just binding to simple types like datetime // so the field name will be value. FieldLayout fl = new FieldLayout(); Field field = new Field(); field.Name = "Value"; // use our custom groupby evaluator field.Settings.GroupByEvaluator = new CustomDateTimeEvaluator(); // add the fields to the field layout and the field layout to the grid fl.Fields.Add(field); this.xamDataGrid1.FieldLayouts.Add(fl); // show the group by area this.xamDataGrid1.GroupByArea.IsExpanded = true; // group by the data field FieldSortDescription fsd = new FieldSortDescription(); fsd.Field = field; fsd.Direction = System.ComponentModel.ListSortDirection.Descending; fsd.IsGroupBy = true; fl.SortedFields.ClearNonGroupByFields(); fl.SortedFields.Add(fsd); } } internal class CustomDateTimeEvaluator : IGroupByEvaluator { private const string PastDue = "Past Due"; private const string DueToday = "Due Today"; private const string NotDueYet = "Not Due Yet"; public bool DoesGroupContainRecord(GroupByRecord groupByRecord, DataRecord record) { object cellValue = record.GetCellValue(groupByRecord.GroupByField); string desc = groupByRecord.Description; // handle null values specially if (cellValue == null || cellValue is DBNull) return desc == PastDue; // if the value is not a date time, just group them together if (cellValue is DateTime == false) return true; return desc == GetDateLabel((DateTime)cellValue); } public object GetGroupByValue(GroupByRecord groupByRecord, DataRecord record) { object cellValue = record.GetCellValue(groupByRecord.GroupByField); string desc = string.Empty; DateTime targetDate = DateTime.MinValue; if (cellValue == null || cellValue is DBNull) { desc = "None"; } else if (cellValue is DateTime) { targetDate = (DateTime)cellValue; desc = GetDateLabel(targetDate); } groupByRecord.Description = desc; return targetDate; } public System.Collections.IComparer SortComparer { // return null to use the default comparer get { return null; } } private string GetDateLabel(DateTime date) { int comparison = date.Date.CompareTo(DateTime.Today.Date); string desc; if (comparison < 0) desc = "Past Due"; else if (comparison == 0) desc = "Due Today"; else desc = "Not Due Yet"; return desc; } }
Target Platforms: Windows 10, Windows 8.1, Windows 8, Windows 7, Windows Server 2012, Windows Vista SP1 or later, Windows XP SP3, Windows Server 2008 (Server Core not supported), Windows Server 2008 R2 (Server Core supported with SP1 or later), Windows Server 2003 SP2