Hi Uttkarsh,
The Short Version
I realize I didn’t give you the full scope of the issue in my previous messages. Ultimately, I have a Dictionary<string, object> where each key represents a column name and the value array represents all the values for that column. I need to display this dynamically in a FlexGrid with built-in filtering/sorting enabled. In addition to the built-in grid filtering, I also have two custom spatial/selection filters applied from my ViewModel.
The Long Version
I was testing your idea along with several other approaches and kept running into roadblocks. I should have presented you with the full picture initially because our use case is a bit unique.
This refactor was prompted by an upgrade from .NET Framework to .NET 9. We updated our C1 packages from v4.6.20251.877 to v9.0.20251.1133. We have a backend system that returns a Dictionary<string, object?> for a given dataset. Historically, we constructed a DataTable from this dictionary specifically so we could define the DataType for each column. Without specifying the data types, the FlexGrid misses out on the built-in sorting and filtering options (which was the issue I originally posted about).
We ultimately need 3 forms of filtering to work in unison in our FlexGrid:
- Built-in Grid Filtering: The standard value/condition filtering provided by the FlexGrid UI.
- Filter by Extent: Each row has associated spatial Geometry. We have a button that filters the grid to only show rows whose geometry falls within a specific map extent.
- Filter by Selected: The grid’s row selection needs to be synced with geometry selection on our map. If the user toggles “Filter by Selected,” the grid should only display rows that are currently selected on the map.
In our old .NET Framework setup, we had a C1FlexGrid bound to a DataView. This DataView contained all the fields from our dictionary, plus 3 additional fields: Geometry, IsVisible (set to true/false based on the map extent), and IsSelected (a pseudo two-way binding between the UI row selection and map selection). We handled the filtering by binding C1FlexGridFilterService.FlexGridFilter on the grid to a C1FlexGridFilter property in our ViewModel. We didn’t love this approach because it forced a WPF UI dependency into our ViewModel, but it worked.
After updating to v9.0.20251.1133, the C1FlexGridFilter class seems to have been removed so a refactor we needed to get the tool working again. The documentation suggested using a C1DataCollection. I had high hopes for this because the filtering/grouping architecture seems ideal for our setup, but I just can’t get it working with our data. Here is what I’ve tried so far:
- C1DataCollection
I created an AttributeRow class with a Dictionary<string, object?> Values property, an IsSelected boolean, and a Geometry property. In my XAML, I disabled AutoGenerateColumns. I listened to the ItemsSourceChanged event, grabbed the first row, and manually built the columns from the dictionary keys using this code:
foreach (var kvp in firstRow.Values)
{
flexGrid.Columns.Add(new GridColumn() { Header = kvp.Key, Binding = $"Values[{kvp.Key}]" });
}
I could successfully apply my custom “Filter by Selected” and “Filter by Extent” logic by passing FilterPredicateExpressions into FilterAsync(). However, because the columns were bound to dictionary values, the FlexGrid couldn’t determine the underlying DataType. Consequently, I lost the ability to sort columns or use the FlexGrid’s built-in column filters.
-
C1DataCollection
I tried a very similar manual column-generation setup using DataRowView instead of my custom class.
However, I hit the exact same issue where sorting and built-in filtering were disabled. I’m assuming this limitation is directly tied to creating the GridColumns manually rather than letting AutoGenerateColumns inspect a strongly typed schema?
-
C1BindingListDataCollection with a DataTable
Lastly, I tried reverting to our original DataTable setup, but instead passing dataTable.DefaultView into a C1BindingListDataCollection. I re-enabled AutoGenerateColumns, and finally, the native sorting and grid filtering worked again! To handle the custom map filters, I added the Geometry, IsVisible, and IsSelected columns back into the DataTable. My plan for the “Filter by Extent” option was to set the IsVisible boolean in the table based on my own spatial queries using the Row’s Geometry and then use a FilterOperationExpression on the IsVisible field. Similarly, for the IsSelected filtering, I would pass the SelectedItems collection to my ViewModel, but the grid seems to return a dynamic ItemWrapper class rather than the DataRowView itself. The issue with this setup is that it seems when I would modify one of the row values (IsVisible or IsSelected) it would reset my row selection. Maybe the ItemWrapper class sets its own bindings? These additional updates to the grid/UI were causing a lot of issues with maintaining that IsSelected value in-sync with the UI. I struggled to make this work, even though it felt like the closest solution.
All of this is to say: I fear I have greatly overcomplicated this migration.
To summarize: I have dynamic column data (Dictionary<string, object?>) that I need to display in a FlexGrid. I need native UI sorting/filtering, alongside the ability to apply two custom external filters (Extent and Selection) from my ViewModel.
What is the recommended architectural approach for this in the .NET 9 FlexGrid? Any and all advice is greatly appreciated!