2009-08-24 91 views
104

是否可以輕鬆地爲WPF Grid中的行或列指定邊距和/或填充值?WPF:帶有列/行邊距/填充的網格?

我當然可以額外列添加到空間的事情了,但是這似乎是填充/利潤率工作(它會給 simplier XAML)。是否有人從標準Grid派生出來添加這個功能?

+2

一個有用的例子:http://www.codeproject.com/Articles/107468/ WPF-Padded-Grid – peter70 2014-05-30 07:11:14

回答

14

你可以寫你自己的GridWithMargin類,從Grid繼承,並重寫ArrangeOverride方法應用利潤率

67

RowDefinitionColumnDefinition屬於ContentElement類型,並且Margin嚴格是FrameworkElement屬性。所以對你的問題,「很容易」答案是一個最明確的不。不,我還沒有看到任何展示這種功能的佈局面板。

您可以按照建議添加額外的行或列。但是,您也可以在Grid元素本身或任何可能在Grid之內的任何內容設置邊距,因此這是目前最佳的解決方法。

1

一種可能性是增加固定寬度的行和列作爲填充/保證金您正在尋找對於。

您可能還會考慮受限於容器的大小,並且網格將變得與包含元素或其指定的寬度和高度一樣大。您可以簡單地使用沒有設置寬度或高度的列和行。這樣他們默認均勻分散網格內的總空間。那麼它只是將你的元素在你的網格中垂直和水平居中。

另一種方法可能是將所有網格元素封裝在固定的單行&列網格中,該列網格具有固定的大小和邊距。您的網格包含固定的寬度/高度框,其中包含您的實際元素。

+0

感謝Adam,但是添加額外的列/行正是我試圖避免的。我只是想減少我的標記,並能夠指定一個邊距或填充將有助於這一點。 – 2011-04-14 11:33:46

+0

您只需定義額外的列和行,而不是爲它們添加標記。例如,如果您想在3列之間的列之間添加N寬度,則您將有5列定義。第一個是自動寬度,下一個固定,然後自動,然後固定,然後自動。然後只將第1,3和5列分配給實際的內容元素。我看到你對額外列標記的看法,但除非你有數百個元素,這對我來說似乎微不足道。你的電話雖然。另外,你有沒有嘗試使用堆疊面板的邊距設置? – 2011-05-04 02:51:03

+0

對於我的情況,添加一個「分配器/保證金」列是迄今爲止最乾淨和最簡單的。謝謝! – jchristof 2018-02-20 16:55:14

19

你可以使用這樣的事情:

<Style TargetType="{x:Type DataGridCell}"> 
    <Setter Property="Padding" Value="4" /> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type DataGridCell}"> 
     <Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 
      <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> 
     </Border> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 

或者,如果你不需要TemplateBindings:

<Style TargetType="{x:Type DataGridCell}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type DataGridCell}"> 
       <Border Padding="4"> 
        <ContentPresenter /> 
       </Border> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 
+22

感謝JayGee,但是這個解決方案是用於DataGrid--而不是標準的Grid控件。 – 2011-04-14 11:31:16

3

我和電網的一個做到了現在。

  • 首先對網格內的每個元素應用相同的邊距。你可以做這個mannualy,使用風格,或任何你喜歡的。假設你想要一個6px的水平間距和一個2px的垂直間距。然後,爲網格的每個孩子添加「3px 1px」的邊距。
  • 然後刪除在網格周圍創建的邊距(如果要將網格內控件的邊框對齊到網格的相同位置)。這樣做是爲網格設置一個「-3px -1px」的邊距。這樣,網格外的其他控件將與網格內的outtermost控件對齊。
+0

對網格中的每個元素應用相同的邊距似乎是最簡單的方法。 – Envil 2015-12-19 10:08:45

16

使用Border控制單元控制外部並且限定用於所述填充:​​

<Grid> 
     <Grid.Resources > 
      <Style TargetType="Border" > 
       <Setter Property="Padding" Value="5,5,5,5" /> 
      </Style> 
     </Grid.Resources> 

     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 

     <Border Grid.Row="0" Grid.Column="0"> 
      <YourGridControls/> 
     </Border> 
     <Border Grid.Row="1" Grid.Column="0"> 
      <YourGridControls/> 
     </Border> 

    </Grid> 


來源:

+1

鏈接頁面現在有服務器錯誤。 – 2016-05-12 10:21:18

+1

@RichardEverett檢查返回機器:鏈接在答案中更新。 – CJBS 2017-05-24 23:41:38

3

我最近在開發一些軟件的時候遇到了這個問題,並且問我爲什麼問這個問題?他們爲什麼這樣做?答案就在我面前。一行數據是一個對象,所以如果我們保持對象的方向,那麼特定行的設計應該是分開的(假設你將來需要重新使用行顯示)。所以我開始爲大多數數據顯示使用數據綁定堆棧面板和自定義控件。列表偶爾會出現,但大多數網格僅用於主頁面組織(標題,菜單區域,內容區域,其他區域)。您的自定義對象可以輕鬆地管理堆棧面板或網格中每行的任何間距要求(單個網格單元格可以包含整個行對象,還可以正確反應方向變化,展開/摺疊等等。

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition /> 
    <RowDefinition /> 
    </Grid.RowDefinitions> 

    <custom:MyRowObject Style="YourStyleHereOrGeneralSetter" Grid.Row="0" /> 
    <custom:MyRowObject Style="YourStyleHere" Grid.Row="1" /> 
</Grid> 

<StackPanel> 
    <custom:MyRowObject Style="YourStyleHere" Grid.Row="0" /> 
    <custom:MyRowObject Style="YourStyleHere" Grid.Row="1" /> 
</StackPanel> 

自定義控件如果使用數據綁定您也將繼承DataContext的...我個人最喜歡的益處這種方法的。

+0

您試圖在此處做的是在'GridView'模式下創建WPF'ListView'控件的粗略版本,但沒有規定讓所有「RowObjects」共享相同的列寬。事實上,它不再與電網有很大關係。 – 2017-12-11 21:52:04

0

雖然你不能添加保證金或填充到一個網格,你湊ld使用類似Frame(或類似容器)的東西,可以將其應用於。

這樣(如果你在按鈕上顯示或隱藏控件,點擊說),你不需要爲每個可能與之交互的控件添加邊距。

把它看作是將控件組分隔成單元,然後對這些單元應用樣式。

2

以爲我會加我自己的解決方案,因爲沒有人提到過這個。除了設計基於網格的UserControl之外,還可以使用樣式聲明將網格中包含的控件作爲目標。需要添加填充/保證金的所有元素,而無需定義每個,這是麻煩和勞動力intensive.For實例的照顧,如果你的網格只含有的TextBlocks,你可以這樣做:

<Style TargetType="{x:Type TextBlock}"> 
    <Setter Property="Margin" Value="10"/> 
</Style> 

哪個就像相當於「細胞填充」一樣。

+0

做這滴嗎?例如,如果在網格行中有一個堆棧面板,堆棧面板的textblock子級是否會繼承此屬性? – Maslow 2017-03-08 20:35:04

+0

不知道它是否會流過直接的孩子,但你可以通過一個簡單的測試找出答案。 – 2017-03-11 00:44:04

+0

@Maslow答案絕對是「是的」,但你的措辭有點誤導。 「Margin」屬性沒有「繼承」,它就是說ResourceDictionary中的任何'Style'都將應用於它的'TargetType''的每個元素到處***在該字典所有者的整個範圍***內元件。所以這是'流行',而不是財產。 – 2017-12-11 22:01:07

-1

有時簡單的方法是最好的。只需用空格填充你的字符串。如果只有幾個文本框等,這是迄今爲止最簡單的方法。

您還可以簡單地插入固定大小的空白列/行。非常簡單,你可以很容易地改變它。

+0

爲什麼這會降低投票率? – rolls 2017-07-19 00:10:43

2

如前所述創建一個GridWithMargins類。 這是我工作的代碼示例

public class GridWithMargins : Grid 
{ 
    public Thickness RowMargin { get; set; } = new Thickness(10, 10, 10, 10); 
    protected override Size ArrangeOverride(Size arrangeSize) 
    { 
     var basesize = base.ArrangeOverride(arrangeSize); 

     foreach (UIElement child in InternalChildren) 
     { 
      var pos = GetPosition(child); 
      pos.X += RowMargin.Left; 
      pos.Y += RowMargin.Top; 

      var actual = child.RenderSize; 
      actual.Width -= (RowMargin.Left + RowMargin.Right); 
      actual.Height -= (RowMargin.Top + RowMargin.Bottom); 
      var rec = new Rect(pos, actual); 
      child.Arrange(rec); 
     } 
     return arrangeSize; 
    } 

    private Point GetPosition(Visual element) 
    { 
     var posTransForm = element.TransformToAncestor(this); 
     var areaTransForm = posTransForm.Transform(new Point(0, 0)); 
     return areaTransForm; 
    } 
} 



<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication1" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <local:GridWithMargins ShowGridLines="True"> 
      <Grid.RowDefinitions> 
       <RowDefinition /> 
       <RowDefinition /> 
       <RowDefinition /> 
       <RowDefinition /> 
       <RowDefinition /> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 
      <Rectangle Fill="Red" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
      <Rectangle Fill="Green" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
      <Rectangle Fill="Blue" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
     </local:GridWithMargins> 
    </Grid> 
</Window> 
+0

引發System.ArgumentException:'寬度必須是非負數。' actual.Width - = Math.Min(actual.Width,RowMargin.Left + RowMargin.Right); actual.Height - = Math.Min(actual.Height,RowMargin.Top + RowMargin.Bottom); – 2017-07-17 15:03:51

0

在UWP(Windows10FallCreatorsUpdate及以上版本),你可以在這裏找到

<Grid RowSpacing="3" ColumnSpacing="3">