J'ai un ensemble de paires clé/valeur que je souhaite afficher sur une fenêtre WPF. J'utilise une grille pour les disposer comme suit:
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0">Code</Label>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Code}"/>
<Label Grid.Row="1" Grid.Column="0">Name</Label>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Name}"/>
</Grid>
Cependant, lorsque j'affiche cela, les TextBox sont écrasées avec leurs bordures supérieure et inférieure touchant la TextBox au-dessus/en dessous. Quelle est la meilleure façon d'ajouter de l'espace vertical aux lignes de cette disposition?
Le moyen le plus simple consiste à définir une marge sur les commandes individuelles. Le définir sur les TextBox devrait être suffisant, car une fois qu'ils sont espacés, les étiquettes se positionneront verticalement au centre de chaque ligne et auront de toute façon beaucoup d'espace.
Vous pouvez le définir une fois en utilisant un style:
<Grid Margin="4">
<Grid.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="0,0,0,4" />
</Style>
</Grid.Resources>
...
</Grid>
Cela ajoutera une marge de 4 pixels au bas de n'importe quel TextBox à l'intérieur de votre grille.
Une autre belle approche peut être vue ici .
Vous créez une classe pour définir la propriété Margin
:
public class MarginSetter
{
public static Thickness GetMargin(DependencyObject obj) => (Thickness)obj.GetValue(MarginProperty);
public static void SetMargin(DependencyObject obj, Thickness value) => obj.SetValue(MarginProperty, value);
// Using a DependencyProperty as the backing store for Margin. This enables animation, styling, binding, etc…
public static readonly DependencyProperty MarginProperty =
DependencyProperty.RegisterAttached(nameof(FrameworkElement.Margin), typeof(Thickness),
typeof(MarginSetter), new UIPropertyMetadata(new Thickness(), MarginChangedCallback));
public static void MarginChangedCallback(object sender, DependencyPropertyChangedEventArgs e)
{
// Make sure this is put on a panel
var panel = sender as Panel;
if (panel == null) return;
panel.Loaded += Panel_Loaded;
}
private static void Panel_Loaded(object sender, EventArgs e)
{
var panel = sender as Panel;
// Go over the children and set margin for them:
foreach (FrameworkElement fe in panel.Children.OfType<FrameworkElement>())
fe.Margin = GetMargin(panel);
}
}
Vous avez maintenant attaché le comportement des propriétés, de sorte que la syntaxe comme celle-ci fonctionne:
<StackPanel local:MarginSetter.Margin="5">
<TextBox Text="hello" />
<Button Content="hello" />
<Button Content="hello" />
</StackPanel>
C'est le moyen le plus simple et le plus rapide de définir Margin
sur plusieurs enfants d'un panneau, même s'ils ne sont pas du même type. (C'est-à-dire Button
s, TextBox
es, ComboBox
es, etc.)
Qu'en est-il de la configuration de l'alignement vertical de TextBox au centre?
<Grid Margin="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0">Code</Label>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Code}" VerticalAlignment="Center"/>
<Label Grid.Row="1" Grid.Column="0">Name</Label>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Name}" VerticalAlignment="Center"/>
</Grid>