12

Basically in need to achieve something like this using treeview control in wpf: (random picture)


(source: msdn.com)

Where nodes and child nodes have same headers.

I googled a lot, but my knowledge in wpf not that good.

Here is my parent node class:

 public class Parent : PropertyChangedBase
    {
        public string ParentName { get; set; }
        public BindableCollection<Child> Children { get; set; }
    }

And child:

public class Child : PropertyChangedBase
{
    public string ChildName { get; set; }
}

My xaml tree view:

  <TreeView Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Nodes}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type projectModels:Parent}" ItemsSource="{Binding Children}">
                <StackPanel>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="20"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <CheckBox Grid.Column="2"></CheckBox>
                        <TextBlock Grid.Column="1" Text="{Binding ParentName}">
                        </TextBlock>
                    </Grid>
                </StackPanel>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type projectModels:Child}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding ChildName}"></TextBlock>
                </StackPanel>
            </DataTemplate>
        </TreeView.Resources>
    </TreeView>

I tried using Grid but obviously it create different grids, so I can relay on column width.

I tried How to make gridview a child element of a treeview in wpf application , but they use ListView. It's not an option for me right now, as treeviewitem selection functionality is tightly coupled with my treeview and code behind.

Any ideas how it can be done? Thanks.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
makambi
  • 1,100
  • 3
  • 13
  • 30
  • Did your code work, other than a problem with the column widths being different in each item? – Andrew Stephens Jul 04 '14 at 08:32
  • Yeah, it work but not in the way I need it to be done. I need common headers for tree view and it's sub nodes. So I can resize them all, and nodes' with was the same. – makambi Jul 04 '14 at 08:36

2 Answers2

21

Try this xaml

  <TreeView x:Name="treeviewList"  ItemsSource="{Binding ManufacturerList}">
    <TreeView.ItemTemplate>
        <DataTemplate>
            <TreeViewItem  ItemsSource="{Binding Models}">
                <TreeViewItem.Header>
                    <Grid Width="350">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="100"></ColumnDefinition>
                            <ColumnDefinition Width="Auto" MinWidth="50"></ColumnDefinition>
                            <ColumnDefinition ></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Task}" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="0"/>
                        <TextBlock Text="{Binding durationTotal}" Margin="10,0,10,0" HorizontalAlignment="Left" VerticalAlignment="Center"  Grid.Column="1"/>
                        <TextBlock Text="{Binding HeadNote}" HorizontalAlignment="Left"  VerticalAlignment="Center"  Grid.Column="2"/>
                    </Grid>
                </TreeViewItem.Header>
                <TreeViewItem.ItemTemplate>
                    <DataTemplate>
                        <Grid Margin="-20,0,0,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100"></ColumnDefinition>
                                <ColumnDefinition Width="Auto" MinWidth="50"></ColumnDefinition>
                                <ColumnDefinition></ColumnDefinition>
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding SubTask}" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="0"/>
                            <TextBlock Text="{Binding Duration}" Margin="10,0,10,0" HorizontalAlignment="Left" VerticalAlignment="Center"  Grid.Column="1"/>
                            <TextBlock Text="{Binding Notes}" HorizontalAlignment="Left" VerticalAlignment="Center"  Grid.Column="2"/>
                        </Grid>
                    </DataTemplate>
                </TreeViewItem.ItemTemplate>
            </TreeViewItem>
        </DataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

c# code

public class Company
{
    public string Task { get; set; }
    public string durationTotal { get; set; }
    public string HeadNote { get; set; }
    public List<Model> Models { get; set; }
}
public class Model
{
    public string SubTask { get; set; }
    public string Duration { get; set; }
    public string Notes { get; set; }      
}

   List<Company> ManufacturerList = new List<Company>();

        ManufacturerList.Add(new Company()
        {
            Task = "Coding",
            durationTotal = "4",
            HeadNote = "Coding Task",
            Models = new List<Model>()
            {new Model(){SubTask = "Write", Duration = "2", Notes ="It pays the bills" },
            new Model(){SubTask = "Compile", Duration = "1", Notes ="c# or go home" },
            new Model(){SubTask = "Test", Duration = "1", Notes ="works on my m/c" },}
        });


        ManufacturerList.Add(new Company()
        {
            Task = "Communicate",
            durationTotal = "2",
            HeadNote = "Communicate Task",
            Models = new List<Model>()
            {new Model(){SubTask = "Email", Duration = "0.5", Notes ="so much junk mail"  },
            new Model(){SubTask = "Blogs", Duration = "0.25", Notes ="blogs.msdn.com/delay" },
            new Model(){SubTask = "Twitter", Duration = "0.25", Notes ="RT:nothing to report" },}
        });

        treeviewList.ItemsSource = ManufacturerList;

Result

enter image description here

Heena
  • 8,450
  • 1
  • 22
  • 40
  • How to add fixed headers as datagrid column headers? – Siddhi Kamat Jul 15 '21 at 16:14
  • To add fixed headers, we could Put everything together in a Dockpanel, add a Datagrid with just the DataGridTextColumn width spec and x:Name="col0" then connect the ColumnDefinition Grid to each other using Width="{Binding ElementName=col0,Path=ActualWidth}". Ref: https://coderoad.ru/37433320/WPF-TreeView-ItemTemplate-%D0%B2%D1%8B%D1%81%D0%B0%D0%B4%D0%BA%D0%B8 – Damian Nass Sep 19 '21 at 08:53
7

If the only problem with your code is that each treeview item renders with different grid column widths, you can try the "share size scope" feature to align them all. In the TreeView control, set Grid.IsSharedSizeScope to true:-

Then add a SharedSizeGroup to the ColumnDefinitions that should have the same width across all the treeview items (your first column definition has a fixed width anyway, so it's not needed on that):-

<Grid.ColumnDefinitions>
   <ColumnDefinition Width="20" />
   <ColumnDefinition Width="Auto" SharedSizeGroup="A" />
   <ColumnDefinition SharedSizeGroup="B" />
</Grid.ColumnDefinitions>

The values are just strings used to "name" the columns, and can be anything you like.

Andrew Stephens
  • 9,413
  • 6
  • 76
  • 152