views:

17

answers:

1

I have a Grid that looks something like the simplified example showed below. There are more elements in the grid but the problem is about the ListBox and the TextBlock.

If the TextBlock (or any other element with the same grid-configuration) has a ColumnSpan of two, every Update to an Item of the ListBox is very slow. I have looked with Perforator and VisualProfiler but could not see any special thing. If I set the second ColumnDefinition to a fixed width, all works as desired. The same happens, if I set the first RowHeight to a fixed height.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2">The column-span of this TextBlock seems to lead to an refresh-problem</TextBlock>
    <ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding}"></ListBox>                
</Grid>

Has someone a deeper insight into this and can explain me if this construction is a no no or what else here happens.

+1  A: 

The problem is that the listbox creates all visual elements in the list to figure out which is the widest since your GridColumn is set to Auto in width. If your list contains many items or has a complicated (heavy) ItemTemplate, you're in trouble.

Normally, the ListBox only creates visual elements for visible elements (this is done by the VirtualizingStackPanel inside the ItemsPanelTemplate.

An alternative is to set a default width that will work 95% of the time - and then use a GridSplitter in the next column for the last 5% (So the user can widden the list). Alternate, you can use another Panel (e.g. a DockPanel) that doesn't ask the ListBox how wide it wants to be... :-)

Goblin
+1 As you wrote: "ListBox only creates visual elements for visible elements", but why not in the explained situation? If I set a fixed with to the ListBox, this does not change the situation. It's not really a big problem, I workaround it with a fixed with for the GridColumn and a grid-splitter, however it gives my a bad feeling: There is no other WPF-Element I use as much as the Grid. Normaly I would not have remarked this performance impact but now I know about and I have done a lot apps with this structure and therefore burning a lot of cpu-power for nothing.
HCL
The problem is in how the Grid handles vertical assignment of space. When you set a row to Auto - the grid checks with the children in that row how large they wish to be with an available height of Infinite. The ListBox when confronted with infinite will return the height of all it's visual children... However, the reason you don't see it in all instances is that in some cases the Grid can determine the available height or the maximum height available and thus passes this value to the ListBox in the Arrange()-pass. Same goes for Columns sized Auto.
Goblin