0

The source code can be found here : https://www.codeproject.com/Articles/24973/TreeListView

The way the original author has set it up, is the data is filled in the xaml itself. I need to create the TreeViewList inside of my ViewModel, but I can't figure out how to bind my own TreeViewList within the xaml to display it properly.

Here's an example of me creating a tree in the code behind and calling the window.

    public TreeListView TreeList { get; set; } = new TreeListView();

    private void generateTree()
    {
        TreeList.Columns.Add(new GridViewColumn() { Header = "Col1" });
        TreeList.Columns.Add(new GridViewColumn() { Header = "Col2" });
        TreeList.Columns.Add(new GridViewColumn() { Header = "Col3" });
    }

    public ICommand AssemblyTreeCommand => new RelayCommand(AssemblyTree, p => CanAssemblyTree);
    public bool CanAssemblyTree { get; set; } = true;
    private void AssemblyTree(object parameter)
    {
        generateTree();
        AssemblyTreeDialogWindow dialog = new AssemblyTreeDialogWindow()
        {
            DataContext = this,
            Topmost = true
        };
        dialog.ShowDialog();

    }

AssemblyTreeDialog Window class looks like this:

   <local:TreeListView AllowsColumnReorder="True" ItemsSource="{Binding TreeList}">
        <!--Create an item template to specify the ItemsSource-->
        <local:TreeListView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Children}" />
        </local:TreeListView.ItemTemplate>
        <local:TreeListView.Columns>
            <!--Create the first column containing the expand button and the type name.-->
            <GridViewColumn Header="Name" Width="200">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <!--The Expander Button (can be used in any column (typically the first one))-->
                            <local:TreeListViewExpander/>
                            <!--Display the name of the DataElement-->
                            <TextBlock Text="{Binding}"/>
                        </StackPanel>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <!--Create a second column containing the number of children.-->
            <GridViewColumn Header="Children" Width="100">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <!--Display the size of the DataElement-->
                        <TextBlock Text="{Binding Children.Count}" HorizontalAlignment="Right"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <!--Create a third column containing the brush of the material.-->
            <GridViewColumn Header="Brush" Width="100">
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <!--Border showing the actual color-->
                            <Border Background="{Binding Brush}" CornerRadius="2"
                                    Width="16" Height="16"
                                    BorderThickness="1" BorderBrush="DarkGray"/>
                            <!--Display the brush-->
                            <TextBlock Text="{Binding Brush}"/>
                        </StackPanel>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </local:TreeListView.Columns>
        <!--Create some sample data-->
        <MaterialGroup>
            <MaterialGroup>
                <DiffuseMaterial Brush="Blue"/>
                <DiffuseMaterial Brush="Red"/>
                <SpecularMaterial Brush="Orange"/>
            </MaterialGroup>
            <EmissiveMaterial Brush="AliceBlue"/>
        </MaterialGroup>
    </local:TreeListView>

Interestingly if I bind the line <GridViewColumn Header="Name" Width="200"> so that it reads <GridViewColumn Header="{Binding TreeList}" Width="200">it gives me this:

testcase1

I'll explain my end goal as best as possible.

The System is a giant list of parts. A main table displays all of the parts while a subtable displays all of the parts which make up that part. All parts (including those which are used to create other parts) exist within the MainTable. So a Parent part might have a set of children parts, which each individually have children parts which they are made up of. This is the relationship i'm trying to model using this tool.

The code that I've written maps the parts list out into a list of class objects which contain the data. I'll post it below. It's working to map to a TreeView right now.

Result

A datastructure I've based it off is here : Treeview with multiple columns

private void generateTree(string PN)
{
    Proces selectedRow = new Proces() { procesId = (int)Vwr.Table.SelectedRow.Row["PID"], procesName = (string)Vwr.Table.SelectedRow.Row["PN"], subProcesses = generateSubtable(PN) };
    processes.Add(selectedRow);
}


public List<Proces> generateSubtable(string PN)
{
    List<Proces> subTable = new List<Proces>();

    foreach (DataRow mplrow in Vwr.Table.Tbl.Rows) if (mplrow["PN"].ToString() == PN)
            MainVM.Modules.AllModules[0].SubVwr.Tables[0].LoadTableQuery.Prms[0].Val = mplrow[0];
    MainVM.Modules.AllModules[0].SubVwr.Tables[0].Tbl = Db.GetTable(MainVM.Modules.AllModules[0].SubVwr.Tables[0].LoadTableQuery);

    foreach (DataRow sub in MainVM.Modules.AllModules[0].SubVwr.Tables[0].Tbl.Rows)
    {
        Proces subItem = new Proces() { procesId = (int)sub["ItemNo"], procesName = sub["PN"].ToString(), subProcesses = generateSubtable(sub["PN"].ToString()) };
        subTable.Add(subItem);
    }

    return subTable;
}
Tristan
  • 96
  • 13
  • Why do you need to create the entire tree in code behind... Can you not just create the data in the code behind (or preferably view model) and just bind the ItemsSource to it? – chancea Mar 08 '18 at 20:00
  • Sure. The columns will be static, the amount of children will be variable. I'm looking for help with how/where to bind things. And sorry by code behind I meant viewModel * – Tristan Mar 08 '18 at 20:04
  • If you post the class object you are using to hold the information of a row I can post a formal answer, you basically just bind the ItemsSource to the collection of that class and then bind each column to a property of that class. – chancea Mar 08 '18 at 20:12
  • @chancea I'll post it one sec. – Tristan Mar 08 '18 at 20:16
  • Yeah that link you showed is more the route I was thinking. You would have an object that holds each column value along with a list of sub rows. You would need to create such a class and covert each datarow to that object. then set the ItemsSource binding to a list of that object. – chancea Mar 08 '18 at 21:28
  • @chancea would you be willing to type out the syntax for binding that kind of list datastructure to this xaml? It's a List , Proces holds the data, so ProcesID, ProcesName. and "SubProces", a pointer to it's own List (children) – Tristan Mar 09 '18 at 14:08
  • I was looking into the codeproject source code. He didnt add a way to bind directly to the source it seems... you will have to read more into how he wants you to do it or modify the source code... – chancea Mar 10 '18 at 00:36
  • It has to be generic and you need to know the binding for each. You need TreeView to have a DateTemplate that binds to a collection in a ViewModel. That collection needs to have the other collections within it also as ViewModels etc. Each DataTemplate within the TreeView should look for the inner property name to bind to. In other words, don't try to list it all in one ViewModel but build each ViewModel as part of the tree with it's own collection in each and write the DataTemplates to target each ViewModel distinctly. – Michael Puckett II Mar 10 '18 at 02:55

1 Answers1

0

Found the answer! After some pretty extensive searching, and trying many different solutions. Thought i'd post incase someone else might also be trying to do the same.

credit: http://dlaa.me/blog/post/9898803

Tristan
  • 96
  • 13