How to show the top-so-many or bottom-so-many records in a filter in WinForms GridGroupingControl?
Filtering
The QueryRecordMeetsFilterCriteria event has to be handled to get this behavior. A Hashtable is used to handle the values that are to be filtered at the top and bottom. The following sample displays the first 2 and last 2 records in a filter. The Hashtable is filled by using the user defined function, SetPositionFilter().
To perform a filter that restricts the filtered set to a certain number of elements, you have to filter twice. In the first pass, you get the total set of records that satisfies the filter. Then these records are numbered by using an unbound column populated indirectly with the SetPositionFilter method. Once the unbound column is populated with a position index value, you can then apply a second filter to select the first so-many or last so-many records.
C#
//events triggered on the form load. this.gridGroupingControl1.TableDescriptor.QueryValue += new FieldValueEventHandler(unboundField_QueryValue); this.gridGroupingControl1.QueryRecordMeetsFilterCriteria += gridGroupingControl1_QueryRecordMeetsFilterCriteria; this.gridGroupingControl1.FilterBarSelectedItemChanged += gridGroupingControl1_FilterBarSelectedItemChanged; // Gets the filterbar selected text. void gridGroupingControl1_FilterBarSelectedItemChanged(object sender, FilterBarSelectedItemChangedEventArgs e) { if(searchtext != e.SelectedText && searchtext != null) { restrict = false; } SetPositionInFilter(); searchtext = e.SelectedText; } //Gets the checkBox values in a hashtable. private void unboundField_QueryValue(object sender, FieldValueEventArgs e) { if(e.Field.Name == "print") { object value = recordPositions[e.Record.Id]; if(value != null) e.Value = value; } } void gridGroupingControl1_QueryRecordMeetsFilterCriteria(object sender, QueryRecordMeetsFilterCriteriaEventArgs e) { if(restrict) { e.Handled = true; e.Result = (bool)recordPositions[e.Record.Id]; } } //Private method used for filtering Top-so-many and bottom-so-many values private void SetPositionInFilter() { foreach (GridRecord rec in this.gridGroupingControl1.Table.Records) { int pos = -1; if(rec.ParentDetails != null && rec.ParentDetails.FilteredRecords != null) { pos = rec.ParentDetails.FilteredRecords.IndexOf(rec); } // Filters the Top and bottom 2 records. bool val = (pos > -1) && (pos < 2 || pos >= rec.ParentDetails.FilteredRecords.Count - 2); if(recordPositions.ContainsKey(rec.Id)) { recordPositions[rec.Id] = val; } else { recordPositions.Add(rec.Id, val); } } restrict = true; }
VB
'events triggered on the form load. Private Me.gridGroupingControl1.TableDescriptor.QueryValue += New FieldValueEventHandler(AddressOf unboundField_QueryValue) Private Me.gridGroupingControl1.QueryRecordMeetsFilterCriteria += AddressOf gridGroupingControl1_QueryRecordMeetsFilterCriteria Private Me.gridGroupingControl1.FilterBarSelectedItemChanged += AddressOf gridGroupingControl1_FilterBarSelectedItemChanged ‘Gets the filterbar selected text. Private Sub gridGroupingControl1_FilterBarSelectedItemChanged(ByVal sender As Object, ByVal e As FilterBarSelectedItemChangedEventArgs) If searchtext <> e.SelectedText AndAlso searchtext IsNot Nothing Then restrict = False SetPositionInFilter() searchtext = e.SelectedText End Sub 'Gets the checkBox values in a hashtable. Private Sub unboundField_QueryValue(ByVal sender As Object, ByVal e As FieldValueEventArgs) If e.Field.Name = "print" Then Dim value As Object = recordPositions(e.Record.Id) If value IsNot Nothing Then e.Value = value End If End If End Sub Private Sub gridGroupingControl1_QueryRecordMeetsFilterCriteria(ByVal sender As Object, ByVal e As QueryRecordMeetsFilterCriteriaEventArgs) If restrict Then e.Handled = True e.Result = CBool(recordPositions(e.Record.Id)) End If End Sub 'Private method used for filtering Top-so-many and bottom-so-many values Private Sub SetPositionInFilter() For Each rec As GridRecord In Me.gridGroupingControl1.Table.Records Dim pos As Integer = -1 If rec.ParentDetails IsNot Nothing AndAlso rec.ParentDetails.FilteredRecords IsNot Nothing Then pos = rec.ParentDetails.FilteredRecords.IndexOf(rec) End If ‘Filtering Top and bottom 2 records. Dim val As Boolean = (pos > -1) AndAlso (pos < 2 OrElse pos >= rec.ParentDetails.FilteredRecords.Count - 2) If recordPositions.ContainsKey(rec.Id) Then recordPositions(rec.Id) = val Else recordPositions.Add(rec.Id, val) End If Next rec restrict = True End Sub
Figure 1: Top and bottom 2 records value set as true on filtering first time
Figure 2: Top and bottom 2 values filtered on second time filtering applied to the same value
Samples:
C#: UnboundFilter-C#
VB: UnboundFilter-VB