从ViewModel向可视树添加RichTextBlockOverflow

时间:2014-05-21 23:25:51

标签: c# windows-runtime windows-store-apps richtextblock richtextblockoverflow

我正在构建一个电子阅读器类型的应用程序作为Windows 8.1 / WP8.1通用应用程序。我的文字包含在使用FlipView作为其来源的ObservableCollection<FrameworkElement>中。每个FrameworkElement都是RichTextBlock或RichTextBlockOverflow。我的问题是FlipView在第三个元素之后停止显示任何内容。

我找到了similar problem on the MDSN forums的人。他们的解决方案似乎表明问题是RichTextBlock/Overflows不在视觉树中。但是,当我通过手动将RichTextBlock/Overflows附加到层次结构中的StackPanel来尝试相同时,我得到一个异常,告诉我该元素已经是元素的子元素(并且它是 - - 这是ObservableCollection被添加到其中的孩子。

我该如何解决这个问题?我的RichTextBlocks及其Overflows不应该是树的一部分,因为它们位于FlipView的ItemSource中吗?

我的ViewModel代码如下。我可以通过命令访问我的View中的元素,但我希望将其保持在最低限度。

修改
我通过解决方法“修复”了这个问题。这里的问题是FlipView虚拟化其子元素,因此在滚动远离第一页之后,原始RichTextBlock被虚拟化,导致依赖它的所有RichTextBlockOverflow丢失其内容。我的解决方案是将我的FlipView的ItemsPanelTemplate从VirtualizingStackPanel更改为StackPanel。这里明显的缺点是我失去了虚拟化的性能优势。我想我会发布这个作为一个自我回答,除非我找到或收到一些效果很快的东西。

   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;
    }

0 个答案:

没有答案