2009-08-24 98 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">