मैं एक StackPanel के बच्चे तत्वों को कैसे बाहर निकालूं?


187

एक StackPanel दिया:

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

बच्चे के तत्वों को बाहर निकालने का सबसे अच्छा तरीका क्या है ताकि उनके बीच समान आकार के अंतराल हों, भले ही बाल तत्व खुद विभिन्न आकारों के हों? क्या यह प्रत्येक व्यक्तिगत बच्चों पर गुण स्थापित किए बिना किया जा सकता है?


वास्तव में सिर्फ व्यक्तिगत वस्तुओं में पैडिंग जोड़ना सबसे अच्छा विकल्प लगता है।
ज़ार

जवाबों:


278

कंटेनर के दायरे में लागू मार्जिन या पैडिंग का उपयोग करें:

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

संपादित करें: यदि आप दो कंटेनरों के बीच के मार्जिन का फिर से उपयोग करना चाहते हैं, तो आप मार्जिन मान को बाहरी दायरे में संसाधन में परिवर्तित कर सकते हैं।

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

और फिर आंतरिक दायरे में इस मान को देखें

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

5
स्कोप्ड स्टाइल ऐसा करने का एक शानदार तरीका है - टिप के लिए धन्यवाद!
एना बेट्स

2
क्या होगा अगर मैं इसे पूरी परियोजना के लिए उपयोग करना चाहता हूं?
grv_9098

10
क्या कोई समझा सकता है कि यह तब ही क्यों काम करता है जब आप स्पष्ट रूप से टाइप (जैसे टेक्स्टबॉक्स) को परिभाषित करते हैं? अगर मैं इस फ्रेमवर्क के उपयोग की कोशिश करता हूं, ताकि सभी बच्चों को स्थान मिल जाए, तो इसका कोई प्रभाव नहीं पड़ता है।
जैक उलेजा

4
यदि आपने पहले से ही किसी शैली को परिभाषित कर लिया है तो यह अच्छी तरह से काम नहीं करता है Button
मार्क इनग्राम

1
एक साइड नोट के रूप में, यदि आप इसके साथ ऐसा करना चाहते हैं, तो आपको इसके बदले Labelउपयोग Paddingकरना होगाMargin
एंथनी निकोल्स

84

एक और अच्छा दृष्टिकोण यहाँ देखा जा सकता है: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between- items-in-stackpanel.aspx लिंक टूटा हुआ है -> यह इस लिंक का वेबआर्क है।

यह दिखाता है कि संलग्न व्यवहार कैसे बनाया जाए, ताकि इस तरह से वाक्य रचना काम करे:

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

यह एक पैनल के कई बच्चों के लिए मार्जिन सेट करने का सबसे आसान और सबसे तेज़ तरीका है, भले ही वे एक ही प्रकार के न हों। (यानी बटन, टेक्स्टबॉक्स, कॉम्बोबॉक्स, आदि)


5
इस बारे में जाने के लिए यह एक बहुत ही दिलचस्प तरीका है। यह इस बारे में बहुत सारी धारणाएं बनाता है कि आप चीजों को कैसे अंतरिक्ष में लाना चाहते हैं, और यहां तक ​​कि आपको पहले / अंतिम आइटम पर मार्जिन को स्वचालित रूप से समायोजित करने का अवसर भी देता है।
Armentage

2
बहुमुखी प्रतिभा के लिए +1। ब्लॉग पोस्ट पर सुधार करने के लिए, if (fe.ReadLocalValue(FrameworkElement.MarginProperty) == DependencyProperty.UnsetValue)वास्तव में बच्चे के मार्जिन को सेट करने से पहले जोड़ना, कुछ तत्वों के लिए मैन्युअल रूप से मार्जिन निर्दिष्ट करने की अनुमति देता है।
Xerillio

ध्यान दें कि यह काम नहीं करता है यदि बच्चे की वस्तुओं को गतिशील रूप से जोड़ा जाता है / हटाया जाता है, जैसे कि एक बदलते संग्रह के लिए बाध्य ItemControl में।
ड्रू नॉक

1
मामले में यह काम नहीं करता है: परियोजना का निर्माण करें, अन्यथा यह पृष्ठ को प्रस्तुत नहीं करेगा।
बैटल

2
लिंक टूट गया है!
डेव

13

मैंने एलाड काटज़ के जवाब में सुधार किया ।

  • अंतिम आइटम को अंतिम रूप से संभालने के लिए MarginSetter में LastItemMargin संपत्ति जोड़ें
  • वर्टिकल और हॉरिज़ॉन्टल प्रॉपर्टी के साथ स्पेसिंग अटैचमेंट को जोड़ें, जो वर्टिकल और हॉरिज़ॉन्टल लिस्ट में आइटम्स के बीच स्पेसिंग को जोड़ता है और लिस्ट के अंत में किसी भी ट्रेसिंग मार्जिन को खत्म करता है।

जिस्ट में सोर्स कोड

उदाहरण:

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

एलाड के जवाब की तरह, यह काम नहीं करता है अगर बच्चे की वस्तुओं को गतिशील रूप से जोड़ा / हटाया जाता है, जैसे कि ItemsControlएक बदलते संग्रह के लिए बाध्य। यह मानता है कि माता-पिता की Loadघटना की आग से आइटम स्थिर हैं ।
ड्रू नोक

इसके अलावा, आपका जिस्ट 404 देता है।
ड्रू नोक

Gist का अपडेटेड लिंक।
कोणीयसेन

9

वह चीज जो आप वास्तव में करना चाहते हैं, सभी बाल तत्वों को लपेटना है। इस मामले में आपको एक आइटम नियंत्रण का उपयोग करना चाहिए और भयानक संलग्न गुणों का सहारा नहीं लेना चाहिए, जिसे आप स्टाइल करने की इच्छा रखने वाले प्रत्येक संपत्ति के लिए एक मिलियन होने का अंत करेंगे।

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

यहां छवि विवरण दर्ज करें


ग्रेट टिप, लेकिन यह स्टाइल टारगेट टाइप के साथ "फ्रेमवर्कप्लिमेंट" के रूप में बेहतर काम करता है (अन्यथा यह छवि के लिए काम नहीं करता है, उदाहरण के लिए)
पफिन

1
मुझे यह विचार पसंद है। बस एक जोड़: StackPanel ( Margin="0 0 -5 0") के मार्जिन से रिक्ति की मात्रा घटाना भी सूची में अंतिम आइटम के बाद रिक्ति का मुकाबला करेगा।
लेबल

इसके साथ समस्या यह है कि आपके द्वारा सेट की गई शैली किसी भी अन्य शैली को ओवरराइड करेगी जो आपके पास पहले से ही आइटम पर हो सकती है। इसे दूर करने के लिए इस संबंधित प्रश्न / स्वीकृत उत्तर को यहां देखें
वैक्सिंगैटिरिकल

6

सर्गेई के जवाब के लिए +1। और अगर आप अपने सभी StackPanels पर इसे लागू करना चाहते हैं, तो आप ऐसा कर सकते हैं:

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

लेकिन सावधान रहें: यदि आप अपने App.xaml (या किसी अन्य शब्दकोश जो Application.Resources में विलय कर दिया गया है) में इस तरह की शैली को परिभाषित करते हैं, तो यह नियंत्रण की डिफ़ॉल्ट शैली को ओवरराइड कर सकता है । स्टैकपैन जैसे ज्यादातर दिखने वाले नियंत्रण के लिए यह कोई समस्या नहीं है, लेकिन टेक्स्टबॉक्स आदि के लिए आप इस समस्या पर ठोकर खा सकते हैं , जिसके सौभाग्य से कुछ वर्कअराउंड होते हैं।


<Style.Resources> क्या आप इसके बारे में निश्चित हैं कि जब मैंने यह कोशिश की तो यह त्रुटि दिखा रहा था।
grv_9098

क्षमा करें, मैं याद नहीं कर सकता। मुझे इसे स्वयं देखने की कोशिश करनी होगी। मैं तुम्हारे पास वापस मिलने आऊँगा।
आंद्रे लुस

हाँ, यह काम करता है। स्टैकपैनल में सभी TextBlocks पर TextWeight = "Bold" सेट करने के लिए बस यही किया। केवल अंतर यह था कि मैंने स्टैकपैनल पर स्पष्ट रूप से शैली सेट की थी।
आंद्रे लुस

उर चिंता के लिए धन्यवाद, लेकिन मुझे अभी भी संदेह है। मुझे पता है कि इसे स्कोप स्टाइल कहा जाता है। मुझे लगता है कि यह <StackPanel.Resources> होगा न कि <Style.Resources>। यह बहुत अच्छा होगा यदि आप अपने कोड का टुकड़ा पेस्ट कर सकते हैं ...
grv_9098

3

सर्गेई के सुझाव पर अमल करते हुए, आप केवल एक मोटी वस्तु के बजाय एक पूरी शैली को परिभाषित कर सकते हैं और (मार्जिन सहित विभिन्न संपत्ति बसने वालों के साथ) पुन: उपयोग कर सकते हैं:

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

ध्यान दें कि यहाँ ट्रिक निहित शैली के लिए स्टाइल इनहेरिटेंस का उपयोग है, जो कि कुछ बाहरी (शायद बाहरी एक्सएएमएल फ़ाइल से विलय) संसाधन शब्दकोश में शैली से विरासत में मिला है।

पक्षीय लेख:

सबसे पहले, मैंने उस बाहरी शैली संसाधन पर नियंत्रण की शैली गुण को सेट करने के लिए निहित शैली का उपयोग करने की कोशिश की (जैसा कि कुंजी "MyStyle" के साथ परिभाषित किया गया है):

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

जिसके कारण दृश्य स्टूडियो 2010 CATASTROPHIC विफल त्रुटि (HRESULT: 0x8000FFFF (E_UNEXPECTED)) के साथ तुरंत बंद हो गया, जैसा कि https://connect.microsoft.com/VisualStudio-feedback/details/753211/xaml-editor-window-fails पर वर्णित है। -साथ आपत्तिजनक विफलता-जब-ए-शैली-की कोशिश करता करने के लिए सेट-शैली-संपत्ति #


3

Grid.ColumnSpacing , Grid.RowSpacing , StackPanel.Spacing अब UWP प्रीव्यू पर हैं, सभी यहां जो भी अनुरोध किया गया है उसे बेहतर तरीके से पूरा करने की अनुमति देगा।

ये गुण वर्तमान में केवल विंडोज 10 फॉल क्रिएटर्स अपडेट इनसाइडर एसडीके के साथ उपलब्ध हैं, लेकिन इसे अंतिम बिट्स के लिए बनाना चाहिए!



2

मेरा दृष्टिकोण StackPanel को विरासत में मिला है।

उपयोग:

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

सभी आवश्यक है कि निम्न लघु वर्ग है:

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

कभी-कभी आपको पैडिंग सेट करने की ज़रूरत होती है, न कि मार्जिन को डिफ़ॉल्ट से छोटी वस्तुओं के बीच जगह बनाने के लिए

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.