views:

284

answers:

3

Hi:

(Scenario: Windows Phone 7 / Silverlight)

I have a ListBox that i will simplify to this XAML:

<ListBox ItemsSource="{Binding Path=ImageLinks}"> <!-- ImageLinks a collection in ViewModel -->
    <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image Source="{Binding Path=ImageSource}" /> <!-- ImageSource is a string with the url to the image-->
                </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Now, the above code works, but the problem is that as the item is rendered/loaded or whatever it starts downloading the image but while doing so, it blocks the UI. And since more than one item fits at the time, the UI gets blocked until all of the corresponding images are downloaded.

So, the question is, how do i get this functionality without the UI being blocked while downloading the images (and avoiding redownloading all of them each time the view gets navigated to)?.

Thanks in advance.

Well problem Solved, Thanks to all of you who took the time to help me.

+1  A: 

You could populate ImageLinks in a secondary thread that is not tied to the UI and bind it directly from the code-behind once it is populated instead of direct XAML binding.

Dennis Delimarsky
Thanks for your suggestion i think i know what you mean (although ImageLinks is a List and ImageSource is a string). You want me to have maybe ImageSource as a BitmapImage instead of a string and populate it before i bind it to the Listbox. The problem with this is that i save the model with isolated storage witch won't let me have a property of type BitmapImage (Well i didn't mention this, sorry). I did think of something like this before, but ended downloading every image every time the view was navigated to.
Felipe Guajardo
You can populate the `List` that you have in a separate thread. In fact, `ImageSource` can be bound via `SetBinding` like this: `ListBoxName.SetBinding(ListBox.ItemsSourceProperty, b);` where b is an instance of `Binding`.
Dennis Delimarsky
+1  A: 

You could also use the PersistentImageCache class from my Kawagoe toolkit, which has been designed precisely for this use case. Let me know if it helps! :)

Andréas Saudemont
THanks. i don't know if i'm doing something wrong, but i was playing with the demo project from your toolkit in the WP7 emulator and when the application is first lauched, the UI locks for a few seconds while (i think) it's loading the very first items. After that i can smoothly scroll down a few items whose images have been downloaded, but as i reach again items with no images yet, the UI locks again. Of course if let the application load the whole collection, exit and reenter, all is good and smooth, BUT, all of this is exactly the behavior i get with the method i'm already using.
Felipe Guajardo
The demo project uses the system image loader by default; it switches to PersistentImageCache once you tap the "persistent" button at the top of the page. It sounds like I could make things clearer here... :)
Andréas Saudemont
I see. I'll give it another try.But i think you should use your toolkit by default because the demo may be a little biased since once one can switch, the images are already downloadloaded and your class could be just using the browser cache.
Felipe Guajardo
+1  A: 

Delay created a solution to exactly this problem.
See his blog entry on the topic at http://blogs.msdn.com/b/delay/archive/2010/09/02/keep-a-low-profile-lowprofileimageloader-helps-the-windows-phone-7-ui-thread-stay-responsive-by-loading-images-in-the-background.aspx

Matt Lacey
Thanks, this worked better than i expected.
Felipe Guajardo
One thing to note though. When i first tried the control, i added it to a xaml page with an associated sample data. As i replaced my <Image Source="{Binding Path=ImageSource}" /> with <Image delay:LowProfileImageLoader.UriSource="{Binding Path=ImageSource}" /> Visual Studio (2010 Express for Windows Phone from Sept. 16) crashed until i removed the xmlns referencing the sample data
Felipe Guajardo