WPF:具有列/行边距/填充的网格?

是否可以轻松地为WPF Grid中的行或列指定边距和/或填充?

我当然可以添加额外的列空间的东西,但这似乎是一个填充/边距的工作(这将给予简单的XAML)。 有人从标准网格派生出来添加这个function吗?

您可以编写自己的GridWithMargin类,从Gridinheritance,并重写ArrangeOverride方法以应用边距

RowDefinitionColumnDefinitionContentElementtypes, Margin是一个FrameworkElement属性。 所以对于你的问题, “这是否容易” ,答案是肯定的。 不,我还没有看到任何展示这种function的布局面板。

您可以按照您的build议添加额外的行或列。 但是,您也可以在Grid元素上设置边距,也可以在Grid设置边距,这是目前最好的解决方法。

你可以使用这样的东西:

 <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> 

在单元格控件外部使用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> 

资源:

  • 原始来源
  • 和从后面的机器

我现在用我的一个网格做了。

  • 首先对网格中的每个元素应用相同的边距。 你可以做这个mannualy,使用风格,或任何你喜欢的。 可以说你想要一个6px的水平间距和一个2px的垂直间距。 然后,为网格的每个子节点添加“3px 1px”的边距。
  • 然后删除在网格周围创build的边距(如果要将网格内控件的边框alignment到网格的相同位置)。 这样做是为网格设置一个“-3px -1px”的边距。 这样,网格外的其他控件将与网格内的outtermost控件alignment。

我最近在开发一些软件的时候遇到了这个问题,并且问我为什么要问这个问题? 他们为什么这样做呢?答案就在我面前。 一行数据是一个对象,所以如果我们保持对象的方向,那么特定行的devise应该是分开的(假设你将来需要重新使用行显示)。 所以我开始使用数据绑定堆栈面板和大多数数据显示的自定义控件。 列表偶尔会出现,但大多数网格仅用于主页面组织(标题,菜单区域,内容区域,其他区域)。 您的自定义对象可以轻松地pipe理堆栈面板或网格中每一行的任何间距要求(一个网格单元格可以包含整个行对象,还可以正确反应方向的变化,展开/折叠等等。

 <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> 

你的自定义控件也将inheritanceDataContext,如果你使用数据绑定…我个人最喜欢这种方法的好处。

如前所述创build一个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> 

以为我会加我自己的解决scheme,因为没有人提到这一点。 而不是devise一个基于网格的UserControl,你可以用一个样式声明来定位包含在网格中的控件。 注意为所有元素添加填充/边距,而不必为每个元素定义,这是繁琐和劳动密集型的。例如,如果您的网格只包含TextBlocks,则可以这样做:

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

这就像“细胞填充”的等价物。

一种可能性是添加固定宽度的行和列来充当你正在寻找的填充/保证金。

你也可能会认为你受到容器大小的限制,并且一个网格将变得与包含元素或其指定的宽度和高度一样大。 您可以简单地使用没有设置宽度或高度的列和行。 这样他们默认均匀分解网格内的总空间。 那么这只是将你的元素在你的网格中垂直和水平居中的主要原因。

另一种方法可能是将所有网格元素封装在具有固定大小和边距的单行和列网格中。 您的网格包含固定的宽度/高度框,其中包含您的实际元素。

虽然你不能为网格添加边距或者填充,但是你可以使用类似于Frame(或者类似的容器)的东西,你可以把它应用到。

这样(如果你显示或隐藏控制button上单击说),你不会需要添加每个控件可能交互的余地。

把它看作是把控制组分成单元,然后把风格应用到这些单元。

有时候简单的方法是最好的。 只需用空格填充你的string。 如果只有几个文本框等,这是迄今为止最简单的方法。

您也可以简单地插入固定大小的空白列/行。 非常简单,你可以很容易地改变它。