Question

Étant donné un StackPanel:

<StackPanel>
  <TextBox Height="30">Apple</TextBox>
  <TextBox Height="80">Banana</TextBox>
  <TextBox Height="120">Cherry</TextBox>
</StackPanel>

Quelle est la meilleure façon d'espacer les éléments de l'enfant afin qu'il existe des lacunes de taille égale entre eux, même si les éléments enfants eux-mêmes sont de tailles différentes? Peut-il être fait sans la définition des propriétés sur chacun des enfants individuels?

Était-ce utile?

La solution

Utilisation marge ou Padding, appliqué sur la portée à l'intérieur du conteneur:

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Margin" Value="0,10,0,0"/>
        </Style>
    </StackPanel.Resources> 
    <TextBox Text="Apple"/>
    <TextBox Text="Banana"/>
    <TextBox Text="Cherry"/>
</StackPanel>

EDIT:. Si vous voulez réutiliser la marge entre deux conteneurs, vous pouvez convertir la valeur de la marge à une ressource dans un champ extérieur, f.e

<Window.Resources>
    <Thickness x:Key="tbMargin">0,10,0,0</Thickness>
</Window.Resources>

et reportez-vous à cette valeur dans le champ intérieur

<StackPanel.Resources>
    <Style TargetType="{x:Type TextBox}">
        <Setter Property="Margin" Value="{StaticResource tbMargin}"/>
    </Style>
</StackPanel.Resources>

Autres conseils

Une autre approche agréable peut être vu ici: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between-items- en stackpanel.aspx

Il montre comment créer un comportement attaché, de sorte que la syntaxe comme ceci fonctionnerait:

<StackPanel local:MarginSetter.Margin="5">
   <TextBox Text="hello" />
   <Button Content="hello" />
   <Button Content="hello" />
</StackPanel>

Ceci est le plus facile et plus rapide à mettre en marge de plusieurs enfants d'un groupe, même si elles ne sont pas du même type. (Boutons à savoir, TextBoxes, ComboBoxes, etc.)

Je me suis amélioré sur Elad Katz » réponse.

  • Ajouter une propriété LastItemMargin à MarginSetter pour traiter spécialement le dernier élément
  • Ajouter espacement propriété attachée avec verticale et les propriétés horizontales qui ajoute l'espacement entre les éléments dans les listes verticales et horizontales et élimine toute marge de fuite à la fin de la liste

code source dans les GIST .

Exemple:

<StackPanel Orientation="Horizontal" foo:Spacing.Horizontal="5">
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</StackPanel>

<StackPanel Orientation="Vertical" foo:Spacing.Vertical="5">
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</StackPanel>

<!-- Same as vertical example above -->
<StackPanel Orientation="Vertical" foo:MarginSetter.Margin="0 0 0 5" foo:MarginSetter.LastItemMargin="0">
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</StackPanel>

La chose que vous voulez vraiment faire est envelopper tous les éléments enfants. Dans ce cas, vous devez utiliser un contrôle d'éléments et ne pas recourir à des propriétés attachées horribles que vous finirez par avoir un million de pour chaque propriété que vous souhaitez style.

<ItemsControl>

    <!-- target the wrapper parent of the child with a style -->
    <ItemsControl.ItemContainerStyle>
        <Style TargetType="Control">
            <Setter Property="Margin" Value="0 0 5 0"></Setter>
        </Style>
    </ItemsControl.ItemContainerStyle>

    <!-- use a stack panel as the main container -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- put in your children -->
    <ItemsControl.Items>
        <Label>Auto Zoom Reset?</Label>
        <CheckBox x:Name="AutoResetZoom"/>
        <Button x:Name="ProceedButton" Click="ProceedButton_OnClick">Next</Button>
        <ComboBox SelectedItem="{Binding LogLevel }" ItemsSource="{Binding LogLevels}" />
    </ItemsControl.Items>
</ItemsControl>

entrer image description ici

1 pour la réponse de Sergey. Et si vous voulez l'appliquer à tous vos StackPanels que vous pouvez faire ceci:

<Style TargetType="{x:Type StackPanel}">
    <Style.Resources>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Margin" Value="{StaticResource tbMargin}"/>
        </Style>
    </Style.Resources>
</Style>

Mais attention: si vous définissez un style comme celui-ci dans votre App.xaml (ou un autre dictionnaire qui est fusionné dans les Application.Resources) il peut remplacer la valeur par défaut le style du contrôle. Pour la plupart des contrôles lookless comme le StackPanel est pas un problème, mais pour textboxes etc vous pouvez tomber par hasard sur ce problème , qui a heureusement des solutions de contournement.

Faisant suite à la suggestion de Sergey, vous pouvez définir et réutiliser un ensemble de style (avec divers setters de propriété, y compris la marge) au lieu d'un objet Epaisseur:

<Style x:Key="MyStyle" TargetType="SomeItemType">
  <Setter Property="Margin" Value="0,5,0,5" />
  ...
</Style>

...

  <StackPanel>
    <StackPanel.Resources>
      <Style TargetType="SomeItemType" BasedOn="{StaticResource MyStyle}" />
    </StackPanel.Resources>
  ...
  </StackPanel>

Notez que l'astuce ici est l'utilisation du style héritage pour le style implicite, héritant du style dans certains extérieur (probablement fusionné à partir du fichier XAML externe) dictionnaire de ressources.

Sidenote:

Dans un premier temps, je naïvement essayé d'utiliser le style implicite pour définir la propriété Style du contrôle de cette ressource de style externe (par exemple défini avec la touche « MyStyle »):

<StackPanel>
  <StackPanel.Resources>
    <Style TargetType="SomeItemType">
      <Setter Property="Style" Value={StaticResource MyStyle}" />
    </Style>
  </StackPanel.Resources>
</StackPanel>

qui a causé Visual Studio 2010 pour arrêter immédiatement avec l'erreur CATASTROPHIQUE PANNE (HRESULT: 0x8000FFFF (E_UNEXPECTED)), comme décrit à https://connect.microsoft.com/VisualStudio/ commentaires / détails / 753211 / XAML-éditeur-fenêtre échoue avec catastrophique en cas de panne lors d'un-style-tente-set à style propriété #

Grid.ColumnSpacing , Grid.RowSpacing , StackPanel.Spacing sont maintenant aperçu UWP, tout permettra de mieux acomplish ce qui est demandé ici.

Ces propriétés sont actuellement disponibles avec les créateurs d'automne de Windows Update 10 Insider SDK, mais devrait le faire aux bits finaux!

Le UniformGrid pourrait ne pas être disponible dans Silverlight, mais quelqu'un a porté à partir de WPF. http://www.jeff.wilcox.name/2009/01/uniform -grid /

Mon approche hérite StackPanel.

Utilisation:

<Controls:ItemSpacer Grid.Row="2" Orientation="Horizontal" Height="30" CellPadding="15,0">
    <Label>Test 1</Label>
    <Label>Test 2</Label>
    <Label>Test 3</Label>
</Controls:ItemSpacer>

Tout ce qui est nécessaire est court la classe suivante:

using System.Windows;
using System.Windows.Controls;
using System;

namespace Controls
{
    public class ItemSpacer : StackPanel
    {
        public static DependencyProperty CellPaddingProperty = DependencyProperty.Register("CellPadding", typeof(Thickness), typeof(ItemSpacer), new FrameworkPropertyMetadata(default(Thickness), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnCellPaddingChanged));
        public Thickness CellPadding
        {
            get
            {
                return (Thickness)GetValue(CellPaddingProperty);
            }
            set
            {
                SetValue(CellPaddingProperty, value);
            }
        }
        private static void OnCellPaddingChanged(DependencyObject Object, DependencyPropertyChangedEventArgs e)
        {
            ((ItemSpacer)Object).SetPadding();
        }

        private void SetPadding()
        {
            foreach (UIElement Element in Children)
            {
                (Element as FrameworkElement).Margin = this.CellPadding;
            }
        }

        public ItemSpacer()
        {
            this.LayoutUpdated += PART_Host_LayoutUpdated;
        }

        private void PART_Host_LayoutUpdated(object sender, System.EventArgs e)
        {
            this.SetPadding();
        }
    }
}

il faut parfois mettre Rembourrage, pas de marge pour faire l'espace entre les éléments plus petits que par défaut

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top