2011-02-28 32 views
6

我想要一個邏輯和簡單的方式來產生一個控制集來填補和其餘的停靠的佈局。我可以使用:WPF:StackPanel與FirstChildFill?

<DockPanel LastChildFill="True"> 
    <Button Content="3" DockPanel.Dock="Bottom" /> 
    <Button Content="2" DockPanel.Dock="Bottom" /> 
    <Button Content="1" /> 
</DockPanel> 

但它不是很直觀的使用。我也可以這樣做:

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="*" /> 
    <RowDefinition Height="Auto" /> 
    <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Button Content="1" Grid.Row="0" /> 
    <Button Content="2" Grid.Row="1" /> 
    <Button Content="3" Grid.Row="2" /> 
</Grid> 

但它也很多xaml。我真正想要的是這樣的:

<StackPanel Fill="None|First|Last"> 
    <Button Content="1" /> 
    <Button Content="2" /> 
    <Button Content="3" /> 
</StackPanel> 

怎麼能實現這一目標,而不必扭轉項目與DockPanel中並沒有使用行和附加屬性的固定數量與網格?

回答

3

您可以隨時使用不同的對接規則編寫自己的面板。您可以使用標準的DockPanel實現(在框架源代碼中提供 - 它看起來不是很複雜),並根據您喜歡的規則創建類似的東西。你甚至可以創建一個派生自DockPanel的類並重寫ArrangeOverride。

但個人而言,我只是使用停靠面板,它完全符合你的要求,只是你不喜歡它關於哪個成員是填充的規則。

如果您插入/刪除行,IME網格有一個可怕的維護問題,因爲您發現自己無休止地調整行號 - DockPanel在這方面更容易。

更新:

在這裏,你走了,我已經拒絕你這樣做你自己的快樂 - 這是剛切下來/反轉框架的源代碼版本:

public class BottomDockingPanel : DockPanel 
{ 
    protected override Size ArrangeOverride(Size arrangeSize) 
    { 
     UIElementCollection children = InternalChildren; 
     int totalChildrenCount = children.Count; 

     double accumulatedBottom = 0; 

     for (int i = totalChildrenCount-1; i >=0 ; --i) 
     { 
      UIElement child = children[i]; 
      if (child == null) { continue; } 

      Size childDesiredSize = child.DesiredSize; 
      Rect rcChild = new Rect(
       0, 
       0, 
       Math.Max(0.0, arrangeSize.Width - (0 + (double)0)), 
       Math.Max(0.0, arrangeSize.Height - (0 + accumulatedBottom))); 

      if (i > 0) 
      { 
       accumulatedBottom += childDesiredSize.Height; 
       rcChild.Y = Math.Max(0.0, arrangeSize.Height - accumulatedBottom); 
       rcChild.Height = childDesiredSize.Height; 
      } 

      child.Arrange(rcChild); 
     } 
     return (arrangeSize); 
    } 
} 
+0

謝謝!這會讓我開始... – 2011-02-28 15:30:44

0

沒有這種WPF中的面板可以支持這種開箱即用的功能。如果你想要這個特定的行爲,你可以創建你自己的面板,但我不會建議你這樣做,因爲它非常自定義,並且不需要經常這樣做(如果想要一個具有像MiddleChildFill行爲的面板,該怎麼辦?你自己的面板也是這樣?)。

通常這種佈局是通過使用Grid(如你所說)來實現的。是的,Grid有一個非常詳細的語法(你可以使用像this這樣的助手來簡化它),但它給了你最大的靈活性。而在一天結束時,這纔是重中之重。

+0

我經常使用這種佈局模式。有一個選項可以填充最後一個或第一個孩子的StackPanel將會非常有用,我認爲。 – 2011-02-28 15:37:25

+0

@Andreas Zita - 這是你的選擇,我只是分享我的經驗:) – 2011-02-28 15:45:30

1

您可以在其中使用帶有StackPanel的DockPanel。 「主要」內容將顯示在最後,而不是第一個,但至少底部內容將在您的XAML中以邏輯順序顯示。如果您願意將填充的內容放在最後,這將是最簡單的方法。

<DockPanel LastChildFill="True"> 
    <StackPanel DockPanel.Dock="Bottom"> 
    <Button Content="Bottom 1" /> 
    <Button Content="Bottom 2" /> 
    <Button Content="Bottom 3" /> 
    </StackPanel> 
    <Button Content="Main" /> 
</DockPanel> 

或者,如果你想要的一切(包括填充內容)在相同的順序XAML它顯示在屏幕上顯示出來,你可以使用兩行的網格,並在一個StackPanel第二排。正如你所指出的那樣,網格需要一些XAML,但是嵌套的StackPanel將使您不必爲每個新項目添加RowDefinition和Grid.Row。

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="*" /> 
    <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Button Grid.Row="0" Content="Main" /> 
    <StackPanel Grid.Row="1"> 
    <Button Content="Bottom 1" /> 
    <Button Content="Bottom 2" /> 
    <Button Content="Bottom 3" /> 
    </StackPanel> 
</Grid> 
+0

我的具體情況的問題是,我想用一個ItemsContainer上的模板產生這種佈局,我認爲沒有辦法拆分項目演示者在「主要」和「其餘」 - 可枚舉。如果有可能,我可以這樣做...... – 2011-02-28 15:33:56

+0

您可以始終讓您的ViewModel公開兩個屬性:一個用於第一個孩子(您要填充空間),另一個用於其餘項目。然後你可以爲第一個使用ContentControl,剩下的就可以使用ItemsControl。不完全優雅,但比編寫自己的面板簡單得多。 – 2011-03-01 13:02:20