如何为WrapPanel的内部控件设置边距

时间:2011-01-11 10:40:45

标签: wpf wpf-controls

以下是我正在使用的示例:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <WrapPanel Orientation="Horizontal" TextElement.FontSize="30" TextElement.FontStyle="Italic"  >
        <Button Content="test1" Margin="10,0" Padding="10,10" />
        <Button Content="test2" Margin="10,0" Padding="10,10" />
        <Button Content="test3" Margin="10,0" Padding="10,10" />
        <Button Content="test4" Margin="10,0" Padding="10,10" />
        <Button Content="test5" Margin="10,0" Padding="10,10" />
    </WrapPanel>
</StackPanel>

如您所见,我的包装面板有几个按钮。 每个按钮都有相同的边距和填充。

问题是,有没有办法为包装面板设置边距和填充,因此包装面板中的每个元素都可以使用它的值?

为了设置内部元素的字体,我可以使用“TextElement”附加属性提供程序。有没有类似的方法我可以为内部控件设置边距和填充?

这会缩短代码,让我只指定一次Margin和Padding,而不是为面板中的每个控件设置它。

谢谢!

5 个答案:

答案 0 :(得分:22)

The solution provided by James Hay是达到理想效果的最简单方法。

但是,还有其他可能的解决方案:

  1. 您可以为WrapPanel实施自己的附加属性/行为,为其所有子项设置Margin和/或Padding。有关详细信息,请参阅this CodeProject article by Josh Smith
  2. 您可以创建自己的面板,该面板继承自WrapPanel,只需添加所需的属性并覆盖相应的方法,以便为所有子元素设置Margin / Padding
  3. 您还可以将Style定义从Window.Resources移至WrapPanel.Resources,从x:Key移除Style属性,然后移除{{来自所有Style="{StaticResource ButtonStyle}"的1}}。这样,Button就会应用于所有 Style,它们是Button的子项。如果您还有其他控件作为子级,则可以将WrapPanel的{​​{1}}更改为适当的公共基本类型(例如TargetType):
  4. Style

    但请注意,这会影响FrameworkElement内的所有 <StackPanel> <WrapPanel Orientation="Horizontal"> <WrapPanel.Resources> <Style TargetType="{x:Type Button}"> <Setter Property="Margin" Value="10,0" /> <Setter Property="Padding" Value="10,10" /> </Style> </WrapPanel.Resources> <Button Content="test1" /> <Button Content="test2" /> <Button Content="test3" /> <Button Content="test4" /> <Button Content="test5" /> </WrapPanel> </StackPanel> 个实例,而不仅仅是其直接的孩子!

答案 1 :(得分:17)

这里可以看到另一种不错的方法: 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>

这是最简单的&amp;将边距设置为面板的几个子节点的最快方法,即使它们的类型不同。 (即按钮,文本框,组合框等)

答案 2 :(得分:7)

WrapPanel没有任何为其所有子项添加填充或边距的属性。您可能想要的是每个按钮共享的样式。类似的东西:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
            <Setter Property="Margin" Value="10,0" />
            <Setter Property="Padding" Value="10,10" />
        </Style>
    </Window.Resources>

    <StackPanel>
      <WrapPanel Orientation="Horizontal"  >
         <Button Content="test1" Style="{StaticResource ButtonStyle}" />
         <Button Content="test2" Style="{StaticResource ButtonStyle}" />
         <Button Content="test3" Style="{StaticResource ButtonStyle}" />
         <Button Content="test4" Style="{StaticResource ButtonStyle}" />
         <Button Content="test5" Style="{StaticResource ButtonStyle}" />
       </WrapPanel>
    </StackPanel>
   </Window>

答案 3 :(得分:2)

这是一个自定义的WrapPanel控件,它添加了一个ItemMargin依赖项属性。

/// <summary>
/// A wrap panel which can apply a margin to each child item.
/// </summary>
public class ItemMarginWrapPanel : WrapPanel
{
    /// <summary>
    /// ItemMargin static DP.
    /// </summary>
    public static readonly DependencyProperty ItemMarginProperty =
        DependencyProperty.Register(
        "ItemMargin",
        typeof( Thickness ),
        typeof( ItemMarginWrapPanel ),
        new FrameworkPropertyMetadata(
            new Thickness(),
            FrameworkPropertyMetadataOptions.AffectsMeasure ) );

    /// <summary>
    /// The margin that will be applied to each Item in the wrap panel.
    /// </summary>
    public Thickness ItemMargin
    {
        get
        {
            return (Thickness)GetValue( ItemMarginProperty );
        }
        set
        {
            SetValue( ItemMarginProperty, value );
        }
    }

    /// <summary>
    /// Overridden. Sets item margins before calling base implementation.
    /// </summary>
    /// <param name="constraint"></param>
    /// <returns></returns>
    protected override Size MeasureOverride( Size constraint )
    {
        RefreshItemMargin();

        return base.MeasureOverride( constraint );
    }

    /// <summary>
    /// Overridden. Sets item margins before calling base implementation.
    /// </summary>
    /// <param name="finalSize"></param>
    /// <returns></returns>
    protected override Size ArrangeOverride( Size finalSize )
    {
        RefreshItemMargin();

        return base.ArrangeOverride( finalSize );
    }

    /// <summary>
    /// Refresh the child item margins.
    /// </summary>
    private void RefreshItemMargin()
    {
        var children = InternalChildren;
        for( int i = 0, count = children.Count; i < count; i++ )
        {
            var ele = children[i] as FrameworkElement;
            if( null != ele )
                ele.Margin = ItemMargin;
        }
    }
}

现在你可以这样做:

<Style
    x:Key="MarginWrapPanelStyle"
    TargetType="{x:Type mycustomcontrols:ItemMarginWrapPanel}">
    <Setter
        Property="ItemMargin"
        Value="5" />
</Style>

答案 4 :(得分:0)

如果面板中的项目不多,您可以使用Line控件,并在StackPanel的情况下为WrapPanel和高度赋予宽度。然后你可以设置Line的样式。

   <WrapPanel Orientation="Horizontal"  >
     <Button Content="test1" />
     <Line Width="15" />
     <Button Content="test2" />
     <Line Width="15" />
     <Button Content="test3" />
   </WrapPanel>