What is the easy way to set spacing between items in StackPanel?

后端 未结 4 793
情书的邮戳
情书的邮戳 2021-02-01 05:50

Is there an easy way to set default space between items inside StackPanel so I\'ll don\'t have to set Margin property on each item?

相关标签:
4条回答
  • 2021-02-01 06:10

    if all the controls are the same then do as IanR suggested and implement a Style that catches that control. if it's not then you can't create a default style to a base class because it just won't work.

    the best way for situations like these is to use a very neat trick - attached properties (aka Behaviors in WPF4)

    you can create a class that has an attached property, like so:

    public class MarginSetter
    {
        public static Thickness GetMargin(DependencyObject obj)
        {
            return (Thickness)obj.GetValue(MarginProperty);
        }
    
        public static void SetMargin(DependencyObject obj, Thickness value)
        {
            obj.SetValue(MarginProperty, value);
        }
    
        // Using a DependencyProperty as the backing store for Margin.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MarginProperty =
            DependencyProperty.RegisterAttached("Margin", typeof(Thickness), typeof(MarginSetter), new UIPropertyMetadata(new Thickness(), CreateThicknesForChildren));
    
        public static void CreateThicknesForChildren(object sender, DependencyPropertyChangedEventArgs e)
        {
            var panel = sender as Panel;
    
            if (panel == null) return;
    
            foreach (var child in panel.Children)
            {
                var fe = child as FrameworkElement;
    
                if (fe == null) continue;
    
                fe.Margin = MarginSetter.GetMargin(panel);
            }
        }
    
    
    }
    

    now, to use it, all you need to do is to attach this attached property to any panel you want, like so:

    <StackPanel local:MarginSetter.Margin="10">
        <Button Content="hello " />
        <Button Content="hello " />
        <Button Content="hello " />
        <Button Content="hello " />
    </StackPanel>
    

    Completely reusable of course.

    0 讨论(0)
  • 2021-02-01 06:14

    I find that creating a grid inside the stack panel, then adding the desired number of columns (or rows) as follows:

        <StackPanel Grid.Row="1" Grid.Column="0" Height="34" Width="698" Margin="10,5,10,10" Orientation="Horizontal"  HorizontalAlignment="Center" VerticalAlignment="Center" >
            <Grid Width="698" Margin="0,0,0,0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Button x:Name="StartButton" Content="Start" Grid.Row="0" Grid.Column="0" Style="{StaticResource 3DButton}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="70" Click="StartButton_Click" />
                <Button x:Name="HelpButton"  Content="Help"  Grid.Row="0" Grid.Column="1" Style="{StaticResource 3DButton}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="70" Click="HelpButton_Click"  />
                <Button x:Name="ExitButton"  Content="Exit"  Grid.Row="0" Grid.Column="2" Style="{StaticResource 3DButton}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="70" Click="ExitButton_Click" Foreground="Red" />
            </Grid>
        </StackPanel>
    
    0 讨论(0)
  • 2021-02-01 06:22

    I use a transparent separator, which works well:

    <Separator Opacity="0" Height="20"/>
    

    You can of course use margins but then if you want to change the margins you have to update all of the elements.

    The separator can even be styled in a static resource.

    An attached property could do it too but I think it's overkill.

    0 讨论(0)
  • 2021-02-01 06:33

    The accepted answer doesn't work anymore. But I used that answer and the blog the author of that answer (Elad Katz) to make a working code (tested in .Net Core) that I reproduce here:

        public static class EstablecedorMargen { 
    
    
        public static Thickness GetMargen(DependencyObject objeto) => objeto != null ? (Thickness)objeto.GetValue(PropiedadMargen) : new Thickness();
    
        public static void SetMargen(DependencyObject objeto, Thickness value) => objeto?.SetValue(PropiedadMargen, value);
    
        public static readonly DependencyProperty PropiedadMargen 
            = DependencyProperty.RegisterAttached("Margen", typeof(Thickness), typeof(EstablecedorMargen), new UIPropertyMetadata(new Thickness(), Cambió));
    
    
        public static void Cambió(object sender, DependencyPropertyChangedEventArgs e) {
            if (!(sender is Panel panel)) return;
            panel.Loaded += new RoutedEventHandler(EstablecerMargenControlesHijos);
        } 
    
    
        public static void EstablecerMargenControlesHijos(object sender, RoutedEventArgs e) {
    
            if (!(sender is Panel panel)) return;
            foreach (var hijo in panel.Children) {
                if (!(hijo is FrameworkElement feHijo)) continue;
                feHijo.Margin = GetMargen(panel);
            }
    
        } 
    
    
    } 
    

    Then you use:

       <StackPanel local:EstablecedorMargen.Margen="10" >          
                <Button Content="1" />
                <Button Content="2" />
                <Button Content="3" />
        </StackPanel>
    
    0 讨论(0)
提交回复
热议问题