I have a list of tasks which has a nested list of tasks. Now I want to show this list grouped in a WPF DataGrid using MVVM pattern. The TaskName of the "outer" Task should be the Title of the Group, all nested Tasks should be shown below.
The result should look like this: Example
public class ProjectTask
{
public Guid TaskUID { get; set; }
public string TaskName { get; set; }
public DateTime TaskStartDate { get; set; }
public DateTime TaskFinishDate { get; set; }
public List<ProjectTask> SubTasks { get; set; } = new();
}
public List<ProjectTask> ProjectTasks
{
get { return projectTasks; }
set { projectTasks = value; OnPropertyChanged(); }
}
What I tried so far, was creating a CollectionViewSource
<CollectionViewSource x:Key="GroupedTaskList" Source="{Binding ProjectTasks}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="SubTasks" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
and bind it to a DataGrid
<DataGrid AutoGenerateColumns="False" IsReadOnly="True"
ItemsSource="{Binding Source={StaticResource GroupedTaskList}}"
>
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="Name" Binding="{Binding Path=TaskName}" />
<DataGridTextColumn Header="Start" Binding="{Binding Path=TaskStartDate, StringFormat=d}" />
<DataGridTextColumn Header="End" Binding="{Binding Path=TaskFinishDate, StringFormat=d}" />
</DataGrid.Columns>
</DataGrid>
But how can I group the Tasks?
CodePudding user response:
<DataGrid.Columns>
<DataGridTextColumn Header="" AutomationProperties.Name="" IsReadOnly="True" Binding="{Binding Path=TaskName}"/>
<DataGridTextColumn Header="" AutomationProperties.Name="" IsReadOnly="True" Binding="{Binding Path=TaskStartDate, StringFormat=d}"/>
<DataGridTextColumn Header="" AutomationProperties.Name="" IsReadOnly="True" Binding="{Binding Path=TaskEndDate, StringFormat=d}"/>
<DataGridTemplateColumn Header="Sub Tasks" AutomationProperties.Name="">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ListView ItemsSource="{Binding SubTaskList}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SubTask}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
I was able to achieve it using a template column like this, Hope this helps.
Edited After Understanding Question better
<DataGrid ItemsSource="{Binding Tasks}" AutoGenerateColumns="false"
RowDetailsVisibilityMode="Visible"
CanUserAddRows="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="Task Name" Binding="{Binding TaskName}"/>
<DataGridTextColumn Header="Task Start Date" Binding="{Binding TaskStartDate}"/>
<DataGridTextColumn Header="Task End Date" Binding="{Binding TaskStartDate}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding SubTasks}" AutoGenerateColumns="false" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Sub Task Name" Binding="{Binding TaskName}"/>
<DataGridTextColumn Header="Sub Task Start Date" Binding="{Binding TaskStartDate}"/>
<DataGridTextColumn Header="Sub Task End Date" Binding="{Binding TaskStartDate}"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
Just a quick view of what this does https://imgur.com/OIc9uCr