Domanda

Dato un StackPanel:

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

Qual è il modo migliore per ripartire gli elementi del bambino in modo che ci siano tutte le stesse dimensioni, le lacune tra di loro, anche se i bambini stessi elementi sono di dimensioni diverse?Può essere fatto senza l'impostazione delle proprietà dei singoli bambini?

È stato utile?

Soluzione

Margine o imbottitura, applicata alla portata all'interno del contenitore:

<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:. Nel caso in cui si vorrebbe riutilizzare il margine tra due contenitori, è possibile convertire il valore del margine a una risorsa in un ambito esterno, f.e

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

e quindi fare riferimento a questo valore del perimetro interno

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

Altri suggerimenti

Un altro approccio bello può essere visto qui: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between-items- in-stackpanel.aspx

Si mostra come creare un comportamento allegato, in modo che la sintassi come questo dovrebbe funzionare:

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

Questo è il modo più semplice e veloce per impostare Margine a diversi bambini di un pannello, anche se non sono dello stesso tipo. (Vale a dire i pulsanti, caselle di testo, ComboBox, ecc.)

Ho migliorato Elad Katz' di risposta.

  • Aggiungere LastItemMargin proprietà MarginSetter appositamente per gestire l'ultimo elemento
  • Aggiungere la Spaziatura proprietà associata con Verticale e Orizzontale proprietà che aggiunge la spaziatura tra gli elementi verticali e orizzontali liste ed elimina finali di margine alla fine della lista

Codice sorgente in gist.

Esempio:

<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 cosa si vuole veramente fare è avvolgere tutti gli elementi figlio. In questo caso è necessario utilizzare un controllo di elementi e non ricorrere alle proprietà orribili allegate che si finirà per avere un milione di per ogni proprietà che si desidera stile.

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

entrare descrizione dell'immagine qui

+1 per la risposta di Sergey. E se si desidera applicare che a tutti i vostri StackPanels si può fare questo:

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

Ma attenzione: se si definisce uno stile come questo nella vostra App.xaml (o un altro dizionario che si fonde nelle Application.Resources) è possono ignorare l'impostazione predefinita stile del controllo. Per i controlli per lo più lookless come lo StackPanel non è un problema, ma per caselle di testo, ecc si può inciampare su questo problema , che ha per fortuna alcune soluzioni.

In seguito il suggerimento di Sergey, è possibile definire e riutilizzare un intero stile (con vari setter di proprietà, tra cui Margine) invece di un oggetto Spessore:

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

Si noti che il trucco è l'uso di stile di eredità per lo stile implicita, che eredita dalla stile in qualche esterno (probabilmente unito da file XAML esterno) dizionario risorse.

Nota a margine:

In un primo momento, ho ingenuamente cercato di usare lo stile implicita per impostare la proprietà Style del controllo a quella risorsa di stile esterno (dire definito con il "MyStyle" chiave):

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

che ha causato Visual Studio 2010 di chiudere immediatamente con l'errore catastrofico fallimento (HRESULT: 0x8000FFFF (E_UNEXPECTED)), come descritto in https://connect.microsoft.com/VisualStudio/ feedback / dettagli / 753.211 / XAML-editore-window-fallisce-con-cui-a-style-cerca-catastrofico fallimento-to-set-stile-proprietà #

Grid.ColumnSpacing , Grid.RowSpacing , StackPanel.Spacing sono ora in UWP anteprima, tutte le permetterà di migliorare compire quanto richiesto qui.

Queste proprietà sono attualmente disponibili solo con Windows 10 Caduta Creatori aggiornamento Insider SDK, ma dovrebbe rendere ai bit finali!

L'UniformGrid potrebbe non essere disponibile in Silverlight, ma qualcuno ha fatto il porting da WPF. http://www.jeff.wilcox.name/2009/01/uniform -grid /

Il mio approccio eredita StackPanel.

Utilizzo:

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

Tutto ciò che serve è la seguente classe breve:

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 volte è necessario impostare il Padding, non è Margine per fare spazio tra gli elementi più piccoli di default

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top