CommunityToolkit / WindowsCommunityToolkit

The Windows Community Toolkit is a collection of helpers, extensions, and custom controls. It simplifies and demonstrates common developer tasks building .NET apps with UWP and the Windows App SDK / WinUI 3 for Windows 10 and Windows 11. The toolkit is part of the .NET Foundation.
https://docs.microsoft.com/windows/communitytoolkit/
Other
5.87k stars 1.37k forks source link

DataGrid Exception when bound to CollectionView and IsReadOnly=False #4929

Open HoloMetrix opened 1 year ago

HoloMetrix commented 1 year ago

Describe the bug

I have a DataGrid with ItemSource bound to a grouped collection view. Adding a group to the bound collection fails if the DatGrid property ReadOnly = False. All works fine when IsReadOnly = True.

<Page
    x:Class="WinUI3BugDemonstrator.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
    xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:WinUI3BugDemonstrator"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="using:WinUI3BugDemonstrator.ViewModels"
    d:DataContext="{d:DesignInstance Type=vm:MainPageViewModel}"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    mc:Ignorable="d">
    <Page.Resources>
        <CollectionViewSource
            x:Name="CollectionView"
            IsSourceGrouped="True"
            Source="{Binding FilteredCollection, Mode=OneWay}" />
    </Page.Resources>
    <StackPanel>
        <Button x:Name="GenerateDataButton" Click="GenerateDataButton_Click">
            Make data and filter it!
        </Button>
        <controls:DataGrid
            x:Name="datagrid"
            Grid.Row="2"
            Margin="12"
            HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch"
            AutoGenerateColumns="False"
            IsReadOnly="False" <!-- changing this to true makes it all work fine -->
            ItemsSource="{x:Bind CollectionView.View, Mode=OneWay}">
            <controls:DataGrid.Columns>
                <controls:DataGridTemplateColumn Header="Value X">
                    <controls:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Margin="4" Text="{Binding X}" />
                        </DataTemplate>
                    </controls:DataGridTemplateColumn.CellTemplate>
                </controls:DataGridTemplateColumn>
                <controls:DataGridTemplateColumn Header="Value Y">
                    <controls:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Margin="4" Text="{Binding Y}" />
                        </DataTemplate>
                    </controls:DataGridTemplateColumn.CellTemplate>
                </controls:DataGridTemplateColumn>
            </controls:DataGrid.Columns>
        </controls:DataGrid>
    </StackPanel>
</Page>

Button click calls GenerateData in the view model. Generating the data and filtering it causes an exception:

public partial class MainPageViewModel : ObservableObject
{
    private ObservableGroupedCollection<int, Vector2> rawCollection;

    [ObservableProperty]
    private ObservableGroupedCollection<int, MyData> filteredCollection;

    public void GenerateData()
    {
        rawCollection = new ObservableGroupedCollection<int, Vector2>();
        // Generate 10 data groups
        for (int i = 0; i < 10; i++)
        {
            List<Vector2> groupValues = new List<Vector2>();
            for (int j = 0; j < 5; j++)
            {
                groupValues.Add(new Vector2(Random.Shared.Next(100), Random.Shared.Next(100)));
            }
            var orderedList = groupValues.OrderBy(vector => vector.X);
            rawCollection.AddGroup(i, orderedList);
        }

        FilterData();
    }

    public void FilterData()
    {
        int maxXVal = 75;
        int maxYVal = 80;

        FilteredCollection = new ObservableGroupedCollection<int, MyData>();

        foreach (var group in  rawCollection)
        {
            List<MyData> currentGroup = new List<MyData>();
            foreach (var v in group)
            {
                if (v.X <= maxXVal && v.Y <= maxYVal)
                {
                    currentGroup.Add(new MyData { X = v.X.ToString(), Y = v.Y.ToString()});
                }
            }

            FilteredCollection.AddGroup(group.Key, currentGroup); // Null Reference exception here
        }

        OnPropertyChanged(nameof(this.FilteredCollection));
    }
}

MyData.cs only contains two string properties: X, Y.

Regression

No response

Reproducible in sample app?

Steps to reproduce

Using the minimal code example provided, set the IsReadOnly property of DataGrid to False. Click the button. See the Exception.

Expected behavior

Setting IsReadOnly = False should not cause an exception when changing the bound collection.

Screenshots

No response

Windows Build Number

Other Windows Build number

Windows 10 22H2 (Build 19045.3324)

App minimum and target SDK version

Other SDK version

No response

Visual Studio Version

2022

Visual Studio Build Number

17.7.1

Device form factor

Desktop

Nuget packages

Additional context

No response

Help us help you

Yes, but only if others can assist.

ghost commented 1 year ago

Hello HoloMetrix, thank you for opening an issue with us!

I have automatically added a "needs triage" label to help get things started. Our team will analyze and investigate the issue, and escalate it to the relevant team if possible. Other community members may also look into the issue and provide feedback 🙌