Boland
Boland

Reputation: 155

ItemsControl with Grid as template : add control to Grid

Windows Phone 7.1 project (XAML). I have a itemscontrol with a grid as template, bound to collection of data-elements, everything works okay. However, I have to add one extra Image to the Grid, which does not bind to the collection. Some kind of header image.

I have this code:

<ItemsControl ...>
    <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid ShowGridLines="True" x:Name="ShipsGrid">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                        <ColumnDefinition Width="0.1*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                        <RowDefinition Height="0.1*"></RowDefinition>
                    </Grid.RowDefinitions>

                    <!--<Image Source="/images/image.png" x:Name="SuperImage"/>-->

                </Grid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Image x:Name="ElementImage" Source="{Binding ImageUri, Mode=OneWay}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </controls:ShipItemsGridControl>

If I uncomment the Image in ItemsPanelTemplate (x:Name SuperImage), I get the following error: Cannot explicitly modify Children collection of Panel used as ItemsPanel for ItemsControl. ItemsControl generates child elements for Panel.

I have tried several things, but I can't manage to get it working. Of course I can add it to the itemtemplate and only make it visible in first item, but that is very, very ugly.

Upvotes: 4

Views: 2294

Answers (1)

Rachel
Rachel

Reputation: 132558

What about just stacking the Image on top of your ItemsControl by placing both in a parent panel that allows overlapping controls, such as a Grid or a Canvas?

<Grid>
    <ItemsControl ... />
    <Image Source="/images/image.png"
           VerticalAlignment="Top" HorizontalAlignment="Left" 
           Margin="5,5,0,0" />
</Grid>

In the code sample I just set a margin of 5 for both the Top and the Left margins, but you will probably need to mess with that a bit to line the Image up with your first Grid cell.

Also if you need to dynamically set the height/width of the image to make it the same size as your Grid cell, you can bind the Height and Width properties of the Image to the ItemsControl's ActualHeight/ActualWidth and use a Converter to figure out 1/10th of that size (I have a MathConverter on my blog which would make this easy)

The only other alternative I could think of would be to add it in the code-behind after the items have been generated

void MyItemsControl_Loaded(object sender, EventArgs e)
{
    MyItemsControl.ItemContainerGenerator.StatusChanged += 
        ItemContainerGenerator_StatusChanged;
}

void ItemContainerGenerator_StatusChanged(object sender, EventArgs e)
{
    if (MyItemsControl.ItemContainerGenerator.Status == 
        System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
    {
        // Remove ItemContainerGenerator event
        MyItemsControl.ItemContainerGenerator.StatusChanged
            -= ItemContainerGenerator_StatusChanged;

        // Add Image to ItemsControl here
    }
}

This isn't really ideal though, and I would do my best to simply place the Image on top of the ItemsControl first.

Upvotes: 3

Related Questions