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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4656717/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 22:29:18  来源:igfitidea点击:

How to set margin for inner controls of WrapPanel

wpfwpf-controls

提问by Andrey Tagaew

Here is an example that I'm using:

这是我正在使用的示例:

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

As you can see, my wrap panel has several buttons. Each button has the same margin and padding.

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

The question is, is there a way of setting margin and padding for wrap panel, so each element inside the wrap panel may use it values?

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

For setting inner element's font, i may use "TextElement" attached property provider. Is there similar way how i can set margin and padding for inner controls?

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

This make the code shorter and let me specify Margin and Padding only one time instead of setting it for each control in the panel.

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

Thank you!

谢谢!

采纳答案by gehho

The solution provided by James Hayis the easiest way to achieve your desired result.

James Hay 提供的解决方案是实现所需结果的最简单方法。

However, there are other possible solutions:

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

  1. You could implement your own attached property/behavior for a WrapPanelwhich sets the Marginand/or Paddingfor all its children. See this CodeProject article by Josh Smithfor details.
  2. You could create your own panel which inherits from WrapPaneland just adds the required properties and overrides the appropriate methods, so that the Margin/Paddingis set for all child elements.
  3. You could also move the Styledefinition from the Window.Resourcesto the WrapPanel.Resources, remove the x:Keyattribute from the Style, and remove the Style="{StaticResource ButtonStyle}"from all Buttons. This way, the Styleis applied to allButtons which are children of the WrapPanel. If you also have other controls as children, you could change the TargetTypefor the Styleto an appropriate common base type (e.g. FrameworkElement):
  1. 您可以为 a 实现自己的附加属性/行为,以WrapPanel设置Margin和/或Padding为其所有子项。有关详细信息,请参阅Josh Smith 撰写的这篇 CodeProject 文章
  2. 您可以创建自己的面板,该面板继承WrapPanel并添加所需的属性并覆盖适当的方法,以便为所有子元素设置Margin/ Padding
  3. 您还可以将Style定义从 the移动Window.ResourcesWrapPanel.Resourcesx:Key从 中删除属性Style,并Style="{StaticResource ButtonStyle}"从所有Buttons 中删除。这样, theStyle应用于所有Buttons 的子代WrapPanel。如果您还有其他控件作为子控件,则可以将TargetTypefor更改为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>

Note, however, that this will influence allButtoninstances within the WrapPanel, not only its direct children!

但是请注意,这将影响 中的所有Button实例WrapPanel,而不仅仅是它的直接子代!

回答by Elad Katz

Another nice approach can be seen here: http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between-items-in-stackpanel.aspx

另一个不错的方法可以在这里看到:http: //blogs.microsoft.co.il/blogs/eladkatz/archive/2011/05/29/what-is-the-easiest-way-to-set-spacing-between-项目在stackpanel.aspx

It shows how to create an attached behavior, so that syntax like this would work:

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

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

This is the easiest & fastest way to set Margin to several children of a panel, even if they are not of the same type. (I.e. Buttons, TextBoxes, ComboBoxes, etc.)

这是将 Margin 设置为面板的多个子项的最简单和最快的方法,即使它们的类型不同。(即按钮、文本框、组合框等)

回答by James Hay

WrapPanel does not have any properties that add padding or margins to all its children. What you probably want is a style that is share by each button. Something like:

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>

回答by Bruce Pierson

Here is a customized WrapPanel control that adds an ItemMargin dependency property.

这是一个自定义的 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;
        }
    }
}

Now you can just do:

现在你可以这样做:

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

回答by usefulBee

In case there are not many items in the panel, you could use a Line control and give it a width in case of WrapPanel and height in case of StackPanel. Then you could style the Line.

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

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