There's no substitute for customer feedback! [Improving Windows Phone 7 application performance now a bit easier with LowProfileImageLoader and DeferredLoadListBox updates]

**

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

  • Anonymous
    October 05, 2010
    Thanks, looking forward to checking the latest version when I get home tonight. The OnApplyTemplate fix is something that I also hacked in myself. I didn't report it as I thought that I was just doing something wrong in the order I was loading things.

  • Anonymous
    October 24, 2010
    Hi, Does DeferredLoadListBox  work in pivot control? I am noticing some odd behavior with it. It seems to hang and make things load show when scrolling from one pivot item to the next.

  • Anonymous
    October 25, 2010
    Zeus, I haven't specifically tried that scenario, but this is also the first I've heard of it being a problem, so maybe it's unique to your scenario. What you might do is create a new project and try to reproduce the problem there - reducing everything to its simplest form can often help identify the source of a problem like this. If you're still seeing this behavior in a simplified project, please get in touch with me via the "Email Blog Author" link on this page and I can have a look. Thanks!

  • Anonymous
    November 26, 2010
    For several time in my test app, I encountered the same problem of System.Exception was unhandled in the file LowProfileImageLoader.cs at Ln 155 var response = responseState.WebRequest.EndGetResponse(pendingResponse); Any suggestions to resolve or work around it. Thanks very much.

  • Anonymous
    November 28, 2010
    info815, As you can tell from the comment in the catch clause of that block, instances of WebException are expected when the file couldn't be downloaded, etc.. If you're running with first chance exceptions enabled, you may simply be hitting an instance of that. But if you're really seeing instances of Exception itself, it might be interesting to see the message and stack trace contained within to get an idea of what might be causing this. If you're able to share those, that could be quite helpful. Thanks!

  • Anonymous
    January 23, 2011
    Hi, first of all thanks for releasing this. It does make a noticeable difference in performance. I am encountering a weird issue. I'm using the listbox in a user control that is within a pivot. However intermittently the application crashed throwing the "All containers must have a Height set (ex: via ItemContainerStyle), though the heights need not all need to be the same." exception. However this is said, and when you inspect the height property it has a value but the actual height doesn't. Do you have any ideas on what would be causing this? I have read that "ActualWidth and ActualHeight are calculated based on the Width/Height property values and the layout system.  There is no guarantee as to when these values will be "calculated"." Which is why I'm guessing this error doesn't always occur for me. I was wondering whether the UnmaskItemContent needs to be called as an action using the Dispatcher?

  • Anonymous
    January 23, 2011
    The comment has been removed

  • Anonymous
    January 24, 2011
    I implemented a retry counter like you suggested, after many attempts at trying to reproduce the issue it appears having a retry counter is enough to resolve the issue. In my testing it appears just trying it 1 to 2 more times is enough. I now only throw an exception if the ActualHeight is 0 and the retry counter is greater than 2. You do notice a very slight pause in the UI rendering however as this error only occurs occasionally it seems a plausible and passable workaround. It's worth noting that I have a global retry counter, I considered one per item you try to unmask however it appears that a global one is more than enough as updates don't occur that frequently.

  • Anonymous
    January 24, 2011
    Michael James, Great information - thanks a lot for the update!

  • Anonymous
    January 27, 2011
    "So in lieu of a reliable way to detect the cache state of individual images (I'm open to suggestions, by the way!)" IIRC WebClient has a download can be forced to only use cached stuff. But of course WebClient is async as well.. But maybe this can be used as a starting point...

  • Anonymous
    January 27, 2011
    Martin, That's a really interesting idea! What I'd really like is a way to tell if each image is in the cache or not - and I'm concerned the technique you point out might force the code to make a cache-only web request which is unnecessary/wasteful when it succeeds and delay-inducing when it fails. Ick. :( You may be onto something here, but it's not quite the clean WebClient.IsImageCached(...) method I might prefer... :)

  • Anonymous
    March 09, 2011
    David, I just implemented the DeferredLoadListBox and it gives an amazing performance compared to a ListBox. However, my layout depends on Items in the ListBox with different Heights (Text-Blocks with varying length and wordwrapping). I'd even go as far and calculate the Height on my own but couldn't find an example on how to do. The Items in the DeferredLoadListBox are not controlls and therefore don't have an height? I also couldn't find any examples out there... Thanks in advance for some tips where to look.

  • Anonymous
    March 10, 2011
    Arne Schmid, One way of doing this is to subclass and override the GetContainerForItemOverride method on (DeferredLoad)ListBox - that's your chance to customize the ListBoxItem container that gets automatically generated and you can assign a Height there (with full knowledge of the corresponding model object which will be its DataContext). For some background on how containers work with ItemsControl subclasses, here's a good post to read: drwpf.com/.../itemscontrol-g-is-for-generator Hope this helps!

  • Anonymous
    March 20, 2011
    The comment has been removed

  • Anonymous
    March 21, 2011
    Nadeem, Sorry for the confusion! GetContainerForItemOverride is the place to provide a custom container type (or just customize the default one), but PrepareContainerForItemOverride is the method I was thinking of when I talked about access to the container and the object for relevant customizations: msdn.microsoft.com/.../system.windows.controls.itemscontrol.preparecontainerforitemoverride(v=VS.95).aspx With that mistake of mine cleared up, I think you'll have an easier time of this. :)

  • Anonymous
    March 21, 2011
    Thanks a lot David. I have a good idea of how to do it now. ...I should have spent more time digging for the right method but sometimes a person get's overwhelmed with the sheer amount of new info to digest :-) Regards, Nadeem

  • Anonymous
    April 07, 2011
    Hi David, I have tried to use the LowProfileImageLoader in a ListBox and WrapPanel as the ListBox's ItemsPanel but my image was not loaded at all :( Do you have any idea why? Regards, Veri

  • Anonymous
    April 08, 2011
    Veri, Nothing about switching to a different ItemsPanel should affect how LowProfileImageLoader works. You might try switching back to the default ItemsPanel to see if the problem remains - if so, then it's probably something else (like a broken Binding?). Alternatively maybe try WrapPanel+LowProfileImageLoader outside a ListBox to verify that works okay.

  • Anonymous
    April 18, 2011
    Hi David, I have tried your suggestion but it still didn't work :( I have a few questions though:

  1. Do I have to use the DeferredListBox or can I use the default ListBox?
  2. Can I change the LowProfileImageLoader.UriSource to catch string instead of url? Regards, Veri
  • Anonymous
    April 18, 2011
    Veri,
  1. You can definitely use LowProfileImageLoader with the default ListBox. The two classes work together, but are not tied together. :)
  2. I don't quite understand the question, but if you're asking if you could make UriSource a string-typed property instead of a Uri-typed property, that should work just fine (once you update the parts of the code that assume Uri). Hope this helps!
  • Anonymous
    July 25, 2012
    Thank you for this lib! Is there a way to fade in the downloaded image? I tried from ImageOpened but I discover here that it is not triggered :( Thanks for any help!

  • Anonymous
    July 25, 2012
    Geobert, Please see the comments in this post for some information about ImageOpened: blogs.msdn.com/.../keep-a-low-profile-lowprofileimageloader-helps-the-windows-phone-7-ui-thread-stay-responsive-by-loading-images-in-the-background.aspx But you may be able to modify the code for LowProfileImageLoader itself to get the effect you want by adding in an Animation of the Image's Opacity property from 0->1. Hope this helps!

  • Anonymous
    August 30, 2012
    The comment has been removed

  • Anonymous
    September 01, 2012
    iglaweb, If there's a crash, you can usually find out what the exception was in the debugger and use that (plus the call stack) to figure out what went wrong. Sometimes it can help to turn on first chance exception handling in the debugg.r as well (a web search will say how to do that). Because my sample application works properly, I'm not sure offhand what would cause this - another thing to try would be incrementally commenting stuff out of your application until the problem goes away and using that to see what the specific cause might be. Hope this helps!

  • Anonymous
    January 14, 2013
    Hi David, great stuff! Wouldn't it be a good idea to have an option to store the downloaded file in isolated storage for later use? And then automatically check whether the icon is already available in isolated storage and load it from there instead of the internet?

  • Anonymous
    January 15, 2013
    Pete, Sure, that's a neat idea. Shawn Burke actually wrote a framework for that called AgFx: github.com/.../AgFx. You may want to check that out; my understanding is that it supports exactly the scenario you're interested in. Good luck!