سؤال

بالنظر إلى stackpanel:

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

ما هي أفضل طريقة للمساحة عناصر الطفل بحيث تكون هناك فجوات بحجمها على قدم المساواة بينهما، على الرغم من أن عناصر الأطفال نفسها بأحجام مختلفة؟ هل يمكن القيام به دون تحديد خصائص على كل من الأطفال الفرديين؟

هل كانت مفيدة؟

المحلول

استخدام الهامش أو الحشو، المطبق على النطاق داخل الحاوية:

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

تحرير: في حال كنت ترغب في إعادة استخدام الهامش بين الحاويات، يمكنك تحويل قيمة الهامش إلى مورد في نطاق خارجي، FE

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

نصائح أخرى

يمكن رؤية نهج آخر لطيف هنا:http://blogs.microsoft.co.il/blogs/eladkatz/archive 21/05/29/what-s-the-esiest-wearto-set-spacing-between-items-in-stackpanel.aspx.

يوضح كيفية إنشاء سلوك مرفق، بحيث يعمل بناء جملة مثل هذا:

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

هذه هي أسهل وأسرع طريقة لتعيين الهامش للعديد من الأطفال من لوحة، حتى لو لم تكن من نفس النوع. (أي الأزرار، مربع النص، comboboxes، إلخ.)

لقد تحسنت إجابة Elad Katz.

  • أضف الخاصية LastItemmargin إلى Margensetter إلى التعامل بشكل خاص في العنصر الأخير
  • أضف خصائص Spacing المرفقة مع خصائص رأسية وأفقية تضيف تباعد بين العناصر في القوائم الرأسية والأفقية وتزيل أي هامش زائدة في نهاية القائمة

شفرة المصدر في GIST.

مثال:

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

    <!-- 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 image description here

+1 للحصول على إجابة سيرجي. وإذا كنت ترغب في تطبيق ذلك على كل ما تبذلونه من STACKPANLES، فيمكنك القيام بذلك:

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

ولكن حذار: إذا حددت نمطا مثل هذا في تطبيقك .xaml (أو قاموس آخر تم دمجه في التطبيق. يمكن تجاوز النمط الافتراضي للتحكم. بالنسبة لعناصر تحكم غير صغرة مثل StackPanel أنها ليست مشكلة، ولكن بالنسبة للنصوص وما إلى ذلك قد تتعثر عليها هذه المشكلة, ، والتي لحسن الحظ لديها بعض الحلول.

متابعة اقتراح سيرجي، يمكنك تحديد وإعادة استخدام نمط كامل (مع وجود خصوصية مختلفة، بما في ذلك الهامش) بدلا من مجرد كائن سمك:

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

لاحظ أن الخدعة هنا هي استخدام الميراث على الطراز على النمط الضمني، والورث من النمط في بعض القاموس المدمج في بعضها (ربما دمج من ملف XAML الخارجي).

ملاحظة جانبية:

في البداية، حاولت سذاجة استخدام النمط الضمني لتعيين خاصية نمط التحكم في هذا المورد النمط الخارجي (يقول مع تحديد مع المفتاح "mystyle"):

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

مما تسبب في إيقاف تشغيل Visual Studio 2010 على الفور مع خطأ الفشل الكارثي (HRESULT: 0x8000FFFFF (E_unexpected))، كما هو موضح في https://connnect.microsoft.com/visualstudio/feedback/details/753211/xaml-editor-window-fails-with-catstrophic-failure-when-style-riptto-set-style-property

grid.columnspacing., grid.rowspacing., stackpanel.Spacing. الآن على معاينة UWP، كلها ستسمح تماما بإغراء ما هو مطلوب هنا.

هذه الخصائص متوفرة حاليا فقط مع تحديث Windows 10 Fall Creators Insider SDK، ولكن يجب أن تصل إلى البتات النهائية!

قد لا يكون HearchGrid متاحا في Silverlight، لكن شخصا ما قد أداره من WPF. http://www.jeff.wilcox.name/2009/01/uniform-grid/

نهجي يرث 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();
        }
    }
}

في بعض الأحيان تحتاج إلى تعيين الحشو، وليس الهامش لجعل المساحة بين العناصر أصغر من الافتراضي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top