2

My apologies in advance for this rather long post.

I am working on a PDF viewer for Windows 8.1 Store apps. The viewer displays PDF pages inside a ScrollViewer. We've run into a fairly large obstacle with large documents, where it turns out that the ScrollViewer won't display anything below a certain VerticalOffset. There's a msdn thread about it here: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/f0b2b401-57ec-4cf0-9092-8bed5194f62b/scrollviewer-does-not-render-content-at-offsets-larger-than-2096700?forum=winappswithcsharp#4eb5d5c1-3887-4e3c-af03-96c0f6a8a7b2

Basically, if a document has some 1000 pages or so, then content below the offset 2096700 gets cut off. (We do offer a single page view mode with a FlipView, but that's an option for the user, not a solution to the problem).

As you can see in the thread, the suggestion is to virtualize the ScrollViewer.

As far as I am concerned, we already are vitualizing it. The ScrollViewer contains a Canvas of a size calculated to contain every page of the document, but it's completely transparent. Instead, as the user scrolls around, only the content where the viewport current is is rendered, as well as some of the surrounding content (in order to facilitate smooth scrolling). Content too far from the ViewPort is removed.

On a side note, this is how we originally built it for Windows 8.0, and it worked fine there. It's something that changed with the plumbing under the hood for Windows 8.1.

I've been thinking about how to solve this problem, and come up with a few possible solutions. However, I am not convinced they're the best ones available. So I wanted to ask others what they suggest I do.

One of the solutions I've thought of is to shrink the content of the ScrollViewer so that it's never larger than, say, 1000000. Then, when the user gets closer to the bottom of that, I can move back up to the top half and add all the content further up than it actually should be (basically, subtract 500000 from the offset). With zooming in and out, this might be somewhat tricky. The other problem now is of course the ScrollBars. I guess I would have to somehow add my own ScrollBars and make the ScrollViewer's two scrollbars invisible. Would this be doable?

Other than this, I can't relly think of anything else that could be considered virtualization. Perhaps some of you have an idea of how to solve a problem like this, or perhaps you could tell me that my above suggestion is crazy...

I also considered to leave the content of the ScrollViewer empty, and instead have my own content below (z level wise) that I can move about using RenderTransformations to match that of the ScrollViewer. I even ran a small experiment with colored rectangles, and found some issues which makes me thing it will be very hard to do. It seems that when the ScrollBar first pops up (Visibility auto) when you zoom in then the content jumps a bit. This might be solvable though...

I guess it's also possible to develop my own control from scratch... Maybe base it off of something like PanView (http://code.msdn.microsoft.com/windowsapps/PanView-A-Metro-Panning-dc8f28c3) I am however worried that the manipulation won't feel right (physics working differently than regular ScrollViewer). Also, the manipulation code will be executed on the UI thread, which might lead to some lag as it's already a rather heavy control.

Any other suggestions or ideas? I realize this is probably not a common problem.

Thanks, Tomas

Tomas
  • 131
  • 1
  • 7

1 Answers1

0

I've hit that problem before and while I've never had to fix it (it was a prototype) - I think a solution might be to subclass a list control like the ListView and for its ItemsPanel use a virtualizing panel you get with the platform, like a VirtualizingStackPanel or ItemsStackPanel. I think these might use some tricks to work around the 2M limitation. Worth noting here, IIRC the VSP changes the unit of measure for the offsets of the ScrollViewer from pixels to something else (items?). Other than that - you could open a support request as suggested in the MSDN thread you linked.

Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
  • The support request is drafted and ready to go. Perhaps is doable, but the VirtualizingStackPanel seems to be tricky to use, since the user can scroll in 2D, and the things we put on the screen are small squaretiles (except for the edges, where they may be rectangular). So we might end up with a very large 2D structure. Another problem is that the control also has larger, page sized rectangles that (if available) contains low-res thumbnails of pages so that the user has something to look at while content is being rendered. It would be hard to combine these two things into a VSP. – Tomas Jul 08 '14 at 19:07
  • Not sure I understand what you are saying. You can use data virtualization to avoid having to construct large structures. You can use a (virtualized) list of lists unless your pages really need to be scrollable in 2D. Keep asking new questions of you hit roadblocks implementing what you need. – Filip Skakun Jul 08 '14 at 19:54