Hi,
I'm trying to extend the filtering of a grid - to let the default filtering do its job, and then to display some of the rows hidden by the filtering mechanism. To do this, I'm hooking to the AfterRowFilterChanged event and try to set to "visible" some of the rows which have the IsFilteredOut property set to true. However, I can't find a suitable property/method which would do this.
So my question is: does anybody know how to make visible in an UltraGrid a row which was filtered out by the default filtering mechanism?
Thanks,
Bogdan
Hi Bogdan,
You can do this by handling the FilterRow event. FilterRow fires for each row when a filter is applied. From there, you can use the RowFilteredOut property to override the FilteredOut state determined by the applied filter. In this way, you can exclude specific rows from the filter.
Please try this out and let me know if it works for your requirement.
Hi Mike,
Thanks for the hint, I like that it's a really clean and neat solution!
In my case it almost did the trick, but there is a problem: I need to "un-filter" the rows after all the rows are filtered. The reason for this is that I need to make some rows visible if there are any other rows visible (left visible by the default filtering) which share the same value (an ID) in a hidden column with the rows hidden by the filtering. But this needs to work regardless of the filter's order in the grid - and at FilterRow it looks like the other dependent rows may - or may not - be already processed by the filtering.
So if there is a way to "filter in" rows which were "filtered out" by the grid's default filtering mechanism AFTER the filtering was completed (probably in the AfterRowFilterChanged event?) that would work best for my scenario.
That's going to be tricky.
First, the filtering is performed asynchronously. So in order to achieve what you are describing, you would have to force it to be done synchronously so you go over the rows a second time after the filtering is complete.
The good news is that this can be done. Like so:
private void ultraGrid1_BeforeRowFilterChanged(object sender, BeforeRowFilterChangedEventArgs e) { e.ProcessMode = ProcessMode.Synchronous; }
Second is the problem of somehow un-filtering the row. There's no way to do that directly on the row itself. You can't change the hidden state of a filtered-out row - or rather, you can, but it will have no effect. So what you would have to do is change the RowFilterAction so that the grid doesn't automatically hide filtered out rows and then hide them yourself.
private void ultraGrid1_InitializeLayout(object sender, Infragistics.Win.UltraWinGrid.InitializeLayoutEventArgs e) { UltraGridLayout layout = e.Layout; UltraGridBand band = layout.Bands[0]; UltraGridOverride ov = layout.Override; ov.FilterUIType = FilterUIType.FilterRow; ov.AllowRowFiltering = DefaultableBoolean.True; ov.RowFilterAction = RowFilterAction.AppearancesOnly; }
private void ultraGrid1_FilterRow(object sender, FilterRowEventArgs e) { e.Row.Hidden = e.RowFilteredOut; }
Then you can go back to your original approach of un-hiding the rows you want in AfterRowFilterChanged.
private void ultraGrid1_AfterRowFilterChanged(object sender, AfterRowFilterChangedEventArgs e) { foreach (UltraGridRow row in e.Rows) { // Unhide the row based on some condition if (condition) row.Hidden = false; } }
Thank you for the suggestion - it worked fine, EXCEPT for the case when we sorted the columns - this is the point where things got a bit messy and that's why I went for a different solution.
What worked reasonably fine for me was something like this:
- let the filter do its own filtering
- then filter by the groupped column, starting from what the grid has already filtered
- and then change the existing filters so that they don't override the results of the "groupped by" column filter (by using a regex which matches everything)
The code looks something like this:
// Set custom FILTERINGgrid.AfterRowFilterChanged += gridOnAfterRowFilterChanged;
/// <summary>/// Custom row filtering - makes sure to display al the rows in a group/// All rown in the same group must have the same groupByColumnId/// </summary>private void gridOnAfterRowFilterChanged(object sender, AfterRowFilterChangedEventArgs afterRowFilterChangedEventArgs){ // If an option different than "All" was chosen if (!string.IsNullOrEmpty(afterRowFilterChangedEventArgs.NewColumnFilter.ToString())) { ((UltraGrid)sender).FilterGridByGrouppedColumn(afterRowFilterChangedEventArgs, groupByColumnName); } else { // ResetFilters all filters here }}
/// <summary>/// Custom row filtering - makes sure to display al the rows in a group/// All rown in the same group must have the same groupByColumnId/// </summary>public static void FilterGridByGrouppedColumn(this UltraGrid grid, AfterRowFilterChangedEventArgs afterRowFilterChangedEventArgs, string groupByColumnName){ // Get all rows which were not filtered out by the default filtering // and create a FilterCondition which matches any of the groupByColumnId of the rows not filtered out List<int> visibleIds = afterRowFilterChangedEventArgs.Rows.Where(x => !x.IsFilteredOut). Select(x => (int)x.Cells[groupByColumnName].Value). Distinct(). ToList(); string regexPattern = string.Join("|", visibleIds); FilterCondition myConditions = new FilterCondition { CompareValue = regexPattern, ComparisionOperator = FilterComparisionOperator.Match };
// Clear the filtering on the OrderInvoiceId column grid.Rows.ColumnFilters[groupByColumnName].FilterConditions.Clear();
// Apply the new condition to make the rest of the rown visible grid.Rows.ColumnFilters[groupByColumnName].FilterConditions.Add(myConditions);
// Reset existing filters so that they don't interfere with the groupByColumnName-based filter foreach (FilterCondition currentCondition in grid.Rows.ColumnFilters[afterRowFilterChangedEventArgs.Column.Key].FilterConditions) { currentCondition.CompareValue = ".*"; // Regex for matching anything currentCondition.ComparisionOperator = FilterComparisionOperator.Match; }}
You mentioned that you are fine with the result of the method you describe above. Is there anything further that we can do to assist?
The approach described above works for my requirements - a bit hacky, but does the job, so I'll stick to this solution.
But in case you have other suggestions/alternative approaches, please feel free to post them here - they may be useful for somebody else!
Thanks for the help, Mike & Mike! :)