2016-12-25 18 views
-2

ここ数日のために私は、テキストブロックの以下のレイアウトのまわりで私の頭をラップしようとしてきた:WPF - コンプレックスのTextBlockレイアウト

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

テキストブロックのすべては、動的な幅を有しています。それらは高さが固定されており、固定サイズのコンテナ内にあります。彼らは次の要件を満たす必要があります:

  • 2は、常に完全長である必要があります。
  • 3のTextBlock 1を無視した場合、これらの2つの要件が「自動」に設定された列に、グリッド内の他の二つのテキストブロックを置くことによって満たすことができ2.

サイジングした後に残され、残りのスペースを埋めると "することができます*」と表記しています。

かかわらず第3の要件がある:

  • 1はそれができ、すべてのスペースをとるが、しかし3

例を制限することなく:

ブロック3(ブロック2における

ロングコンテンツコンテンツは全長であり、ブロック3のコンテンツはトリムされる):

ブロック3の短いコンテンツ(ブロック2と3の両方のコンテンツは全長です。ブロック1)は、残りのスペースを埋める:

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

は、WPFでこのレイアウトを実現する方法はありますか?どうやって?

答えて

0

純粋なXAMLではこれが可能ではないと思います。要件を達成する1つの方法は、すべての魔法を実行する独自のパネルを実装することです。

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

おかげでここに一つの実施です。ただし、2番目の例では期待どおりに動作しません。私はそれを動作させるためにあなたのコードを変更しました、最後の '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

関連する問題