Skip to content

DataGrid: Bug - Incorrect DataSource Change Detection in Grid Component Due to Boxing #2515

@StevenTCramer

Description

@StevenTCramer

🐛 Bug Report

Title

Bug: Incorrect DataSource Change Detection in Grid Component Due to Boxing

Description

Problem

The current implementation of the OnParametersSetAsync method in the Grid component incorrectly detects changes in the data source, leading to unnecessary refreshes and potential performance issues.

Current Behavior

The existing code uses a comparison that can be affected by boxing:

var _newItemsOrItemsProvider = Items ?? (object?)ItemsProvider;
var dataSourceHasChanged = _newItemsOrItemsProvider != _lastAssignedItemsOrProvider;

This comparison almost always evaluates to true, even when the actual data source hasn't changed.

Expected Behavior

The data source change detection should only return true when either Items or ItemsProvider has actually changed.

Root Cause

The primary issue is boxing, not the reference comparison itself. When Items or ItemsProvider is assigned to _newItemsOrItemsProvider (of type object), boxing occurs if they are value types. This boxing creates a new object instance each time, even if the underlying value hasn't changed. As a result, the reference comparison (!=) always detects a "change" because it's comparing two different boxed instances.

Even for reference types, the cast to object? might create a new reference in some cases, leading to false positives in the change detection.

Solution

Replace the current comparison with a more robust equality check that avoids boxing:

var dataSourceHasChanged = !Equals(Items, _lastAssignedItems) || !Equals(ItemsProvider, _lastAssignedItemsProvider);

This solution uses the Equals method to compare Items and ItemsProvider separately with their last assigned values, avoiding the boxing issue entirely.

Additional Context

This boxing issue can lead to unnecessary data refreshes and re-renders, potentially impacting the performance of applications using this Grid component, especially with large datasets or frequent updates.

Steps to Reproduce

  1. Use the Grid component with either Items or ItemsProvider set.
  2. Perform actions that would trigger OnParametersSetAsync without actually changing the data source.
  3. Observe that the grid unnecessarily refreshes its data.

Proposed Fix

Replace the problematic lines in OnParametersSetAsync with:

var dataSourceHasChanged = !Equals(Items, _lastAssignedItems) || !Equals(ItemsProvider, _lastAssignedItemsProvider);
if (dataSourceHasChanged)
{
    _lastAssignedItems = Items;
    _lastAssignedItemsProvider = ItemsProvider;
    _asyncQueryExecutor = AsyncQueryExecutorSupplier.GetAsyncQueryExecutor(Services, Items);
}

This change ensures accurate detection of data source changes without boxing, preventing unnecessary refreshes.

Impact

This fix will improve the performance and efficiency of the Grid component by reducing unnecessary data refreshes and re-renders caused by false positive change detections due to boxing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    community:contributionIssue will/can be addressed by community contributionimprovementA non-feature-adding improvement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions