Pregunta

Dado un StackPanel:

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

¿Cuál es la mejor manera de espaciar los elementos secundarios para que haya espacios del mismo tamaño entre ellos, aunque los elementos secundarios sean de diferentes tamaños?¿Se puede hacer sin establecer propiedades en cada uno de los niños individuales?

¿Fue útil?

Solución

Uso Margen o Relleno, aplicado al alcance dentro del contenedor:

<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:. En caso de que desee volver a utilizar el margen entre los dos contenedores, se puede convertir el valor de margen a un recurso en un ámbito exterior, f.e

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

y, a continuación se refieren a este valor en el ámbito interior

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

Otros consejos

Otro acercamiento agradable se puede ver aquí: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between-items- en-stackpanel.aspx

Se muestra cómo crear un comportamiento adjunto, por lo que la sintaxis como esto funcionaría:

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

Esta es la forma más fácil y más rápido para establecer Margen a varios hijos de un panel, incluso si no son del mismo tipo. (Es decir, botones, cuadros de texto, cuadros combinados, etc.)

he mejorado La respuesta de Elad Katz.

  • Agregue la propiedad LastItemMargin a MarginSetter para manejar especialmente el último elemento
  • Agregue la propiedad adjunta de espaciado con propiedades verticales y horizontales que agrega espacio entre elementos en listas verticales y horizontales y elimina cualquier margen final al final de la lista.

Código fuente en esencia.

Ejemplo:

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

Lo que realmente quiere hacer es envolver todos los elementos secundarios. En este caso se debe utilizar un control de elementos y no recurrir a las propiedades asociadas horribles, que va a llegar a tener un millón de para cada propiedad que desea estilo.

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

introducir descripción de la imagen aquí

1 para la respuesta de Sergey. Y si desea aplicar eso a todas sus StackPanels usted puede hacer esto:

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

Pero cuidado: si se define un estilo como este en su App.xaml (u otro diccionario que se fusionó con los Application.Resources) que puede reemplazar el valor predeterminado estilo del control. Para los controles sobre todo lookless como StackPanel no es un problema, pero para los cuadros de texto, etc se puede tropezar con este problema, que por suerte tiene algunas soluciones.

En seguimiento a la sugerencia de Sergey, se pueden definir y reutilizar todo un estilo (con varios emisores de propiedad, incluida la garantía) en lugar de sólo un objeto Espesor:

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

Tenga en cuenta que el truco aquí es el uso de la herencia del estilo por el estilo implícita, heredando desde el estilo de alguna externa (probablemente se fusionó de archivo XAML externa) diccionario de recursos.

Nota al margen:

Al principio, yo ingenuamente trató de utilizar el estilo implícita para establecer la propiedad Style del control a ese recurso de estilo externa (digamos define con la "MyStyle" llave):

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

que causó Visual Studio 2010 para parar inmediatamente con el error FALLO catastróficos (HRESULT: 0x8000FFFF (E_UNEXPECTED)), tal como se describe en https://connect.microsoft.com/VisualStudio/ retroalimentación / detalles / 753211 / xaml-editor-window-falla-con-cuando-un-estilo-ses-catastrófico fracaso-a-set-estilo-propiedad #

Grid.ColumnSpacing , Grid.RowSpacing , StackPanel.Spacing ahora están en uwp vista previa, toda permitirá mejorar acomplish lo que se solicita aquí.

Estas propiedades son actualmente sólo está disponible con el Windows 10 Caída Creadores de actualización de información privilegiada SDK, pero deben llegar a los bits finales!

El UniformGrid podría no estar disponible en Silverlight, pero alguien ha portado de WPF. http://www.jeff.wilcox.name/2009/01/uniform -grid /

Mi enfoque hereda StackPanel.

Uso:

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

Todo lo que se necesita es la siguiente breve clase:

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

A veces es necesario establecer Relleno, no de margen para hacer espacio entre los elementos más pequeños que por defecto

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top