Bir StackPanel'in alt öğelerini nasıl boşluk bırakabilirim?


187

Bir StackPanel verildi:

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

Alt öğelerin kendileri farklı boyutlarda olmalarına rağmen, aralarında eşit boyutta boşluklar olmasını sağlamak için alt öğeleri ayırmanın en iyi yolu nedir? Her bir çocuğa özellik koymadan yapılabilir mi?


Gerçekten sadece tek tek öğelere dolgu eklemek en iyi seçenek gibi görünüyor.
zar

Yanıtlar:


278

Konteyner içindeki kapsama uygulanan Kenar Boşluğu veya Dolgu kullanın:

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

DÜZENLEME: İki kapsayıcı arasındaki kenar boşluğunu yeniden kullanmak isterseniz, kenar boşluğu değerini dış bir kapsamdaki bir kaynağa dönüştürebilirsiniz.

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

ve iç değerdeki bu değere bakın

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

5
Kapsamlı Stil bunu yapmak için harika bir yoldur - ipucu için teşekkürler!
Ana Betts

2
Tüm proje için kullanmak istersem ne olur?
grv_9098

10
Birisi bunun neden yalnızca türü (örneğin TextBox) açıkça tanımladığınızda işe yaradığını açıklayabilir mi? Bunu tüm çocukların aralıklı olmasını sağlamak için FrameworkElement kullanarak denersem, hiçbir etkisi olmaz.
Jack Ukleja

4
Zaten bir stil tanımladıysanız bu işe yaramaz Button.
Mark Ingram

1
Eğer bir ile bunu istiyorum Bir yan not olarak, Labelkullanmak zorunda PaddingyerineMargin
Anthony Nichols

84

Başka bir hoş yaklaşım burada görülebilir: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between- items-in-stackpanel.aspx Bağlantı koptu -> bu, bu bağlantının web arşividir .

Ekli bir davranışın nasıl oluşturulacağını gösterir, böylece böyle bir sözdizimi işe yarar:

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

Bu, aynı türden olmasalar bile, bir panelin birkaç çocuğuna Kenar Boşluğu ayarlamanın en kolay ve en hızlı yoludur. (Yani Düğmeler, Metin Kutuları, Açılan Kutular vb.)


5
Bu konuda oldukça ilginç bir yol. Tam olarak şeyleri nasıl yerleştirmek istediğinize dair birçok varsayım yapar ve hatta ilk / son öğelerin kenar boşluklarını otomatik olarak ayarlama fırsatı verir.
Ermenistan

2
Çok yönlülük için +1. Ayrıca blog yazısı üzerinde geliştirmek için, if (fe.ReadLocalValue(FrameworkElement.MarginProperty) == DependencyProperty.UnsetValue)aslında çocuğun kenar boşluğunu ayarlamadan önce ekleyerek bazı elemanlar için kenar boşluklarını manuel olarak belirlemenizi sağlar.
Xerillio

Değişen bir koleksiyona bağlı ItemsControl öğesinde olduğu gibi alt öğeler dinamik olarak eklenirse / kaldırılırsa bunun çalışmadığını unutmayın.
Drew Noakes

1
Çalışmaması durumunda: Projeyi derleyin, aksi takdirde sayfayı oluşturmaz.
Savaşı

2
Bağlantı koptu!
Dave

13

Üzerinde geliştirilmiş Elad Katz' cevabı .

  • Son öğeyi özel olarak işlemek için MarginSetter'e LastItemMargin özelliği ekleyin
  • Dikey ve yatay listelerdeki öğeler arasına boşluk ekleyen ve listenin sonundaki boşlukları ortadan kaldıran Dikey ve Yatay özelliklerle Boşluk ekli özellik ekle

Gist'teki kaynak kodu .

Misal:

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

Elad'ın yanıtı gibi, alt öğeler, ItemsControldeğişen bir koleksiyona bağlı gibi dinamik olarak eklenirse / kaldırılırsa bu işe yaramaz . Ebeveynin Loadolayı başladığı andan itibaren öğelerin statik olduğunu varsayar .
Drew Noakes

Ayrıca, özgeçmişiniz bir 404 verir.
Drew Noakes

Gist bağlantısı güncellendi.
angularsen

9

Gerçekten yapmak istediğiniz şey, tüm alt öğeleri sarmaktır. Bu durumda, bir eşya kontrolü kullanmalı ve stil vermek istediğiniz her mülk için bir milyona sahip olacağınız korkunç ekli özelliklere başvurmamalısınız.

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

resim açıklamasını buraya girin


Harika bir ipucu, ancak bu Stil TargetType ile "FrameworkElement" olarak daha iyi çalışır (aksi takdirde Image için çalışmaz)
Puffin

1
Bu fikri seviyorum. Sadece bir ek: StackPanel ( Margin="0 0 -5 0") kenar boşluğundan boşluk miktarını çıkarmak , listedeki son öğeden sonraki boşluğu da sayacaktır .
etiket17

Buradaki sorun, ayarladığınız stilin Öğeler üzerinde bulunabilecek diğer stilleri geçersiz kılmasıdır. Bunun üstesinden gelmek için buradaki
waxingsatirical

6

Sergey'in cevabı için +1. Ve bunu tüm StackPanels'larınıza uygulamak istiyorsanız bunu yapabilirsiniz:

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

Ancak dikkat: Eğer (Application.Resources birleştirilir ya da başka bir sözlüğe) sizin App.xaml böyle bir stil tanımlayabilir eğer yapabilirsiniz denetimin varsayılan stili geçersiz kılar. Stackpanel gibi çoğunlukla göze çarpmayan kontroller için bu bir sorun değildir, ancak metin kutuları vb . İçin Neyse ki bazı geçici çözümlere sahip olan bu sorunla karşılaşabilirsiniz .


<Style.Resources> u denedim ne zaman bu coz hata gösteriyor eminim.
grv_9098

Üzgünüm, elden geçenleri hatırlayamıyorum. Görmek için kendim denemeliyim. Sana geri döneceğim.
Andre Luus

Evet, işe yarıyor. Bir StackPanel tüm TextBlocks TextWeight = "Kalın" ayarlamak için de aynısını yaptı. Tek fark tarzı açıkça StackPanel ayarlamak oldu.
Andre Luus

İlginiz için teşekkürler, ancak hala şüphem var, bunun Kapsam Stili adını verdiğini biliyorum. Sanırım <Style.Resources> değil, <StackPanel.Resources> olacak. Kod parçasını yapıştırabilirseniz daha iyi olacak ...
grv_9098

3

Sergey'in önerisini takip ederek, bir Kalınlık nesnesi yerine tüm bir Stili (Kenar Boşluğu dahil çeşitli özellik ayarlayıcılarıyla) tanımlayabilir ve yeniden kullanabilirsiniz:

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

Buradaki hilenin, bazı dış (muhtemelen harici XAML dosyasından birleştirilen) kaynak sözlüğündeki stilden devralınan örtük stil için Stil Devralmanın kullanımı olduğunu unutmayın.

Kenar notu:

İlk olarak, bu dış Style kaynağına denetimin Style özelliğini ayarlamak için örtük stili kullanmaya çalıştım ("MyStyle" anahtarıyla tanımlanmış diyelim):

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

Visual Studio 2010'un https://connect.microsoft.com/VisualStudio/feedback/details/753211/xaml-editor-window-fails adresinde açıklandığı gibi CATASTROPHIC FAILURE hatasıyla (HRESULT: 0x8000FFFF (E_UNEXPECTED)) hemen kapanmasına neden oldu. -with-felaket-başarısızlık-a-style-çalışır-to-seti-style-mülk #




2

Benim yaklaşım StackPanel miras.

Kullanımı:

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

Gereken tek şey aşağıdaki kısa sınıftır:

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

0

bazen varsayılandan daha küçük öğeler arasında boşluk bırakmak için Kenar Boşluğu değil Dolgu ayarlamanız gerekir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.