Pergunta

Dado um StackPanel:

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

Qual é a melhor maneira de espaço os elementos filhos para que não haja lacunas de tamanho igual entre eles, mesmo que a criança próprios elementos são de tamanhos diferentes? isso pode ser feito sem definir propriedades em cada uma das crianças individuais?

Foi útil?

Solução

Uso Margem ou Enchimento, aplicada ao alcance no interior do recipiente:

<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:. No caso de você gostaria de re-utilizar a margem entre dois recipientes, você pode converter o valor de margem para um recurso em um escopo externo, F.E.

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

e, em seguida, referir-se a este valor no âmbito interno

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

Outras dicas

Outra boa abordagem pode ser visto aqui: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between-items- in-stackpanel.aspx

Ele mostra como criar um comportamento anexado, de modo que sintaxe como isso iria funcionar:

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

Esta é a maneira mais fácil e mais rápido para set Margem para vários filhos de um painel, mesmo se eles não são do mesmo tipo. (Ou seja, botões, caixas de texto, ComboBoxes, etc.)

I melhorou Elad Katz' resposta .

  • Adicionar propriedade LastItemMargin para MarginSetter para especialmente lidar com o último item
  • Adicionar Espaçamento propriedade anexada com Vertical e propriedades horizontais que adiciona espaçamento entre os itens em listas verticais e horizontais e elimina qualquer margem à direita no final da lista

código-fonte em essência .

Exemplo:

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

A coisa que você realmente quer fazer é envolver todos os elementos filhos. Neste caso, você deve usar um controle de itens e não recorrer a propriedades horríveis em anexo, que você vai acabar por ter um milhão de para cada propriedade que você deseja 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>

enter descrição da imagem aqui

1 para a resposta de Sergey. E se você quiser aplicar isso a todos os seus StackPanels você pode fazer isso:

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

Mas cuidado: se você definir um estilo como este em sua App.xaml (ou outro dicionário que é incorporada os Application.Resources) que pode substituir o padrão estilo de controle. Para controles principalmente lookless como o StackPanel não é um problema, mas para caixas de texto etc você pode tropeçar em cima este problema , que felizmente tem algumas soluções alternativas.

No seguimento sugestão de Sergey, você pode definir e reutilizar um estilo todo (com vários setters de propriedade, incluindo margem) em vez de apenas um objeto Espessura:

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

Note que o truque aqui é o uso de estilo de herança para o estilo implícito, herdando a partir do estilo em algum exterior (provavelmente fundiu a partir do arquivo XAML externo) dicionário de recursos.

Sidenote:

No início, eu ingenuamente tentou usar o estilo implícita para definir a propriedade Style do controle para que o recurso Estilo externa (digamos definido com a tecla "MyStyle"):

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

que causou Visual Studio 2010 para encerrar imediatamente com CATASTRÓFICA erro de falha (HRESULT: 0x8000FFFF (E_UNEXPECTED)), como descrito em https://connect.microsoft.com/VisualStudio/ Feedback / details / 753211 / xaml-editor-window-falha-com-catastrófica-failure-quando-a-style-tentativas-to-set-style-propriedade #

Grid.ColumnSpacing , Grid.RowSpacing , StackPanel.Spacing estão agora na pré-visualização UWP, todos permitirá melhor acomplish o que é solicitado aqui.

Estas propriedades estão actualmente disponíveis apenas com o Windows 10 Queda Criadores Atualização Insider SDK, mas deve fazê-lo para os bits finais!

O UniformGrid pode não estar disponível em Silverlight, mas alguém tem portado lo do WPF. http://www.jeff.wilcox.name/2009/01/uniform -grid /

A minha abordagem herda 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>

Tudo o que é necessário é a seguinte classe curto:

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

Às vezes você precisa definir o preenchimento, não Margin para dar espaço entre os itens menores do que padrão

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top