I’m developing an app for Windows Phone 7 that populates a WrapPanel with a list of objects retrieved from an ObservableCollection<Photo>.
<ListBox ItemsSource="{Binding Photo}">
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding File}" />
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel ItemHeight="150" ItemWidth="150" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
It’s working how it’s supposed to work (in the means that it’s loading all the images), but I’m having some performance issues since WrapPanel : Panel. So it doesn’t virtualize any data, loading all the Image objects of the ListBox, even the ones that the user can’t see.
This approach is OK when ObservableCollection<Photo>.Count <= 30 but as the Collection gets bigger and bigger things start to get slow.
Since the user can have up to 1000 images, it’s simply not going to work this way. Even though I’m binding Thumbnails to display the Image object.
I’ve tried to use David Anson’s LowProfileImageLoader to create Images off the UI thread. And to bind the Images as the user scrolls the ListBox. But it doesn’t work since it’s expecting an UriSource and I’m actually binding a BitmapImage to the Image.Source, because the images are beeing loaded from IsolatedStorage.
public class Photo : INotifyPropertyChanged, INotifyPropertyChanging
{
...
...
public BitmapImage File
{
get
{
// Thumbnail
string filePath = Path.Combine("Images", FileName);
byte[] data;
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream isfs = isf.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
data = new byte[isfs.Length];
isfs.Read(data, 0, data.Length);
isfs.Close();
}
}
MemoryStream ms = new MemoryStream(data);
BitmapImage bi = new BitmapImage();
bi.SetSource(ms);
return bi;
}
}
}
Can anyone help me in this task of making the content (photos) load as the user sees it? Is there anything such as a VirtualizingWrapPanel or WrapPanel : VirtualizingPanel?
Thanks. If any code snippet is needed feel free to ask.
Loading the images to memory from the storage when the user scrolls will make your UI jittery especially when the user tries to scroll or see more elements very quickly.
But, if you have all the images in memory and then would like to bind the images to the listbox on scrolling, you could use the
VirtualizingStackPanel. A wrap panel would need to know the size of the images to display correctly. A workaround is possible if you know the size of the images and if they’re all the same.You could customize the
VirtualizingStackPaneland position the images in rows like the way they would in a wrappanel, or any other way you like.Hope that helps.
Although,
I am not sure if this will solve the problem when you have 1000 heavy images. But it is worth a try, if you haven’t done so.
EDIT: This article might help.