WPF:带列/行边距/填充的网格?
为WPF网格中的行或列指定边距和/或填充是否容易?WPF:带列/行边距/填充的网格?,wpf,grid,padding,margin,Wpf,Grid,Padding,Margin,为WPF网格中的行或列指定边距和/或填充是否容易? 当然,我可以添加额外的列来分隔内容,但这似乎是一项填充/边距的工作(它将提供更简单的XAML)。是否有人从标准网格派生来添加此功能?RowDefinition和ColumnDefinition属于ContentElement类型,并且Margin严格来说是框架元素属性。所以对于你的问题,“是否容易实现”的答案是一个非常明确的否定。不,我没有看到任何展示这种功能的布局面板 您可以根据建议添加额外的行或列。但您也可以在网格元素本身或网格中的任何内容
当然,我可以添加额外的列来分隔内容,但这似乎是一项填充/边距的工作(它将提供更简单的XAML)。是否有人从标准网格派生来添加此功能?
RowDefinition
和ColumnDefinition
属于ContentElement
类型,并且Margin
严格来说是框架元素
属性。所以对于你的问题,“是否容易实现”的答案是一个非常明确的否定。不,我没有看到任何展示这种功能的布局面板
您可以根据建议添加额外的行或列。但您也可以在
网格
元素本身或网格
中的任何内容上设置边距,因此这是您目前最好的解决方法。您可以编写自己的网格WithMargin
类,继承自网格
,并覆盖ArrangeOverride
方法以应用边距一种可能是添加固定宽度的行和列作为您要查找的填充/边距
你也可以考虑你被容器的大小限制,并且网格会变得和包含元素或者它指定的宽度和高度一样大。您可以简单地使用不设置宽度或高度的列和行。这样,默认情况下,它们将均匀地分割栅格内的总空间。然后,它将只是一个在网格内垂直和水平居中元素的问题
另一种方法可能是将所有网格元素封装在具有固定大小和边距的固定带单行和单列网格中。网格包含固定宽度/高度的框,这些框包含实际元素。您可以使用以下内容:
<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>
或者,如果不需要模板绑定:
<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>
我现在用我的一个网格做了这件事
- 首先对网格内的每个元素应用相同的边距。你可以用风格或任何你喜欢的方式来做这件事。假设水平间距为6px,垂直间距为2px。然后将“3px1px”的边距添加到网格的每个子级
- 然后删除围绕网格创建的边距(如果要将网格内控件的边界与网格的相同位置对齐)。执行此操作时,将网格的边距设置为“-3px-1px”。这样,网格外的其他控件将与网格内的outtermost控件对齐
边框
控件,并为其定义填充:
<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>
资料来源:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<custom:MyRowObject Style="YourStyleHereOrGeneralSetter" Grid.Row="0" />
<custom:MyRowObject Style="YourStyleHere" Grid.Row="1" />
</Grid>
或
如果您使用数据绑定,您的自定义控件也将继承DataContext…这是我个人最喜欢的方法。尽管您不能向网格添加边距或填充,但您可以使用框架(或类似容器)之类的东西,将其应用于网格 这样(如果在按钮上显示或隐藏控件,请单击并说),就不需要在每个可能与其交互的控件上添加边距
可以将其视为将控件组隔离到单元中,然后将样式应用到这些单元。认为我应该添加自己的解决方案,因为还没有人提到这一点。与其基于网格设计UserControl,不如使用样式声明将网格中包含的控件作为目标。注意在所有元素中添加填充/边距,而不必添加样式声明必须为每一个定义,这既麻烦又费力。例如,如果网格只包含文本块,则可以执行以下操作:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="10"/>
</Style>
这类似于“单元格填充”。有时简单的方法是最好的。只需在字符串中填充空格。如果只有几个文本框等,这是迄今为止最简单的方法
您也可以简单地插入具有固定大小的空白列/行。非常简单,您可以轻松地更改它。如创建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>
在uwp中(Windows10FallCreatorsUpdate及以上版本)
我很惊讶我还没有看到这个解决方案发布 来自web的bootstrap等框架将使用负边距来回退行/列
<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>
<Grid RowSpacing="3" ColumnSpacing="3">
<StackPanel>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Grid}">
<Setter Property="Margin" Value="-5 0"/>
</Style>
</Grid.Resources>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="10 0"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Btn 1" />
<Button Grid.Column="1" Content="Btn 2" />
<Button Grid.Column="2" Content="Btn 3" />
</Grid>
</Grid>
<TextBlock FontWeight="Bold" Margin="0 10">
Test
</TextBlock>
</StackPanel>
<!--...-->
<Border Padding="10">
<AnyControl>
<!--...-->
<Grid.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource OurLabelStyle}">
<Style.Triggers>
<Trigger Property="Grid.Column" Value="1">
<Setter Property="Margin" Value="20,0" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>