Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I work around this WPF datagrid infinite measure / arrange bug?

A very simple WPF datagrid bound to a list of images. On resizing the columns using the divider (or the main window itself) the CPU goes to 100% and the app enters an infinite loop of arrange / resize resulting in the window contents jumping back and forth and no more user input handled (locked).

The datagrid is defined as:

    <DataGrid ItemsSource="{Binding ImageList}" AutoGenerateColumns="False" x:Name="ImageGrid">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Image 1" Width="40*">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="{Binding ImagePath}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="EmptyText" />
        </DataGrid.Columns>
    </DataGrid>
  • A video of the problem is here (please forgive the poor encoding).
  • My very simplified test project is here .
  • I think it is this bug described on Microsoft Connect here .

Things I've tried:

  • Inheriting the DataGrid and overriding Arrange/Measure for the grid.
  • Overriding the arrange / measure for the window.
  • Tweaking the grid scrollbars, turning them off and various options.

What I can't do:

  • Upgrading to .Net 4.5 is not an option in this project.
  • Remove the columns, there would be no point in the grid then.

Is there any way around this behaviour in .Net 4.0? If not, I'll have to consider a workaround such as using something else in place of the grid although I've spent ages styling it and would hate to lose that work.

Thanks in advance

like image 874
Ryan O'Neill Avatar asked Nov 13 '22 06:11

Ryan O'Neill


1 Answers

I was facing the same issue, and I finally found a workaround after hours of struggling.

Add an event handler to the SizeChanged event in the DataGrid :

<DataGrid SizeChanged="DataGrid_SizeChanged">

And this is the code of the event handler :

private void DataGrid_SizeChanged(object a_sender, SizeChangedEventArgs a_args)
{
    try
    {
        DataGrid dataGrid = a_sender as DataGrid;
        if (dataGrid != null)
        {
            double widthDifference = Math.Abs(a_args.PreviousSize.Width - a_args.NewSize.Width);
            double heightDifference = Math.Abs(a_args.PreviousSize.Height - a_args.NewSize.Height);

            if ((widthDifference != 0 && widthDifference < 1) || (heightDifference != 0 && heightDifference < 1))
            {
                dataGrid.Measure(new Size(Math.Round(dataGrid.ActualWidth), Math.Round(dataGrid.ActualHeight)));
                dataGrid.InvalidateMeasure();
            }
        }
    }
    catch (Exception) { }
}

I don't know if this is a good solution, but this is the only thing that worked for me.

like image 113
Morgan M. Avatar answered Nov 15 '22 11:11

Morgan M.