Как установить поле для внутренних элементов управления WrapPanel - PullRequest
27 голосов
/ 11 января 2011

Вот пример, который я использую:

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

23 голосов
/ 11 января 2011

Решение, предоставленное Джеймсом Хэем , - это самый простой способ достичь желаемого результата.

Однако есть и другие возможные решения:

  1. Вы можете реализовать свое собственное присоединенное свойство / поведение для WrapPanel, который устанавливает Margin и / или Padding для всех его дочерних элементов. Подробнее см. в этой статье CodeProject Джоша Смита .
  2. Вы можете создать свою собственную панель, которая наследуется от WrapPanel и просто добавляет необходимые свойства и переопределяет соответствующие методы, так что Margin / Padding устанавливается для всех дочерних элементов.
  3. Вы также можете переместить определение Style из Window.Resources в WrapPanel.Resources, удалить атрибут x:Key из Style и удалить Style="{StaticResource ButtonStyle}" из всех Button с. Таким образом, Style применяется к всем Button с, которые являются потомками WrapPanel. Если у вас также есть другие элементы управления в качестве дочерних, вы можете изменить TargetType для 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>

Обратите внимание, что это повлияет на все Button экземпляров в пределах WrapPanel, а не только на его прямых потомков!

17 голосов
/ 30 мая 2011

Еще один хороший подход можно увидеть здесь: 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>

Это самый простой и быстрый способ установить маржу для нескольких дочерних элементов панели, даже если они не одного типа. (Т.е. кнопки, текстовые поля, комбинированные списки и т. Д.)

7 голосов
/ 11 января 2011

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>
2 голосов
/ 12 сентября 2014

Вот настроенный элемент управления 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>
0 голосов
/ 04 марта 2014

Если на панели не так много элементов, вы можете использовать элемент управления Line и задать ему ширину в случае WrapPanel и высоту в случае StackPanel. Тогда вы можете стилизовать линию.

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