WPF UniformGrid Layout

MickeySixx picture MickeySixx · Jun 12, 2012 · Viewed 9.6k times · Source

I have an ItemsControl in which I plan on hosting a listing of fruit objects. I have a list of Fruit objects all with their own DataTemplates. I have a Grape object, an Orange object and a Kiwi object.

I want to use a UniformGrid so that all cells have equal size, but I want the Kiwi object to span only 1 cell, I want the Grape to span 2 cells (ColumnSpan = 2) and I want the Orange control to span 4 cells (ColumnSpan = 2 and RowSpan = 2)

How can I accomplish this?

Answer

Rachel picture Rachel · Jun 12, 2012

Items in a UniformGrid cannot span multiple cells.

Why not use a regular Grid instead with the height/width of the rows/columns set to * so they're all equally sized? If you want cells to be a perfect square with the height matching the width, be sure to bind the Grid's Height to the Width, or vice versa.

It should be noted that you need to apply the Grid positioning properties in the ItemContainerStyle, not on the item itself, since an ItemsControl wraps each element inside a ContentPresenter before adding that item to the ItemsPanel (see my blog post here for more details)

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />

            <!-- Can either use a DataTrigger to determine these values, 
                 or store them on the object itself -->
            <Setter Property="Grid.RowSpan" 
                    Value="{Binding RowSpan}" />
            <Setter Property="Grid.ColumnSpan" 
                    Value="{Binding ColumnSpan}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>