【问题标题】:scrollable wrap with overflow带有溢出的可滚动换行
【发布时间】:2014-11-28 16:40:22
【问题描述】:

我需要在可调整大小的列中显示一段文本。文本应该用溢出来换行,但是对于给定的列大小,用户应该能够水平滚动以查看溢出的文本。

我不相信这可以通过开箱即用的控件来实现;如果我错了,请告诉我。我试图通过自定义控件来实现这一点:

public class Sizer : ContentPresenter
{
    static Sizer()
    {
        ContentPresenter.ContentProperty.OverrideMetadata(typeof(Sizer), new FrameworkPropertyMetadata(ContentChanged)); ;
    }

    public Sizer() : base() {}        

    protected override Size MeasureOverride(Size constraint)
    {
        var childWidth = Content==null ? 0.0 : ((FrameworkElement)Content).RenderSize.Width;
        var newWidth = Math.Max(RenderSize.Width, childWidth);
        return base.MeasureOverride(new Size(newWidth, constraint.Height));
    }

    private static void ContentChanged(DependencyObject dep, DependencyPropertyChangedEventArgs args)
    {
        var @this = dep as Sizer;
        var newV = args.NewValue as FrameworkElement;
        var oldV = args.OldValue as FrameworkElement;
        if (oldV != null)
            oldV.SizeChanged -= @this.childSizeChanged;
        if(newV!=null)
            newV.SizeChanged += @this.childSizeChanged;
    }

    private void childSizeChanged(object sender, SizeChangedEventArgs e)
    {
        this.InvalidateMeasure();
    }
}

...我可以像这样在一个简单的 WPF 应用程序中对其进行测试:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="200"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ScrollViewer Grid.Column="0" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" VerticalAlignment="Top">
        <local:Sizer>
            <local:Sizer.Content>
                <TextBlock Background="Coral" Text="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa  aaaaaaaaaaaaaaaaaaa" 
                           TextWrapping="WrapWithOverflow" />
            </local:Sizer.Content>
        </local:Sizer>
    </ScrollViewer>
    <GridSplitter Grid.Column="1" Background="Black" VerticalAlignment="Stretch" HorizontalAlignment="Left" Width="5" />
</Grid>

这很有效。它正确地换行和显示文本,水平滚动条让我查看溢出的文本。如果我将列调整到右侧(更大),则文本会正确重新换行。但是,如果我将列向左(更小)调整大小,则文本不会重新换行。因此,例如,如果我将列的大小调整到右侧,以便所有文本都在一行上,那么无论后续调整大小如何,它都将保持在一行上。这是一个不可接受的错误。

我已经对这段代码进行了大量修改,尽管我还没有你所谓的寻找解决方案的好策略。我不知道也无法发现任何强制文本块重新包装其内容的机制。有什么建议吗?

【问题讨论】:

  • 只有一条评论,但我已经看到了,当您减小尺寸时,UI 渲染不会重新测量。甚至从 MSFT 中发现了一些经过设计的东西。
  • 这看起来很有希望。你有没有机会获得你所读到的内容的链接?
  • 不,但如果你搜索我的问题,我知道我在 SO 上问过这个问题。我得到了一个很好的答案,只是告诉我这是一个死胡同。
  • 我怀疑您指的是:“[VirtulizingStackPanel] 的 Measure 算法......记住有史以来发现的最大尺寸,并强制所有未来的 Measure 调用报告至少一样大的尺寸。”我的树中没有 VSP,但如果 ScrollContentPresenter 执行类似的操作,它会产生我所看到的行为。谢谢。 stackoverflow.com/a/3090616/2970316
  • 是的,就是这样,但我觉得我遇到了其他领域。嘿,这只是一条评论。

标签: wpf scrollviewer word-wrap


【解决方案1】:

通过将以下内容添加到自定义控件,我能够使其正常工作(有一些限制):

    //stores first ScrollViewer ancestor
    private ScrollViewer parentSV = null;

    //stores collection of observed valid widths
    private SortedSet<double> wrapPoints = new SortedSet<double>();

    protected override void OnVisualParentChanged(DependencyObject oldParent)
    {
        parentSV = this.FindParent<ScrollViewer>();
        base.OnVisualParentChanged(oldParent);
    }

...和编辑 MeasureOverride 列出这个:

protected override Size MeasureOverride(Size constraint)
    {
        if (parentSV != null)
        {
            var childWidth = Content == null ? 0.0 : ((FrameworkElement)Content).RenderSize.Width;
            var viewportWidth = parentSV.ViewportWidth;
            if (childWidth > viewportWidth + 5)
                wrapPoints.Add(childWidth);
            var pt = wrapPoints.FirstOrDefault(d => d > viewportWidth);
            if (pt < childWidth)
                childWidth = pt;

            return base.MeasureOverride(new Size(childWidth, constraint.Height));
         }
         else
             return base.MeasureOverride(constraint);
    }

我一点也不喜欢这个。它不适用于WrapPanels(尽管这对我来说不是必需的用例),它偶尔会闪烁,我担心 wrapPoints 集合可能会变得非常大。但它做了我需要它做的事情。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    相关资源
    最近更新 更多