#1,016 – Displaying a Collection of Items in a WrapPanel

You can use data binding to bind a collection of items to a WrapPanel by using the WrapPanel as the ItemsPanel for a simple ItemsControl.  (You could do the same thing with a ListBox).

In the example below, we bind to a collection of Actor objects and set the DataTemplate of our ItemsControl to just display the image of each actor.  The ItemsControl will resize to fit the containing window (via the StackPanel) and the WrapPanel will manage changing the layout of the images as the window size changes.

    <ItemsControl ItemsSource="{Binding ActorList}" Margin="20">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding Image}" Height="100"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

1016-001
1016-002
1016-003

#897 – Content on a TabItem Does Not Automatically Wrap

The individual tabs on a TabControl are each represented by a TabItem.  TabItem is a content control, which means that it contains a single element.  That element is typically a panel, which in turn contains child controls.

If the element that you set for the content of a TabItem is too wide to be completely displayed within the TabControl, it will not automatically wrap.  Below, a horizontally-oriented StackPanel is placed on the first tab and the content does not fit.

    <TabControl Margin="10">
        <TabItem Header="Emperors">
            <StackPanel Orientation="Horizontal">
                <Image Source="Augustus.jpg" Height="100" Margin="5"/>
                <Image Source="Tiberius.jpg" Height="100" Margin="5"/>
                <Image Source="Caligula.jpeg" Height="100" Margin="5"/>
                <Image Source="Claudius.jpg" Height="100" Margin="5"/>
                <Image Source="Nero.jpg" Height="100" Margin="5"/>
            </StackPanel>
        </TabItem>
    </TabControl>

897-001
If you want content on the tab to wrap, you need to use a panel that knows how to wrap its own content (e.g. a WrapPanel).

    <TabControl Margin="10">
        <TabItem Header="Emperors">
            <WrapPanel Orientation="Horizontal">
                <!-- ... -->

897-002

#470 – Elements that Support RightToLeft Flow

Every FrameworkElement has a FlowDirection property that can be either LeftToRight (the default), or RightToLeft.  For panel elements that lay out a series of child elements, this property indicates in which direction the layout should be done.

The FlowDirection property is typically used for cultures where text flows from right to left, e.g. Arabic.  However, you can use this property whenever a right-to-left layout would make sense.

Below are some examples of elements that can use RightToLeft flow.

A Calendar control.

A DatePicker

A Menu, with MenuItem elements

A ListBox

A TreeView

A ProgressBar

A Grid

A StackPanel with Horizontal orientation

#443 – Reversing the Flow Direction in a WrapPanel

You can set a WrapPanel to flow its children from right to left, rather then from left to right by setting the FlowDirection property to RightToLeft.  (The default is LeftToRight).

For a horizontally oriented WrapPanel, elements will fill in the top row from right to left, flowing to the second row when the first one fills up.  For a vertically oriented WrapPanel, elements will fill in the rightmost column from top to bottom and then move to the next column to the left when the first column fills up.

Below are examples of each combination of Orientation and FlowDirection.

Orientation = Horizontal, FlowDirection = LeftToRight (the default).

Orientation = HorizontalFlowDirection = RightToLeft.

Orientation = VerticalFlowDirection = LeftToRight (the default).

Orientation = VerticalFlowDirection = RightToLeft.

You would normally use right-to-left flow in culture that present text from right to left (e.g. Arabic).  But you can also use it whenever this layout makes sense for your application.

#442 – WrapPanel Child Elements Can Be Clipped

By default a WrapPanel will size it’s rows (in Horizontal orientation) or columns (in Vertical orientation) to the size of the tallest/widest element.  This means that no element is ever clipped due to row/column sizing, though they may be clipped if the WrapPanel itself has an explicit size specified.

Child elements can also be clipped if an element ends up larger than the specified ItemWidth and ItemHeight properties.  In the example below, ItemHeight has been set to 50, which is shorter than the Label that has three lines.

#441 – Setting a Consistent Height/Width for Child Elements in a WrapPanel

By default, child elements in a WrapPanel size to fit the largest item on a particular row or column (if their alignment is set to Stretch), or align themselves relative to the largest item on the row or column.

In the example below, the label with 3 lines makes the entire row larger.  But the second row is shorter because all of the labels in that row just have a single line.

You can make all of the child elements in a WrapPanel the same height by setting the WrapPanel’s ItemHeight property to some fixed value.

    <WrapPanel Orientation="Horizontal" ItemHeight="60">
        <Label Background="AliceBlue" Content="William I" VerticalAlignment="Center"/>
        <!-- etc -->

Now the child elements in the second row are the same height as the ones in the first row (and the labels are centered vertically in this larger space).

You can also set a consistent item width using the ItemWidth property.

#440 – How Alignment Properties Behave in a WrapPanel

The alignment properties, when specified for children of a WrapPanel, dictate the alignment within the current row (if Orientation is Horizontal) or column (if Orientation is Vertical).

For example, the VerticalAlignment properties of controls in a WrapPanel whose Orientation is Horizontal indicate the alignment of the control with respect to the other controls within the same row.

In the example below, the William II label is set artificially high, which then dictates the height of a row that it appears in.  Other controls on that same row will then align themselves relative to this height.

    <WrapPanel Orientation="Horizontal">
        <Label Background="AliceBlue" Content="William I" VerticalAlignment="Center"/>
        <Label Background="AntiqueWhite" Content="William II" VerticalAlignment="Center" Height="60"/>
        <Label Background="AliceBlue" Content="Henry I" VerticalAlignment="Bottom"/>
        <Label Background="AntiqueWhite" Content="Stephen" VerticalAlignment="Top"/>
        <Label Background="AliceBlue" Content="Matilda"  VerticalAlignment="Stretch"/>
        <Label Background="AntiqueWhite" Content="Henry II" VerticalAlignment="Center"/>
        <Label Background="AliceBlue" Content="Richard I" VerticalAlignment="Center"/>
        <Label Background="AntiqueWhite" Content="John" VerticalAlignment="Center"/>
    </WrapPanel>