3
votes

I've found a strange behavior with images I have loading in a list. The following is a simplified snippet of an itemTemplate that produces this problem:

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

<Image x:Name="Art" Grid.Row="1" Grid.Column="1" Source="{Binding Url}" Stretch="UniformToFill" />
</Grid>

The files the images load are .png of size 360w,240h. When I first open the page that loads the above xaml, the list renders a 180w, 180h space for each image at the full size available given by the grid dimensions: 180 width and auto height. Then once the image has loaded, the image area is scaled down to width limit of the grid(180) and its height is scaled proportionally(120). So the effect is the list item is drawn at a 180 by 180 square, then shrinks down to 180 by 120 after the image loads.

I would expect that until the image source is downloaded, the image element has dimensions 0,0. I would expect the content of each item would not take up any height at all before the image is loaded; the area should not start out using 180h.

Is this problem by design? Is there any known workarounds for dealing with it? My real code has a default image in the same grid location loaded locally while the download of the final image isn't finished. Its dimensions are the same as the loaded image source so what happens is there is a gap between the top and bottom of the placeholder image while the image loads, then the grid space shrinks to what it should have been all along. It is very gross.

1
I know it's lame, but did you try reversing the order of your row/col definitions? There are stranger anomalies out there, so it's worth asking... - Gayot Fow
I tried playing around with your suggestion but unfortunately changing the order didn't change anything. It would be a bit scary if it had. - user1807768
I ran a small experiment and got the same thing! Thanks for trying! The only other suggestion I have is put the image into a container at row 1, col 1. It could be a wild goose chase, but you never know. - Gayot Fow
Thanks for reproducing this experiment Gayot. It sounds like this isn't a well known issue with an obvious fix so I'll just stick with the low bar solution of explicitly setting the height of the grid to force the correct behavior. - user1807768
All is not lost. There's a user called 'Clemens' who knows this stuff to the dirt bottom. Hopefully he'll weigh in on your question and you'll be all set. - Gayot Fow

1 Answers

2
votes

Apparently, when the Image's Stretch property is set to anything else than None, the ListBoxItem (that contains the Grid and the Image) somehow imposes a layout with initially square dimensions. When the Source is finally loaded, the layout is recalculated to the true dimensions. The same DataTemplate in an ItemsControl (instead of a ListBox) does not show this behaviour.

Fortunately the Image control also has a StretchDirection property, which you can set to DownOnly to prevent the initially square layout. The drawback is that this only works as long as your images do not have to be stretched up, from widths less than 180.

<Image Source="{Binding Url}" Stretch="Uniform" StretchDirection="DownOnly"/>