Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force WPF DataGrid to regenerate itself

I have a custom control which inherits from DataGrid and is basically a 2D DataGrid (accepts an ItemsSource with two dimensions, such as double[,] ).

I added a specific DependencyProperty which is ColumnHeaders and RowHeaders so I can define them.

Here is how it works right now:

  • I bind a 2D ItemsSource to the DataGrid
  • A wrapper method will take this source to transform it to a classic IEnumerable bindable to the actual datagrid's ItemsSource
  • Each row / column auto-generated is done using the events AutoGeneratingColumn & AutoGeneratingRow in order to define their header

The problem here:

When I initialize the DataGrid, everything works fine.

After that, one of the use-cases of my application defines that only the column headers can change (by modifying the DependencyProperty ColumnHeaders

And, whatever I do here, the DataGrid won't re-autogenerate its columns (and therefore, headers won't be changed in any way).

So, is there a way to ask the DataGrid something like "Hey, I want you to restart from scratch and regenerate your columns" ? Because for now, I can't reach the AutoGeneratingColumn event, and calling a method such as InvalidateVisual will just redraw the grid (and not regenerate columns).

Any ideas here?

I'm not sure that we need some code but... I'll put some so nobody asks for it :D

    /// <summary>
    /// IList of String containing column headers
    /// </summary>
    public static readonly DependencyProperty ColumnHeadersProperty =
        DependencyProperty.Register("ColumnHeaders",
                                    typeof(IEnumerable),
                                    typeof(FormattedDataGrid2D),
                                    new PropertyMetadata(HeadersChanged));

    /// <summary>
    /// Handler called when the binding on ItemsSource2D changed
    /// </summary>
    /// <param name="source"></param>
    /// <param name="e"></param>
    private static void ItemsSource2DPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        FormattedDataGrid2D @this = source as FormattedDataGrid2D;
        @this.OnItemsSource2DChanged(e.OldValue as IEnumerable, e.NewValue as IEnumerable);
    }

        // (in the constructor)
        AutoGeneratingColumn += new EventHandler<DataGridAutoGeneratingColumnEventArgs>(DataGrid2D_AutoGeneratingColumn);

    void DataGrid2D_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        DataGridTextColumn column = e.Column as DataGridTextColumn;
        column.Header = (ColumnHeaders == null) ? columnIndex++ : (ColumnHeaders as IList)[columnIndex++]; //Header will be the defined header OR the column number
        column.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);
        Binding binding = column.Binding as Binding;
        binding.Path = new PropertyPath(binding.Path.Path + ".Value"); // Workaround to get a good value to display, do not take care of that
    }
like image 381
Damascus Avatar asked Sep 29 '11 09:09

Damascus


2 Answers

Reset your ItemsSource and it should redraw your DataGrid

void ResetDataGrid()
{
    var temp = myDataGrid.ItemsSource;
    myDataGrid.ItemsSource = null;
    myDataGrid.ItemsSource = temp;
}

You might also be able to refresh the binding, but I haven't tested it to see if this will actually regenerate the DataGrid:

void ResetDataGrid()
{
    myDataGrid.GetBindingExpression(DataGrid.ItemsSourceProperty).UpdateTarget();
}
like image 54
Rachel Avatar answered Nov 04 '22 01:11

Rachel


Toggling AutogeneratedColumns off and then on will cause the columns to be automatically generated again.

dataGrid.AutoGenerateColumns = false;
dataGrid.AutoGenerateColumns = true;
like image 42
Andres Avatar answered Nov 04 '22 01:11

Andres