3

I'm building an e-reader type application as a Windows 8.1/WP8.1 Universal app. My text is contained in a FlipView that uses an ObservableCollection<FrameworkElement> as its source. Each FrameworkElement is either a RichTextBlock or a RichTextBlockOverflow. My problem is that the FlipView stops displaying anything at all after the third element.

I found someone with a similar problem on the MDSN forums. Their solution seemed to indicate that the issue was that the RichTextBlock/Overflows weren't in the visual tree. However, when I attempt to the same by manually attaching the RichTextBlock/Overflows to a StackPanel higher in the hierarchy, I get an Exception telling me that that element is already the child of an element (and it is--it's a child of the ObservableCollectionit's been added to).

How can I fix this? Shouldn't my RichTextBlocks and their Overflows already be part of the tree because they're in the FlipView's ItemSource?

My ViewModel code is below. I can get access to elements from my View through Commanding, though I'd like to keep that to a minimum.

EDIT
I've "fixed" this with a workaround. The issue here is that FlipView virtualizes its child elements, and so after scrolling far enough away from the first page, the original RichTextBlock gets virtualized away, which causes all the RichTextBlockOverflows relying on it to lose their content. My solution was to change my FlipView's ItemsPanelTemplate from a VirtualizingStackPanel to a StackPanel. The obvious drawback here is that I lose the performance advantages of virtualization. I think I'll post this as a self-answer unless I find or receive something that works better soon.

   private void BuildPagesNew()
    {
       //CurrentPage is a public property. It's the ObservableCollection<FrameworkElement>
        CurrentPage.Clear(); 
        RichTextBlockOverflow lastOverflow;            
        lastOverflow = AddOnePage(null);
        CurrentPage.Add(lastOverflow);            

        while(lastOverflow.HasOverflowContent)
        {
            lastOverflow = AddOnePage(lastOverflow);                           
        }
    }

    private RichTextBlockOverflow AddOnePage(RichTextBlockOverflow lastOverflow)
    {
        bool isFirstPage = lastOverflow == null;
        RichTextBlockOverflow rtbo = new RichTextBlockOverflow();

        if (isFirstPage)
        {
            RichTextBlock pageOne = new RichTextBlock();
            pageOne.Width = double.NaN;
            pageOne.Height = double.NaN;
            pageOne.FontSize = 16.00;
            pageOne.MaxWidth = this.TextboxMaxWidth;
            pageOne.MaxHeight = this.TextboxMaxHeight;
            pageOne.HorizontalAlignment = HorizontalAlignment.Left;
            pageOne.VerticalAlignment = VerticalAlignment.Top;
            pageOne.IsDoubleTapEnabled = false;
            pageOne.IsHitTestVisible = false;
            pageOne.IsHoldingEnabled = false;
            pageOne.IsTextSelectionEnabled = false;
            pageOne.IsTapEnabled = false;
            pageOne.SetValue(Helpers.Properties.HtmlProperty, CurrentBook.Pages[0].PageContent);
            pageOne.SetBinding(RichTextBlock.MaxWidthProperty, new Binding
                {
                    Source = TextboxMaxWidth,
                    Path = new PropertyPath("MaxWidth")
                });
            pageOne.SetBinding(RichTextBlock.MaxHeightProperty, new Binding
                {
                    Source = TextboxMaxHeight,
                    Path = new PropertyPath("MaxHeight")
                });

            pageOne.Measure(new Size(this.TextboxMaxWidth, this.TextboxMaxHeight));
            CurrentPage.Add(pageOne);
            if (pageOne.HasOverflowContent)
            {
                pageOne.OverflowContentTarget = rtbo;
                //set width and height here?
                rtbo.Measure(new Size(this.TextboxMaxWidth, this.TextboxMaxHeight));
            }
        }
        else
        {
            //set rtbo width and height here?
            //Maybe set maxheight and maxwidth bindings too
            if (lastOverflow.HasOverflowContent)
            {
                lastOverflow.OverflowContentTarget = rtbo;
                lastOverflow.Measure(new Size(this.TextboxMaxWidth, this.TextboxMaxHeight));
                rtbo.Measure((new Size(this.TextboxMaxWidth, this.TextboxMaxHeight)));
            }
            this.CurrentPage.Add(rtbo);
        }
        return rtbo;
    }
K Mehta
  • 10,323
  • 4
  • 46
  • 76
PingZing
  • 942
  • 5
  • 20

0 Answers0