WPF - 复杂TextBlock的布局

问题描述:

在过去的几天我一直在试图环绕的TextBlocks以下布局我的头:WPF - 复杂TextBlock的布局

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

中的TextBlocks所有具有动态宽度。他们有固定的高度,并在一个固定大小的容器。他们需要满足以下要求:

  • 2具有最高优先级 - 它需要始终处于全长状态。
  • 3可以浆纱2.

当忽略的TextBlock 1,这两方面的要求可以通过将其他两个的TextBlocks网格中的履行,与一组列满后留下的剩余空间为“自动”和“ *“ 分别。

有虽然第三个要求:

  • 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> 
+0

感谢您的回答。但是,第二个示例不能按预期工作。我已经修改了你的代码以使其工作,最后一个'else'分支需要改变为:'InternalChildren [2] .Arrange(new Rect(arrangeSize.Width - sizeLabel2.Width,0,sizeLabel2.Width,sizeLabel2。高度)); InternalChildren [0] .Arrange(new Rect(0,0,arrangeSize.Width - sizeLabel2.Width,sizeLabel0.Height));'。如果你修改答案,我会接受它。 – Mastah

+0

我很高兴你有这个想法,并能够根据您的需求调整逻辑。我更新了我的答案。 – gomi42