wpf silverlight xaml stackpanel

wpf panels



¿Cómo espaciado los elementos secundarios de un StackPanel? (10)

+1 a la respuesta de Sergey. Y si desea aplicar eso a todos sus StackPanels, 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 tenga cuidado: si define un estilo como este en su App.xaml (u otro diccionario que se fusione en Application.Resources) puede anular el estilo predeterminado del control. Para los controles casi sin apariencia como el stackpanel, no es un problema, pero para los cuadros de texto, etc., puede tropezar con este problema , que afortunadamente tiene algunas soluciones.

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 existan lagunas de igual tamaño entre ellos, a pesar de que los elementos secundarios en sí mismos son de diferentes tamaños? ¿Se puede hacer sin establecer propiedades en cada uno de los niños?



Lo que realmente quieres hacer es envolver todos los elementos secundarios. En este caso, debe utilizar un control de elementos y no recurrir a propiedades adjuntas horribles, que terminará teniendo un millón por cada propiedad que desea diseñar.

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


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 clase corta:

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


Otro buen enfoque 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-in-stackpanel.aspx

Muestra cómo crear un comportamiento adjunto, para que una sintaxis como esta funcione:

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

Esta es la forma más fácil y rápida de establecer Margen en varios elementos secundarios de un panel, incluso si no son del mismo tipo. (Es decir, Botones, TextBoxes, ComboBoxes, etc.)


Siguiendo la sugerencia de Sergey, puedes definir y reutilizar un Estilo completo (con varios ajustadores de propiedades, incluido el Margen) en lugar de solo un objeto de Grosor:

<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 de estilo para el estilo implícito, que hereda del estilo en algún diccionario de recursos externo (probablemente fusionado con un archivo XAML externo).

Nota al margen:

Al principio, ingenuamente traté de usar el estilo implícito para establecer la propiedad Style del control en ese recurso de estilo externo (por ejemplo, definido con la tecla "MyStyle"):

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

lo que provocó que Visual Studio 2010 se apagara inmediatamente con el error CATASTROPHIC FAILURE (HRESULT: 0x8000FFFF (E_UNEXPECTED)), como se describe en https://connect.microsoft.com/VisualStudio/feedback/details/753211/xaml-editor-window-fails-with-catastrophic-failure-when-a-style-tries-to-set-style-property#


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

EDITAR: en caso de que desee reutilizar el margen entre dos contenedores, puede convertir el valor de margen a un recurso en un ámbito externo, fe

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

y luego refiérase a este valor en el alcance interno

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


a veces es necesario configurar el relleno, no el margen para hacer espacio entre los elementos más pequeños que el predeterminado


Grid.ColumnSpacing , Grid.RowSpacing , StackPanel.Spacing están ahora en la vista previa de UWP, todos permitirán realizar mejor lo que aquí se solicita.

Estas propiedades solo están disponibles actualmente con Windows 10 Fall Crecer Update Insider SDK, pero deberían llegar a los últimos bits.


Mejoré 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 los elementos en las listas vertical y horizontal y elimina cualquier margen al final de la lista

Código fuente en gist .

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>