1

I'd like to develop a simple mail client in WPF. In any mail client, part of the window is a list of messages. The usual behaviour of desktop clients such as Outlook or Thunderbird is to download every email in your inbox folder as soon as you set up your account. You might have millions of messages there, and the client will quite happily leave you waiting for hours while the messages download.

What I'd like to do is this. Given that you know how many messages are in the inbox without having to download them (which is easy in IMAP, for instance), I could fill a ListBox with placeholder items, and retrieve the corresponding message only when it comes into view.

How can I take action when an incremental set of items is scrolled into view? I came across this option in my research, but I'd like a solution that (a) allows me to identify newly visible messages incrementally rather than having to iterate over the whole set (if possible), and (b) is MVVM-friendly.

Community
  • 1
  • 1
Gigi
  • 28,163
  • 29
  • 106
  • 188
  • 1
    It's not broad or opinion based. I am asking how something specific is done in WPF. – Gigi Apr 16 '14 at 18:32
  • 1
    The question is right there. You just need to read it. – Gigi Apr 16 '14 at 18:32
  • And I'm saying there are way too many solutions for the problem. The best thing you can do is research one yourself, try it, and if it's not good enough ask how to make it better. – gunr2171 Apr 16 '14 at 18:33
  • If you know a solution, then maybe you can contribute an answer. – Gigi Apr 16 '14 at 18:34

1 Answers1

1

This is harder than it looks -- you'll have to get creative. One way into this problem is to notice that ScrollViewer has properties ExtentHeight, ViewportHeight, and VerticalOffset. You can use these properties to get the currently visible items:

  • item height = ExtentHeight / number of items in the ListBox
  • index of first item in the viewport = VerticalOffset / item height
  • number of items in the viewport = ViewportHeight / item height

Now it's just a matter of hooking into the ScrollViewer using your preferred method (subclass ListBox maybe?), and attaching a listener to its ScrollChanged event. Each time the handler gets called, compare the current items in the viewport to the previous. You'll probably also want to throttle the handler, by keeping track of the last time it ran, or better by using Observable.FromEvent and Observable.Throttle.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260