jes9582
jes9582

Reputation: 253

DataGrid-Column widths not updating on ItemsSource change

XAML:

<DataGrid.Columns>
    <DataGridTextColumn x:Name="colDisplayName" Width="Auto" IsReadOnly="True" Header="Name" Binding="{Binding ssn.SSN_DISPLAY_NAME}"></DataGridTextColumn>
    <DataGridTextColumn x:Name="colValue" Width="Auto" Header="Value" Binding="{Binding ssv.SSV_VALUE}" CellStyle="{StaticResource SingleClickEditing}"></DataGridTextColumn>
    <DataGridTextColumn x:Name="colDescription" Width="Auto" IsReadOnly="True" Header="Description" Binding="{Binding ssn.SSN_DESCRIPTION}"></DataGridTextColumn>
    <DataGridTextColumn x:Name="colUnit" Width="Auto" IsReadOnly="True" Header="Unit Abbreviation" Binding="{Binding ssn.UNIT_TYPE.UNIT_NAME.UN_ABBREVIATION}"></DataGridTextColumn>
    </DataGrid.Columns>

CS:

private void tvSystemConfiguration_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
       {
           dgSystemSettings.ItemsSource =
               ((tvSystemConfiguration.SelectedItem as SYSTEM_SETTINGS_GROUP).SYSTEM_SETTINGS_NAMEs.Join
               (ssdc.SYSTEM_SETTINGS_VALUEs, x => x.SSN_ID, y => y.SSV_SSN_ID, (x, y) => new DataGridItem{ ssn = x, ssv = y })).ToList();
       }

Column widths shrink to fit correctly when increasing in column size but do not properly shrink to fit when decreasing in column size. It will not decrase the size of the column on an ItemsSource update after it has increased. Hope that makes sense. Any help is appreciated. Thank you.

Upvotes: 5

Views: 9035

Answers (4)

Fred
Fred

Reputation: 581

Much less flash on screen and less lines, no call to updateLayout necessary:

            foreach (DataGridColumn col in dg.Columns)
            {
                col.Width = DataGridLength.SizeToCells;
                col.Width = DataGridLength.Auto;
            }

Upvotes: 1

Wallace
Wallace

Reputation: 17489

For everyone's convenience, here is an extension method based on David's answer:

public static void AutoResizeColumnWidths(this System.Windows.Controls.DataGrid dataGrid)
{
    // http://stackoverflow.com/questions/4725724/wpf-datagrid-column-widths-not-updating-on-itemssource-change
    foreach (var column in dataGrid.Columns)
        column.Width = 0;

    dataGrid.UpdateLayout();

    foreach (var column in dataGrid.Columns)
        column.Width = System.Windows.Controls.DataGridLength.Auto;

    dataGrid.UpdateLayout();
}

And how it would be called:

dataGrid.AutoResizeColumnWidths();

Upvotes: 4

Levelbit
Levelbit

Reputation: 170

Maybe I can help. I had the same problem and I found, I think, nice solution.

private void DataGrid_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        DataGrid dg = (DataGrid)sender;
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            double width = 0;
            foreach (DataGridColumn column in dg.Columns)
            {
                width += column.ActualWidth;
            }
            dg.Width = width + 2;
        }
    }

Upvotes: 0

David
David

Reputation: 6124

did not make any sense for me, sorry.

I understand the code, but this part:

Column widths shrink to fit correctly when increasing in column size but do not properly shrink to fit when decreasing in column size. It will not decrase the size of the column on an ItemsSource update after it has increased

has me puzzled

I understood this like that:

if the width of a column's content increases, the column's width increases, but if the content's width decreases, the column's width does not.

Is that right ?

if so, this behaviour is normal: Wpf will just resize a datagrid's column width set to Auto if needed, i.e: the content cannot be displayed entirely. So when the content's width shrinks, the column does not resize as the content can still been seen entirely.

the only way I can see to force wpf to recalculate the columns' widths would be to force them all to 0 and then back to auto in the code behind, with one or two updateLayout() thrown in, but this is not very nice programming :-/

Edit: basically, in your code behind:

foreach (DataGridColumn c in dg.Columns)
    c.Width = 0;

// Update your DG's source here

foreach (DataGridColumn c in dg.Columns)
    c.Width = DataGridLength.Auto;

and you probably need a dg.UpdateLayout() or two somewhere in there (after the update and the setting back to auto probably)

Upvotes: 8

Related Questions