5
votes

Goal

To add multiple images in a DataGrid's RowDetails template using the MVVM standards.

Background

I have an inspection window with a DataGrid designed to hold a damaged item's description along with the initials of the inspector. What is more, this DataGrid's RowDetailsTemplate needs to hold the pictures that the inspector took of the damaged item (so there might be more than one picture of the damaged item).

Problem

I have a DamagedWindow.xaml designed to create my DamagedItem entries. It looks like this:

RowDetails working

DataGrid (.XAML)

<DataGrid ItemsSource="{Binding Pictures}" SelectedItem="{Binding SelectedPicture}" AutoGenerateColumns="False" Grid.Column="1" Grid.Row="2" Margin="5" HorizontalAlignment="Stretch" Name="DataGrid1" VerticalAlignment="Stretch" CanUserAddRows="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Titre" Binding="{Binding Name}" Width="*" />
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <Image Height="100" Source="{Binding Path}" />
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

As you can see, my RowDetails template works fine in this DataGrid. I have a class named PicturesList which inherits an ObservableCollection Of my PictureModel(Name, Description, Path).


The text boxes that you see above the DataGrid are properties of my DamagedItemModel (Description, Initiales, PicturesList). So when the user clicks on the Accept (Checkmark) button, the DamagedItem is added to a DamagedItemsList which is then set as the ItemSource of the DataGrid from my MainWindow:

Empty RowDetails

DataGrid (.XAML)

<DataGrid ItemsSource="{Binding Path=DamagedItems}" SelectedItem="{Binding Path=SelectedDamagedItem}" AutoGenerateColumns="False" Name="DataGrid1" Height="250" Margin="3" IsEnabled="True" CanUserAddRows="False" FontSize="16">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Description" Width="*" Binding="{Binding Description}"/>
        <DataGridTextColumn Header="Initiales" Width="70" Binding="{Binding Initiales}"/>
    </DataGrid.Columns>
    <DataGrid.RowDetailsTemplate>
        <DataTemplate>
            <Image Height="100" Source="{Binding Pictures.Path}" />
        </DataTemplate>
    </DataGrid.RowDetailsTemplate>
</DataGrid>

Here when I select the row, I get an empty RowDetailsTemplate result ... Even though my object contains my images. See below for more details:

DamagedItem Properties

So here's my question, is it possible to add multiple images to a RowDetailsTemplate in a DataGrid while following MVVM standards? If it is, what am I doing wrong?

1

1 Answers

5
votes

You can't bind that way. you need to do it like this:

        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <ItemsControl ItemsSource="{Binding Pictures}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <Image Height="100" Source="{Binding Path}"/>
                                <TextBlock Text="{Binding Name}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapPanel/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>

The reason your method was not working is that the Binding source is always one object which is set by Binding Path, and your Binding Path was Pictures.Path which leads to nothing because Pictures object does not have Path, it's its Items which have Path.

In general, Whenever you find yourself dealing with a collection of some kind think of a control which is suitable for showing a collection, like ListBox, DataGrid or the best of all ItemsControl.

Anything that goes inside ItemTemplate of these controls, have their DataContext automatically set to the correspondent item, so you don't have to worry about it. All you have to do is to set the ItemsSource to your collection and set the Binding Paths of things inside to the properties of the Type of that collection, So that it knows where to look for data for each item.

In this code you can think of it this way, Like you have some StackPanels, first one has : Image Source="{Binding Pictures(0).Path}", seconds one has Image Source="{Binding Pictures(1).Path}" and so on. this way all Binding Paths point to an object.