Keep a low profile [LowProfileImageLoader helps the Windows Phone 7 UI thread stay responsive by loading images in the background]


This blog has moved to a new location and comments have been disabled.

All old posts, new posts, and comments can be found on The blog of dlaa.me.

See you there!

Comments (38)
  1. Janki says:

    While you are on topic of images, can you confirm or deny if there is anything in the final release that includes displaying of images ?

    Scenario :

    One common requirement is to show case images in the application. Let's say If I build a niche News Application and it needs to present a list of images. I will like to show that list as close to native phone gallery with all the standard features. Can I do that simply with a built-in control ? Or I have to create that piece of UI ? If we have to create, then how?

  2. David Anson says:

    Janki,

    I don't know of a built-in control that's meant specifically to be an image browser. However, it shouldn't be too difficult to write a custom control for that purpose. There's a lot of information on the web about writing Silverlight controls, so I'll refer you to that for background. In this case, I'd probably start by subclassing ItemsControl and then either use WrapPanel or a custom Panel for the ItemsPanel.

    Hope this helps!

  3. Nnp says:

    Delay,

    great post. i just got source code and trying to run sample app. but it giving me "Predefined type 'System.Object' is not defined or imported" . i am using Beta build. any idea whats wrong?

  4. David Anson says:

    Nnp,

    In the second paragraph of the post I explain that I've only tested this code on the latest internal builds, not the Beta build; I suspect that you're running into some incompatibility with the Beta. You *might* have success re-compiling the PhonePerformance assembly with the Beta Tools (in case it's a binary incompatibility), but your best bet is probably to wait a couple of days and try this out on the official RTW Tools build when it goes live later this week. 🙂

  5. David Burela says:

    This only seems to work with web URIs (throws an exception if I try to bind it to a content image via /Images/mylogo.png  says that relative URLs are not allowed).

    I have a list that has 60 items in it with an icon in each item. It takes a long time to load the screen due to all the initial image decryption. Was hoping I could load the images async through this method.

  6. David Anson says:

    David Burela,

    The underlying implementation attempts to perform an HTTP web request to load each image, so this is expected behavior for now. That said, I'd expect that you could implement fall-back logic similar to what I did for the Silverlight 4 Toolkit's ThemeUri support (in reverse, but the idea's the same). Please have a look at the LoadAndApplyThemeFromUri method near the end of Theme.cs here for an example: silverlight.codeplex.com/…/47051

    But I agree this seems like it probably ought to be part of LowProfileImageLoader, so I've added a note to my TODO list to look into adding it when I get a chance. However, if you try it yourself before then and can tell me it does/does not work, that could be useful to know. 🙂

    Thanks for your feedback – I hope this helps!

  7. Pat Long says:

    I had a problem using pages, that used the LowProfileImageLoader, in Blend. Belnd would totally crash. I have posted a smal fix on my blog and linked back to you. All I added was a DesignerProperties.IsInDesignTool in LowProfileImageLoader.OnUriSourceChanged. See http://www.munkiisoft.com/…/loading-external-images-in-the-background-ndash-windows-phone-7.aspx

    Thanks

    Pat Long

  8. David Anson says:

    Pat Long,

    Thank you very much! I've made a note to address this in my next release of LowProfileImageLoader. It's great to hear you've had some luck with it! 🙂

  9. mike says:

    hey. i used your code and it looks good. I am loading about 50 images from the internet. But, there is an issue. When I leave the page with 50 loaded images and visit another page, and get back to the first page, it seems to load the images again. When I dont use your code, although emulator takes a long time to display the images, once they are loaded they stay there, even if I visit another page and come back. Why is this happening. Is there a way to fix this?

  10. David Anson says:

    mike,

    Thanks for the feedback! It sounds like you're reporting pretty much the same thing Johnny Westlake did in the comments of the related post:

    blogs.msdn.com/…/never-do-today-what-you-can-put-off-till-tomorrow-deferredloadlistbox-and-stackpanel-help-windows-phone-7-lists-scroll-smoothly-and-consistently.aspx

    My comments/suggestions in reply to his comment (on the same post) remain relevant. When I look into this more deeply, I'll let folks know if I come up with anything better. 🙂

  11. David Burela says:

    I attempted to modify the source last night to support local streams. But I didn't get very far. Took me a while to see how you were processing the data, then I wasn't able to slot it in correctly. Sorry I wasn't able to figure it out and submit a patch.

  12. David Anson says:

    David Burela,

    Thanks for trying!

  13. Paschal says:

    Hi Great stuff! I implemented the class in my application Fotobank, available on the Marketplace. It's working very well but I have an issue. On the last page of the app, I display an image selected by a user, and I let hm saving the image to his phone. So what I want to do is to display the app bar only when the image finish to download. I tried everything but I don't see any kind of event on your class to call Oncompleted or something similar. If I make the app bar visible after setting the source, the bar appears before the image is fully displayed. Any idea or help?

    Cheers

    Paschal

  14. Paschal says:

    And by the way regarding my last comment, same apply to the progress bar. I like to stop it only when the image is there. At the moment, I think it's hiding behind the image! I am using Jeff Cox bar by the way great stuff too!

  15. David Anson says:

    Paschal,

    There's an ImageOpened event on Image that sounds like it's what you want. Unfortunately, the platform doesn't fire this event when LowProfileImageLoader is used (because it sets Image.Source to a BitmapImage that used SetSource). Therefore, I'd suggest not using LowProfileImageLoader for just this last image that is special for your application – then you can handle the ImageOpened event and get the behavior you want.

    Hope this helps!

  16. Chris says:

    Hey,

     what's the best way to load images from Isolated storage? Each object has an image file name, and I would like to load a list of these and display their image next to it in a listbox. thanks

  17. David Anson says:

    Chris,

    The IsolatedStorage APIs are probably a good place to start: msdn.microsoft.com/…/system.io.isolatedstorage(VS.95).aspx

    I don't know of any specific aspects of LowProfileImageLoader that should interfere with this process – though it might take a small bit of work if you're going to try to have LPIL do the work of loading from IsolatedStorage itself. (For example, I'm not aware of a URI format for specifying IsolatedStorage as a protocol.)

    Hope this helps!

  18. AdamV says:

    Delay

    How can we capture the image click handler ? we are trying to open the photo details, once user clicks on an image. The KeyUp / KeyDown does not fire as the API does not know whether the image is currently focused. We also tried wrapping the button around the image, but in this case, all the buttons load first & then the images load gradually as per LowProfileImageLoader ( Not pretty). Any thoughts ? Thanks

  19. David Anson says:

    AdamV,

    You might try handling the MouseLeftButtonDown event of the Image (MouseLeftButtonDown doesn't care about focus) or else its ManipulationStarted/Delta/Completed events instead. The former is probably best for giving this a quick try. Though if you go with the latter, the Windows Phone Toolkit's GestureHelper can simplify the task significantly: blogs.msdn.com/…/pining-for-windows-phone-7-controls-we-got-ya-covered-announcing-the-first-release-of-the-silverlight-for-windows-phone-toolkit.aspx

    Hope this helps!

  20. Jeff G says:

    This is really helpful when loading web content into my app, thanks!

    So, how does one check out your twitter library?

  21. David Anson says:

    Jeff G,

    The Twitter code is part of the download ZIP for this post – but remember I warned it was *exceedingly* minimal. Enough to get the sample going – and nothing more. 🙂

  22. benny says:

    thank you for the hard work ,it's very helpful.

  23. Toran Billups says:

    David,

    Love the solution and thanks for the hard work!

    2 Questions for you:

    1.) Is it possible to set a default image so while the images are loading the user would recognize an image is loading in/etc? (i tried setting source = "default.png" but it's not showing after I added the delay tag in XAML)

    2.) If an image fails to load during this async process can I handle this with a call back method such as failed to load?

    Thank you in advance

  24. David Anson says:

    Toran Billups,

    Thanks! 🙂

    1: This isn't supported at the moment, but would be a neat addition. It's already on my TODO list because of this request: blogs.msdn.com/…/quot-your-feedback-is-important-to-us-please-stay-on-the-line-quot-improving-windows-phone-7-application-performance-is-even-easier-with-these-lowprofileimageloader-and-deferredloadlistbox-updates.aspx

    2: It sounds like you might want to use the Image.ImageFailed event – but please see the comments above about the ImageOpened event for why that might not work out for your scenario due to platform behavior. However, you might be able to hook up to that event in the LowProfileImageLoader code itself and maybe that would work for your purposes?

    Hope this helps!

  25. Ashish says:

    Hi David,

    Thanks for the work you've put into this, it is awesome! I'm having a little bit of trouble getting this to work in a WrapPanel. This is what the ItemsControl looks like currently

         <ItemsControl x:Name="SelectionItemsControl">

           <ItemsControl.ItemTemplate>

             <DataTemplate>

               <Border BorderThickness="1"

                       CornerRadius="4"

                       BorderBrush="{Binding BorderBrush}" >

                 <toolkit:GestureService.GestureListener>

                   <toolkit:GestureListener Tap="OnSelectionItemTapped"

                                            DoubleTap="OnSelectionItemDoubleTapped" />

                 </toolkit:GestureService.GestureListener>

                 <Image Source="{Binding ImageSource}"

                        MaxHeight="48"

                        MaxWidth="48"

                        Margin="16" />

               </Border>

             </DataTemplate>

           </ItemsControl.ItemTemplate>

           <ItemsControl.ItemsPanel>

             <ItemsPanelTemplate>

               <toolkit:WrapPanel />

             </ItemsPanelTemplate>

           </ItemsControl.ItemsPanel>

         </ItemsControl>

    If I replace the Image Source with delay:LowProfileImageLoader.UriSource the Tap gesture stops working. Any idea why this might be happening?

  26. David Anson says:

    Ashish,

    Offhand, I can't think of a reason why this should be the case… Unless maybe it's because there's no content before the image loads due to the way LowProfileImageLoader defers setting the URI? If that's the case, you should be able to add Background="Transparent" to your Border element and that should resolve the issue.

    Hope this helps!

  27. Ashish says:

    David,

    Setting Bacground="Transparent" on the Border element fixed the problem. Thanks a bunch!

  28. Yaurthek says:

    Hello,

    I gave your LowProfileImageLoader a try, and it is pretty effective!

    However, I sometimes get a NullReferenceException line 149 (the Uri is null) while binding on a collection of Uris, some of them being null…

    I first thought you didn't handle null Uris at all, but if I use a collection of data with only null Uris, its seems to work without any exception.

    I don't fully understand the problem,  and even less your code, but I somehow found a fix:

    I just added the following lines at the beginning of the OnUriSourceChanged(…) method. (after the uri initialization)

    if (uri == null)

    {

    image.Source = null;

    return;

    }

    Its seems to work as expected now.

  29. David Anson says:

    Yaurthek,

    It sounds like there may be some unusual things going on in your scenario – but it's great to hear you found a resolution. Thanks for sharing!

  30. rabia says:

    how i can fetch images from a web site using its web services.and display in my win phone application…any one can answer me?

    i just want to develop a win phone app…web services are already available…but i don't know how to fetch images into my winPhone app using those web services…. can any one give me example code.plz

  31. Mido says:

    Could you tell me where I can find the source code of PhonePerformance 1.2.1, please?

    Thank you!

  32. David Anson says:

    Mido,

    The link near the bottom of the post that says "[Click here to download the compiled PhonePerformance assembly, sample applications, and full source code for everything.]" should give you everything you need.

  33. In case when no image found on the particular url then it is possible to set nay default image. As i am trying to set default image in case of image failed.but it is not called when i am using LowProfileImageLoader.

    plz suggest …

  34. David Anson says:

    sudhir1986,

    You might be interested in the PlaceImage control I wrote for this purpose: blogs.msdn.com/…/know-your-place-in-life-free-placeimage-control-makes-it-easy-to-add-placeholder-images-to-any-wpf-silverlight-or-windows-phone-application.aspx

    It's not integrated with LowProfileImageLoader, but you might be able to reuse some of the same ideas.

    Good luck!

  35. A.atighechi says:

    Would you please put this source code somewhere like github or codeplex

    I want to fork this and add new features. I want it to be visible where is is originated from

    Ahmad

  36. David Anson says:

    Ahmadreza A,

    I may do that some day, thanks! For now, please have a look at the WP7Contrib project (wp7contrib.codeplex.com); it's on CodePlex and they've incorporated LowProfileImageLoader into their code.

    Hope this helps!

  37. Simon says:

    @David, @Yaurthek – I have run into the same issue with Null Reference Exceptions. I also implemented the same fix by returning if the image or uri was null, however I left the image source alone. I worked out why it was happening in my situation… I'm using the LowProfileImageLoader in a LongListSelector; as images at the top of the list are Unrealized they are removed from the view as part of the virtualization – this means the value goes from a value Uri to NULL but since this is a change it fires the OnUriSourceChanged which then tried to Enqueue a NULL Uri. Hope that helps – not sure if that's a similar situation for Yaurthek?

  38. Simon says:

    UPDATE @David, @Yaurthek – I actually had to update the image source to null just like @Yaurthek's post above (thank you @Yaurthek, I tried adding the source = null as a hail mary when I saw weird artifacts of images appearing after scrolling the list!). Making sure the image source is nulled means the image disappears for good, leaving the LongListSelector to do it's job of realizing and unrealizing when required. Thanks to both of you 🙂

Comments are closed.

Skip to main content