1

I have a main object that has properties, each their own object:

Package {
    Name
    Date
}

Document {
   Name
   Package1 = Package()
   Package2 = Package()
   Package3 = Package()
   Package4 = Package()
}

Now in WPF datagrid, I'd like to bind each column to one of the Document.PackageX properties. But the Name binding inside the DataTemplate always picks up the Document.Name and not the Package.Name

<DataTemplate x:Key="MyCellTemplate">
    <Border>
        <TextBlock Text="{Binding Name}" />     # this is Package.Name property
    </Border>
</DataTemplate>

<DataGrid ItemsSource="{Binding ListOfDocuments}">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Package 1" CellTemplate="{StaticResource MyCellTemplate}"/>
        <DataGridTemplateColumn Header="Package 2" CellTemplate="{StaticResource MyCellTemplate}"/>
        <DataGridTemplateColumn Header="Package 3" CellTemplate="{StaticResource MyCellTemplate}"/>
        <DataGridTemplateColumn Header="Package 4" CellTemplate="{StaticResource MyCellTemplate}"/>
    </DataGrid.Columns>
</DataGrid>

How should I set the context of a cell template to the nested object?

(Apologize for over-simplification but I thought it's easier to read and explains the core issue)

Ehsan Iran-Nejad
  • 1,697
  • 1
  • 15
  • 20
  • 1
    This article might be helpful if you want to get deeper into nested templates. https://stackoverflow.com/questions/2606948/wpf-how-to-bind-a-datagridtemplatecolumn – Glenn Ferrie Oct 29 '18 at 16:56

2 Answers2

1

I assume that OP has fixed data structure as he mentioned in question

Document {
   Name
   Package1 = Package()
   Package2 = Package()
   Package3 = Package()
   Package4 = Package()
}

You need to bind PackageX.Name property to TextBlock as you are biding ListOfDocuments to DataGrid.

<DataGrid ItemsSource="{Binding ListOfDocuments}">
    <DataGrid.Columns>

        <DataGridTemplateColumn Header="Package 1">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Package1.Name}" />     # this is Package.Name property
                    </Border>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTemplateColumn Header="Package 2">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Package2.Name}" />     # this is Package.Name property
                    </Border>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        .....

    </DataGrid.Columns>
</DataGrid>
Gaurang Dave
  • 3,956
  • 2
  • 15
  • 34
1

You need to define 4 different CellTemplates that binds to Package1, Package2, Package3 and Package4 respectively:

<DataGrid ItemsSource="{Binding ListOfDocuments}">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Package 1">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Package1.Name}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Package 2">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Package2.Name}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Package 3">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Package3.Name}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Package 4">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Package4.Name}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

You cannot use the same CellTemplate for all 4 columns. If the CellTemplate is more complicated than what you have showed here, you might want to consider creating the templates programmatically. Please refer to my answer here for an example of how you can do this.

mm8
  • 163,881
  • 10
  • 57
  • 88
  • 1
    Yeah I was trying to avoid creating 4 different "Template"s. Not sure if there is any other way around this. I'll keep looking. – Ehsan Iran-Nejad Oct 29 '18 at 15:55
  • 1
    There is no other way besides created the templates programmatically. Then you don't have to repeat the almost same markup 4 times. – mm8 Oct 29 '18 at 15:58
  • I did what you suggested. DataGridTemplateColumn and DataTemplate is generated in code-behind for each column. Thanks a lot – Ehsan Iran-Nejad Oct 29 '18 at 20:52