WPF-复杂的文本块布局



在过去的几天中

-------------------- -----------
|         1        | |         |
-------------------- |    3    |
|       2       |    |         |
-----------------    -----------

所有文本块都具有动态宽度。它们具有固定高度,并在固定尺寸的容器中。他们需要满足以下要求:

  • 2具有最高优先级 - 它需要始终保持全长。
  • 3可以填充尺寸2的剩余空间2。

当忽略文本块1时,可以通过将其他两个文本块放入网格中来满足这两个要求,分别将列设置为"自动"one_answers"*"。

但是有第三个要求:

  • 1假定可以的所有空间,但不限制3。

示例:

第3块中的长内容(块2内容是全长,块3内容被修剪):

----------------- -------------
|       1       | |           |
----------------- |     3     |
|       2       | |           |
----------------- -------------

第3块中的简短内容(第2块和3个内容都是全长;块1填充剩余空间):

--------------------- ---------
|         1         | |       |
--------------------- |   3   |
|       2       |     |       |
-----------------     ---------

有没有办法在WPF中实现这种布局?如何?

我认为使用纯XAML是不可能的。实现您的要求的一种方法是实施自己的所有魔术面板。这是一个实现:

public class SpecialPanel : Panel
{
    protected override Size MeasureOverride (Size constraint)
    {
        foreach (UIElement child in Children)
        {
            child.Measure (constraint);
        }
        return constraint;
    }
    protected override Size ArrangeOverride (Size arrangeSize)
    {
        if (VisualChildrenCount != 3)
        {
            return (arrangeSize);
        }
        Size sizeLabel0 = InternalChildren[0].DesiredSize;
        Size sizeLabel1 = InternalChildren[1].DesiredSize;
        Size sizeLabel2 = InternalChildren[2].DesiredSize;
        InternalChildren[1].Arrange (new Rect (0, sizeLabel0.Height, sizeLabel1.Width, sizeLabel1.Height));
        var maxRemainingWidthFor2 = arrangeSize.Width - sizeLabel1.Width;
        if (maxRemainingWidthFor2 <= 0)
        {
            InternalChildren[0].Arrange (new Rect (0, 0, sizeLabel0.Width, sizeLabel0.Height));
        }
        else
        {
            if (maxRemainingWidthFor2 < sizeLabel2.Width)
            {
                InternalChildren[2].Arrange (new Rect (arrangeSize.Width - maxRemainingWidthFor2, 0, maxRemainingWidthFor2, sizeLabel2.Height));
                InternalChildren[0].Arrange (new Rect (0, 0, Math.Min (sizeLabel0.Width, sizeLabel1.Width), sizeLabel0.Height));
            }
            else
            {
                var max0 = arrangeSize.Width - maxRemainingWidthFor2;
                var width0 = Math.Min (sizeLabel0.Width, max0);
                InternalChildren[2].Arrange (new Rect (arrangeSize.Width - sizeLabel2.Width, 0, sizeLabel2.Width, sizeLabel2.Height));
                InternalChildren[0].Arrange (new Rect (0, 0, arrangeSize.Width - sizeLabel2.Width, sizeLabel0.Height));. 
            }
        }
        return arrangeSize;
    }
}

用法:

    <local:SpecialPanel>
        <Label
            x:Name="Label1"
            VerticalContentAlignment="Center"
            Content="TextBlock00000000000000" />
        <Label
            x:Name="Label2"
            VerticalContentAlignment="Center"
            Content="TextBloc111111111111" />
        <Label
            x:Name="Label3"
            HorizontalContentAlignment="Center"
            VerticalContentAlignment="Center"
            Content="Label333333" />
    </local:SpecialPanel>

相关内容

  • 没有找到相关文章

最新更新