Wpf 如何设置WrapPanel内部控制的余量

Wpf 如何设置WrapPanel内部控制的余量,wpf,wpf-controls,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"> <St

下面是我正在使用的一个示例:

<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”附加属性提供程序。是否有类似的方法可以设置内部控件的边距和填充

这使得代码更短,并且只允许我指定一次边距和填充,而不是为面板中的每个控件设置边距和填充


谢谢大家!

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>

是实现所需结果的最简单方法

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

  • 您可以为
    WrapPanel
    实现自己附加的属性/行为,该属性/行为为其所有子项设置
    边距
    和/或
    填充
    。有关详细信息,请参阅
  • 您可以创建自己的面板,该面板继承自
    WrapPanel
    ,只需添加所需的属性并覆盖适当的方法,以便为所有子元素设置
    Margin
    /
    Padding
  • 您还可以将
    样式定义从
    窗口.Resources
    移动到
    WrapPanel.Resources
    ,从
    样式中删除
    x:Key
    属性,从所有
    按钮中删除
    样式=“{StaticResource ButtonStyle}”
    。通过这种方式,
    样式
    将应用于所有
    按钮
    s,这些按钮是
    WrapPanel
    的子按钮。如果您还有其他控件作为子控件,则可以将
    样式的
    TargetType
    更改为适当的通用基本类型(例如
    FrameworkElement
    ):
  • 
    


    但是,请注意,这将影响
    包装程序
    中的所有
    按钮
    实例,而不仅仅是其直接子项

    这里可以看到另一个不错的方法:

    它显示了如何创建附加的行为,以便这样的语法可以工作:

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

    这是为面板的几个子级设置边距的最简单和最快速的方法,即使它们不是同一类型。(即按钮、文本框、组合框等)

    如果面板中的项目不多,您可以使用行控件,并为其指定宽度(如果是WrapPanel)和高度(如果是StackPanel)。然后你就可以设计线条了

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

    这里是一个自定义的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;
            }
        }
    }
    
    //
    ///可以对每个子项应用边距的环绕面板。
    /// 
    公共类ItemMarginWrapPanel:WrapPanel
    {
    /// 
    ///ItemMargin静态DP。
    /// 
    公共静态只读从属属性ItemMarginProperty=
    从属属性。寄存器(
    “项目边际”,
    类型(厚度),
    类型(ItemMarginWrapPanel),
    新框架属性元数据(
    新厚度(),
    FrameworkPropertyMetadataOptions.AffectsMeasure));
    /// 
    ///将应用于“包裹”面板中每个项目的边距。
    /// 
    公共页边距
    {
    得到
    {
    返回(厚度)GetValue(ItemMarginProperty);
    }
    设置
    {
    设置值(ItemMarginProperty,值);
    }
    }
    /// 
    ///重写。在调用基本实现之前设置项目边距。
    /// 
    /// 
    /// 
    受保护的覆盖尺寸测量覆盖(尺寸约束)
    {
    RefreshItemMargin();
    返回基准。测量超越(约束);
    }
    /// 
    ///重写。在调用基本实现之前设置项目边距。
    /// 
    /// 
    /// 
    受保护的替代尺寸排列替代(尺寸最终化)
    {
    RefreshItemMargin();
    返回基数。安排覆盖(最终化);
    }
    /// 
    ///刷新子项边距。
    /// 
    私有void RefreshItemMargin()
    {
    var children=内部子代;
    for(int i=0,count=children.count;i
    现在,您只需执行以下操作:

    <Style
        x:Key="MarginWrapPanelStyle"
        TargetType="{x:Type mycustomcontrols:ItemMarginWrapPanel}">
        <Setter
            Property="ItemMargin"
            Value="5" />
    </Style>
    
    
    
    这不是我真正需要的。我刚刚更新了一个示例,并添加了TextElement.FontSize和TextElement.FontStyle属性的用法。我需要类似的方式,但设置边距和填充。还有吗?进一步说(#3)-如果要在WrapPanel中的所有元素上设置样式,请删除TargetType声明,并将Setter更改为包含属性的“Control.”。例如:如果我这样做,VS会抱怨字典中的所有项都必须有一个键,如果我添加键,则样式不会应用于任何内容。第三个解决方案对我来说似乎更优雅/简单,我非常喜欢它!不幸的是,如果您设置了自定义按钮样式,这就不起作用了,如下所示:这是预期的行为,因为WPF总是采用与所讨论的元素“最接近”的属性值。这意味着,因为在元素本身上应用样式,WPF不考虑在某些代码>资源“< /Cord>”节中设置的样式,树中的某些级别更高。我会选择其他方法之一。在.nic中有一个选项#1的示例
    <Style
        x:Key="MarginWrapPanelStyle"
        TargetType="{x:Type mycustomcontrols:ItemMarginWrapPanel}">
        <Setter
            Property="ItemMargin"
            Value="5" />
    </Style>