WPF: Gitter mit Spalten- / Zeilenrand / Auffüllung?


137

Ist es leicht möglich, einen Rand und / oder eine Auffüllung für Zeilen oder Spalten in einem WPF-Raster anzugeben?

Ich könnte natürlich zusätzliche Spalten hinzufügen, um Dinge auszuräumen , aber dies scheint ein Job für Auffüllen / Ränder zu sein (es wird viel einfacheres XAML geben). Hat jemand aus dem Standard-Grid abgeleitet, um diese Funktionalität hinzuzufügen?


4
Ein nützliches Beispiel finden Sie hier: codeproject.com/Articles/107468/WPF-Padded-Grid
peter70

2
Ein bisschen verwirrt, dass dies nicht Teil der
Grundfunktionen

Bis heute, wie aus 10 Jahren Antworten hervorgeht, ist die Wahrheit, dass dies nicht einfach möglich ist. Das Beste (um zusätzliche fehleranfällige Arbeit bei jeder Verwendung einer Zelle zu vermeiden) ist die Ableitung des Rasters (wie zuvor von @ peter70 vorgeschlagen) ), um die entsprechende Abhängigkeitseigenschaft für das Auffüllen von Zellen hinzuzufügen, die die Margin-Eigenschaft des untergeordneten Zellenelements steuert. Dies ist keine lange Aufgabe, und dann haben Sie eine wiederverwendbare Kontrolle. Nebenbemerkung ... Grid ist wirklich eine schlecht gestaltete Steuerung.
Minuten

Antworten:


10

Sie können Ihre eigene GridWithMarginKlasse schreiben , von der geerbt wird Grid, und die ArrangeOverrideMethode zum Anwenden der Ränder überschreiben


31
Ich verstehe nicht, warum Leute dir Daumen hoch geben, weil es alles andere als einfach ist, wie du hier denkst / beschreibst. Versuchen Sie es einfach 30 Minuten lang und Sie werden schnell feststellen, dass Ihre Antwort nicht zutreffend ist. Denken Sie auch an das Überspannen von Zeilen und Spalten
Eric Ouellet

89

RowDefinitionund ColumnDefinitionsind vom Typ ContentElementund Marginsind ausschließlich eine FrameworkElementEigenschaft. Auf Ihre Frage "Ist es leicht möglich?" Lautet die Antwort mit einem eindeutigen Nein. Und nein, ich habe keine Layout-Panels gesehen, die diese Art von Funktionalität demonstrieren.

Sie können wie vorgeschlagen zusätzliche Zeilen oder Spalten hinzufügen. Sie können aber auch Ränder für ein GridElement selbst oder für alles festlegen, was in ein Element passt. Dies Gridist Ihre derzeit beste Problemumgehung.


OP versucht nicht, einen Rand für RowDefinition oder ColumnDefinition festzulegen. Er versucht, einen Rand für die visuellen untergeordneten Elemente des Rasters festzulegen, die von FrameworkElement abgeleitet sind.
15ee8f99-57ff-4f92-890c-b56153

57

Verwenden Sie ein BorderSteuerelement außerhalb des Zellensteuerelements und definieren Sie die Auffüllung dafür:

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


Quelle:


2
@RichardEverett Check the Way Back Machine: Link als Antwort aktualisiert.
CJBS

Diese Antwort gefällt mir am besten. Es bietet eine Lösung für die ursprüngliche Frage und ist unkompliziert. Vielen Dank!
Tobias

Dies ist einfach und praktisch
Aggsol

19

Sie könnten so etwas verwenden:

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

Oder wenn Sie die TemplateBindings nicht benötigen:

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

28
Vielen Dank an JayGee, diese Lösung ist jedoch für das DataGrid - nicht für das Standard-Grid-Steuerelement.
Brad Leach

Durch Klicken auf den Auffüllbereich wird die Zeile nicht mehr ausgewählt.
jor

9

Ich dachte, ich würde meine eigene Lösung hinzufügen, weil dies noch niemand erwähnt hat. Anstatt ein UserControl basierend auf Grid zu entwerfen, können Sie Steuerelemente, die in Grid enthalten sind, mit einer Stildeklaration als Ziel festlegen. Kümmert sich um das Hinzufügen von Auffüllungen / Rändern zu allen Elementen, ohne dass für jedes Element eine Definition erforderlich ist. Dies ist umständlich und arbeitsintensiv. Wenn Ihr Raster beispielsweise nur TextBlocks enthält, können Sie Folgendes tun:

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

Welches ist wie das Äquivalent von "Cell Padding".


rieselt das runter? Wenn Sie beispielsweise ein Stackpanel in einer Rasterzeile haben, erben die untergeordneten Textblock-Elemente des Stackpanels diese Eigenschaft?
Maslow

Ich bin mir nicht sicher, ob es an unmittelbaren Kindern vorbeizieht, aber Sie können es mit einem einfachen Test herausfinden.
James M

2
@ Maslow Die Antwort lautet absolut "Ja", aber Ihre Formulierung ist etwas irreführend. Es gibt kein "Erben" der MarginEigenschaft, es ist so, dass jedes Stylein einem ResourceDictionaryTestament für jedes Element von TargetTypeüberall im gesamten Bereich des Eigentümerelements dieses Wörterbuchs gilt. Es ist also das Style, was rieselt, nicht das Eigentum.
Glenn Slayden

8

Das ist nicht besonders schwierig. Ich kann nicht sagen, wie schwierig es 2009 war, als die Frage gestellt wurde, aber das war es dann.

Beachten Sie, dass, wenn Sie bei Verwendung dieser Lösung explizit einen Rand direkt für ein untergeordnetes Element des Rasters festlegen, dieser Rand im Designer angezeigt wird, jedoch nicht zur Laufzeit.

Diese Eigenschaft kann auf Grid, StackPanel, WrapPanel, UniformGrid oder jeden anderen Nachkommen von Panel angewendet werden. Es betrifft unmittelbare Kinder. Es wird davon ausgegangen, dass Kinder das Layout ihrer eigenen Inhalte verwalten möchten.

PanelExt.cs

public static class PanelExt
{
    public static Thickness? GetChildMargin(Panel obj)
    {
        return (Thickness?)obj.GetValue(ChildMarginProperty);
    }

    public static void SetChildMargin(Panel obj, Thickness? value)
    {
        obj.SetValue(ChildMarginProperty, value);
    }

    /// <summary>
    /// Apply a fixed margin to all direct children of the Panel, overriding all other margins.
    /// Panel descendants include Grid, StackPanel, WrapPanel, and UniformGrid
    /// </summary>
    public static readonly DependencyProperty ChildMarginProperty =
        DependencyProperty.RegisterAttached("ChildMargin", typeof(Thickness?), typeof(PanelExt),
            new PropertyMetadata(null, ChildMargin_PropertyChanged));

    private static void ChildMargin_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var target = d as Panel;

        target.Loaded += (s, e2) => ApplyChildMargin(target, (Thickness?)e.NewValue);

        ApplyChildMargin(target, (Thickness?)e.NewValue);
    }

    public static void ApplyChildMargin(Panel panel, Thickness? margin)
    {
        int count = VisualTreeHelper.GetChildrenCount(panel);

        object value = margin.HasValue ? margin.Value : DependencyProperty.UnsetValue;

        for (var i = 0; i < count; ++i)
        {
            var child = VisualTreeHelper.GetChild(panel, i) as FrameworkElement;

            if (child != null)
            {
                child.SetValue(FrameworkElement.MarginProperty, value);
            }
        }
    }
}

Demo:

MainWindow.xaml

<Grid
    local:PanelExt.ChildMargin="2"
    x:Name="MainGrid"
    >
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Rectangle Width="100" Height="40" Fill="Red" Grid.Row="0" Grid.Column="0" />
    <Rectangle Width="100" Height="40" Fill="Green" Grid.Row="1" Grid.Column="0" />
    <Rectangle Width="100" Height="40" Fill="Blue" Grid.Row="1" Grid.Column="1" />

    <Button Grid.Row="2" Grid.Column="0" Click="NoMarginClick">No Margin</Button>
    <Button Grid.Row="2" Grid.Column="1" Click="BigMarginClick">Big Margin</Button>
    <ComboBox Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" />
</Grid>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void NoMarginClick(object sender, RoutedEventArgs e)
    {
        //  In real life, if we wanted to change PanelExt.ChildMargin at runtime, we 
        //  would prefer to bind it to something, probably a dependency property of 
        //  the view. But this will do for a demonstration. 
        PanelExt.SetChildMargin(MainGrid, null);
    }
    private void BigMarginClick(object sender, RoutedEventArgs e)
    {
        PanelExt.SetChildMargin(MainGrid, new Thickness(20));
    }
}

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein


Wissen Sie, warum Ihre Antwort abgelehnt wird? Scheint eine funktionierende Lösung für das Problem von OP zu sein
System

4
@thesystem Ich denke, jemand hat sich über etwas aufgeregt. Keine große Sache. Aber vielleicht gibt es einen Fehler, den ich verpasst habe. Es passiert.
15ee8f99-57ff-4f92-890c-b56153

hast du dw, weil es eine benötigt buildoder runbevor die Live-Vorschau angezeigt werden kann? Gut und einfach. 1 auf.
Meow Cat 2012

3

Ich bin kürzlich bei der Entwicklung von Software auf dieses Problem gestoßen und habe gefragt, warum? Warum haben sie das getan ... die Antwort war genau dort vor mir. Eine Datenzeile ist ein Objekt. Wenn wir also die Objektorientierung beibehalten, sollte das Design für eine bestimmte Zeile getrennt sein (vorausgesetzt, Sie müssen die Zeilenanzeige später in der Zukunft wiederverwenden). Daher habe ich begonnen, datengebundene Stapelfenster und benutzerdefinierte Steuerelemente für die meisten Datenanzeigen zu verwenden. Gelegentlich werden Listen angezeigt, aber meistens wurde das Raster nur für die primäre Seitenorganisation verwendet (Kopfzeile, Menübereich, Inhaltsbereich, Andere Bereiche). Ihre benutzerdefinierten Objekte können problemlos alle Abstandsanforderungen für jede Zeile innerhalb des Stapelbedienfelds oder Rasters verwalten (eine einzelne Rasterzelle kann das gesamte Zeilenobjekt enthalten. Dies hat auch den zusätzlichen Vorteil, dass Sie ordnungsgemäß auf Änderungen der Ausrichtung reagieren können.

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

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

oder

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

Ihre benutzerdefinierten Steuerelemente erben auch den DataContext, wenn Sie Datenbindung verwenden ... mein persönlicher Lieblingsvorteil dieses Ansatzes.


Sie haben hier versucht, eine Rohversion des WPF- ListViewSteuerelements im GridViewModus zu erstellen , ohne jedoch vorzusehen, dass alle „RowObjects“ dieselbe Spaltenbreite haben. In Wirklichkeit hat es nicht mehr viel mit einem Grid zu tun.
Glenn Slayden

3

in uwp (Windows10FallCreatorsUpdate-Version und höher)

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

Dies gilt auch für Xamarin.Forms.
James M

3

Bearbeitet:

Um einem Steuerelement einen Spielraum zu geben, können Sie das Steuerelement mit einem solchen Rahmen umschließen

<!--...-->
    <Border Padding="10">
            <AnyControl>
<!--...-->

Das OP-Problem besteht nicht darin, einen Rand um das Gitter herum zu haben, sondern einen Rand um Gitterzellen (oder wie tatsächlich um Zeilen und Spalten gefragt, was später durch den Kommentar " Hinzufügen der zusätzlichen Spalten / Zeilen ist genau das, was ich zu vermeiden versuchte " widersprochen wird ). .
Minuten

2

Ich habe es gerade mit einem meiner Gitter gemacht.

  • Wenden Sie zunächst auf jedes Element im Raster den gleichen Rand an. Sie können dies manuell tun, indem Sie Stile verwenden oder was auch immer Sie möchten. Nehmen wir an, Sie möchten einen horizontalen Abstand von 6 Pixel und einen vertikalen Abstand von 2 Pixel. Dann fügen Sie jedem untergeordneten Element des Rasters Ränder von "3px 1px" hinzu.
  • Entfernen Sie dann die Ränder, die um das Raster erstellt wurden (wenn Sie die Ränder der Steuerelemente innerhalb des Rasters an derselben Position des Rasters ausrichten möchten). Stellen Sie dazu einen Rand von "-3px -1px" für das Raster ein. Auf diese Weise werden andere Steuerelemente außerhalb des Rasters an den äußersten Steuerelementen innerhalb des Rasters ausgerichtet.

Das Anwenden des gleichen Randes auf jedes Element innerhalb des Rasters scheint der einfachste Weg zu sein.
Envil

1

Eine Möglichkeit wäre, Zeilen und Spalten mit fester Breite hinzuzufügen, um als Auffüllung / Rand zu fungieren, den Sie suchen.

Sie können auch berücksichtigen, dass Sie durch die Größe Ihres Containers eingeschränkt sind und dass ein Raster so groß wird wie das enthaltende Element oder die angegebene Breite und Höhe. Sie können einfach Spalten und Zeilen ohne festgelegte Breite oder Höhe verwenden. Auf diese Weise wird standardmäßig der gesamte Raum innerhalb des Rasters gleichmäßig aufgeteilt. Dann wäre es nur eine Sache, Ihre Elemente vertikal und horizontal innerhalb Ihres Gitters zu zentrieren.

Eine andere Methode könnte darin bestehen, alle Gitterelemente in ein festes Gitter mit einer einzelnen Zeile und Spalte zu verpacken, das eine feste Größe und einen festen Rand hat. Dass Ihr Raster Felder mit fester Breite / Höhe enthält, die Ihre tatsächlichen Elemente enthalten.


1
Vielen Dank, Adam, aber das Hinzufügen der zusätzlichen Spalten / Zeilen ist genau das, was ich vermeiden wollte. Ich möchte einfach mein Markup reduzieren und die Möglichkeit, einen Rand oder eine Auffüllung anzugeben, würde dabei helfen.
Brad Leach

Sie müssen nur die zusätzlichen Spalten und Zeilen definieren, nicht die Markierung für sie. Wenn Sie beispielsweise N-Breite zwischen Spalten für 3 Spalten hinzufügen möchten, haben Sie 5 Spaltendefinitionen. Die erste wäre die automatische Breite und die nächste fest, dann automatisch, dann fest, dann automatisch. Ordnen Sie dann nur den tatsächlichen Inhaltselementen die Spalten 1, 3 und 5 zu. Ich verstehe Ihren Standpunkt zum zusätzlichen Spalten-Markup, aber wenn Sie nicht Hunderte von Elementen haben, erscheint mir das trivial. Ihr Anruf aber. Haben Sie auch versucht, ein Stapelfeld aus Stapelfeldern mit festgelegten Rändern zu verwenden?
Adam Lenda

In meinem Fall war das Hinzufügen einer Spalte "Splitter / Rand" bei weitem am saubersten und einfachsten. Vielen Dank!
jchristof

1

Ich hatte kürzlich ein ähnliches Problem in einem zweispaltigen Raster. Ich brauchte nur einen Rand für Elemente in der rechten Spalte. Alle Elemente in beiden Spalten waren vom Typ TextBlock.

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

0

Obwohl Sie einem Raster keinen Rand oder Abstand hinzufügen können, können Sie einen Rahmen (oder einen ähnlichen Container) verwenden, auf den Sie ihn anwenden können.

Auf diese Weise (wenn Sie das Steuerelement auf einem Schaltflächenklick ein- oder ausblenden) müssen Sie nicht für jedes Steuerelement, das mit ihm interagieren kann, einen Rand hinzufügen.

Stellen Sie sich vor, Sie isolieren die Gruppen von Steuerelementen in Einheiten und wenden dann Stil auf diese Einheiten an.


0

Wie bereits erwähnt, erstellen Sie eine GridWithMargins-Klasse. Hier ist mein Arbeitscodebeispiel

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

Verwendung:

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

1
Löst System.ArgumentException aus: 'Breite darf nicht negativ sein.' actual.Width - = Math.Min (actual.Width, RowMargin.Left + RowMargin.Right); actual.Height - = Math.Min (actual.Height, RowMargin.Top + RowMargin.Bottom);
Jamie Mellway

Mit Jamies Fix läuft es, tut aber immer noch nicht das, was es sollte. Wenn die Zeilenhöhe und Spaltenbreite auf Auto eingestellt ist, wird das Falsche anders ausgeführt.
15ee8f99-57ff-4f92-890c-b56153

0

Ich bin überrascht, dass ich diese Lösung noch nicht veröffentlicht habe.

Frameworks wie Bootstrap kommen aus dem Web und verwenden einen negativen Rand, um Zeilen / Spalten zurückzuziehen.

Es könnte ein wenig ausführlich sein (wenn auch nicht so schlimm), es funktioniert und die Elemente sind gleichmäßig verteilt und bemessen.

Im folgenden Beispiel verwende ich eine StackPanelWurzel, um zu demonstrieren, wie die 3 Schaltflächen mithilfe von Rändern gleichmäßig verteilt sind. Sie können auch andere Elemente verwenden. Ändern Sie einfach den inneren x: Typ von der Schaltfläche in Ihr Element.

Die Idee ist einfach: Verwenden Sie ein Raster an der Außenseite, um die Ränder von Elementen um die Hälfte des inneren Rasters (unter Verwendung negativer Ränder) aus ihren Grenzen herauszuziehen. Verwenden Sie das innere Raster, um die Elemente gleichmäßig mit dem gewünschten Betrag zu platzieren.

Update: Einige Kommentare eines Benutzers sagten, dass es nicht funktioniert. Hier ist ein kurzes Video, das zeigt: https://youtu.be/rPx2OdtSOYI

Geben Sie hier die Bildbeschreibung ein

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

1
Mein Fehler - ich habe den impliziten Button-Stil nicht bemerkt. Ich war abgelenkt von den negativen Margen.
15ee8f99-57ff-4f92-890c-b56153

-6

Manchmal ist die einfache Methode die beste. Füllen Sie einfach Ihre Saiten mit Leerzeichen. Wenn es sich nur um wenige Textfelder usw. handelt, ist dies bei weitem die einfachste Methode.

Sie können auch einfach leere Spalten / Zeilen mit einer festen Größe einfügen. Sehr einfach und Sie können es leicht ändern.


Wahrscheinlich, weil es keine sehr gute Methode ist. Das Verwenden von Leerzeichen mag der "einfache Ausweg" sein, aber es ist eigentlich eher ein Hack. Es ist nicht präzise, ​​es kann (und wird wahrscheinlich) auf Monitoren mit einer anderen Skalierung unterschiedlich und unzuverlässig gerendert werden, und Sie haben keine Kontrolle über die genaue Menge an Speicherplatz, die Sie erstellen. Einfügen von leeren Spalten / Zeilen werden ein Durcheinander von Ihrem Grid machen ...
Mark
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.