I have a page with lots of components that takes a few seconds to load.
My problem is that the page is rendered before the DataGrid components has calculated its column widths and the user can see the rendering on screen.
I built a very simple example: The DataGrid has 3 columns, the first column has a Width="*"
and the other columns have a fixed width.
The columns with the fixed width are rendered correctly from the beginning, but the star column is rendered with a width of 20.
After a second the DataGrid calculates the correct width of the star column and renders the grid correctly:
My example XAML:
<ScrollViewer>
<Controls:DataGrid Name="mainTable" AutoGenerateColumns="False">
<Controls:DataGrid.Columns>
<Controls:DataGridTemplateColumn Header="col 0" Width="*">
<Controls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Col0}" />
</DataTemplate>
</Controls:DataGridTemplateColumn.CellTemplate>
</Controls:DataGridTemplateColumn>
<Controls:DataGridTextColumn Header="col 1" Binding="{Binding Col1}" Width="150" />
<Controls:DataGridTextColumn Header="col 2" Binding="{Binding Col2}" Width="150" />
</Controls:DataGrid.Columns>
</Controls:DataGrid>
And the code behind:
public MainWindow()
{
InitializeComponent();
var rows = new List<RowObj>();
for (int i = 0; i < 5000; i++)
{
rows.Add(new RowObj
{
Col0 = "col0," + i,
Col1 = "col1," + i,
Col2 = "col2," + i,
Col3 = "col3," + i,
Col4 = "col4," + i,
});
}
mainTable.ItemsSource = rows;
}
As a note: I use WpfToolkit (the latest release, from 2010) and .NET 3.5 And I cannot switch to the WPF4 components.
Any idea how to fix the loading issue ?
My solution was to create a new DataGrid that inherits the Toolkit DataGrid, and override the MeasureOverride method and set the Widths manually. This way at the first rendering the widths are calculated correctly.
protected override Size MeasureOverride(Size availableSize)
{
double totalWidth = availableSize.Width;
double absoluteWidth = 0.0;
DataGridColumn star = null;
foreach (var col in Columns)
{
if (col.Width.IsAbsolute)
{
absoluteWidth += col.Width.Value;
col.MinWidth = col.Width.Value;
}
else if (col.Width.IsAuto)
{
absoluteWidth += col.Width.DisplayValue;
}
else if (col.Width.IsStar)
{
if (null == star)
{
star = col;
}
else
{
// This method only handles one star column
star = null;
break;
}
}
}
if (null != star)
{
double diff = totalWidth - absoluteWidth - 4.0;
if (diff > 0.0)
star.MinWidth = diff;
else
star.MinWidth = 10.0;
}
return base.MeasureOverride(availableSize);
}
WARNING: this is more of a HACK/Workaround, since it imposes some limitations on the type of column widths I can use, and on the operations I can do on them (for example binding widths is out of the question with this solution).
NOTE: for anyone who can load the data before the Page is created, the answer of Rohit Vats will most likely work.