2016-12-25 75 views
-2

在過去的幾天我一直在試圖環繞的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?怎麼樣?

回答

0

我不認爲這是可能的純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