WPF: grelha com margem/enchimento da coluna/linha?
é fácil especificar uma margem e / ou estofamento para linhas ou colunas numa grelha WPF?
Eu poderia, naturalmente, adicionar colunas extra para espaçar as coisas, mas isto parece ser um trabalho para estofar/margens (ele dará Muito XAML simplier). Alguém derivado da grade padrão para adicionar esta funcionalidade?
13 answers
Você poderia escrever a sua própria classe GridWithMargin
, herdada de Grid
, e sobrepor o método ArrangeOverride
para aplicar as margens
RowDefinition
e ColumnDefinition
são do tipo ContentElement
, e Margin
é estritamente uma propriedade FrameworkElement
. Portanto, para a sua pergunta, "é fácil" a resposta é um não muito definitivo. E não, não vi nenhum painel de layout que demonstrasse este tipo de funcionalidade.
Pode adicionar linhas ou colunas extra como sugeriu. Mas você também pode definir margens em um elemento Grid
, ou qualquer coisa que vá dentro de um Grid
, então essa é a sua melhor solução por agora.
Utilize um controlo Border
fora do controlo da célula e defina o enchimento para isso:
<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>
Fonte:
Dava-te jeito algo assim:
<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>
Ou se não precisar das legendas:
<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>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Margin" Value="10"/>
</Style>
Que é o equivalente a"enchimento celular".
- primeiro aplique a mesma margem a todos os elementos da grelha. Você pode fazer isso manualmente, usando estilos, ou o que quiser. Vamos dizer que você quer um espaçamento horizontal de 6px e um espaçamento vertical de 2px. Em seguida, você adiciona margens de "3px 1px" para cada criança da grade.
- depois remova as margens criadas em torno da grelha (se quiser alinhar os contornos dos controlos dentro da grelha com a mesma posição da grelha). Fazer esta configuração uma margem de "- 3px-1px " para a grade. Dessa forma, outros controles fora da grade serão alinhados com os controles mais exteriores dentro da grade.
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<custom:MyRowObject Style="YourStyleHereOrGeneralSetter" Grid.Row="0" />
<custom:MyRowObject Style="YourStyleHere" Grid.Row="1" />
</Grid>
Ou
<StackPanel>
<custom:MyRowObject Style="YourStyleHere" Grid.Row="0" />
<custom:MyRowObject Style="YourStyleHere" Grid.Row="1" />
</StackPanel>
Os seus controlos personalizados também herdarão o texto de dados se o seu utilizar os dados binding...my benefício pessoal favorito desta abordagem.
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>
Uma possibilidade seria adicionar linhas e colunas de largura fixa para agir como o revestimento / margem que você está procurando.
Você também pode considerar que você está limitado pelo tamanho do seu recipiente, e que uma grade se tornará tão grande quanto o elemento contendo ou sua largura e altura especificadas. Você poderia simplesmente usar colunas e linhas sem largura ou altura definida. Dessa forma, eles default para dividir uniformemente o espaço total dentro da grade. Então seria apenas uma questão de centrando os seus elementos verticalmente e horizontalmente dentro da sua grelha.
Outro método pode ser embrulhar todos os elementos da grelha numa grelha fixa com uma única linha e coluna que tenha um tamanho e uma margem fixos. Que a sua grelha contém caixas fixas de largura / altura que contêm os seus elementos reais.
In uwp (Windows10FallCreatorsUpdate version and above)
<Grid RowSpacing="3" ColumnSpacing="3">
Vindo da web, frameworks como o bootstrap irão usar uma margem negativa para retirar linhas / colunas.
Pode ser um pouco descritivo (embora não seja assim tão mau), funciona e os elementos são uniformemente espaçados e dimensionados.No exemplo abaixo eu uso uma raiz StackPanel
para demonstrar como os 3 botões são uniformemente espaçados usando margens. Você poderia usar outros elementos, basta mudar o interior x: Digite de botão para o seu elemento.
A ideia é simples, use uma grelha do lado de fora para puxar as margens dos elementos para fora dos seus limites por metade da quantidade da grelha interna (usando margens negativas), use a grelha interna para espaçar uniformemente os elementos com a quantidade que deseja.
<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>
Embora não possa adicionar margem ou enchimento a uma grelha, pode usar algo como uma moldura (ou um contentor semelhante), a que pode aplicá-la.
Assim (se mostrar ou esconder o controlo num botão, carregue em dizer), não terá de adicionar margem em cada controlo que possa interagir com ele.
Pense nisso como isolando os grupos de controlos em unidades, depois aplicando estilo a essas unidades.
Também pode simplesmente inserir colunas/linhas em branco com um tamanho fixo. Extremamente simples e você pode facilmente mudá-lo.