HierarchicalDataTemplate and Many-To-Many with Payload Entities Navigation Binding Issue
Asked Answered
F

1

1

I have two Many-To-Many with Payload entities as shown below:

Entity Snapshot

So, to make an Assembly stored in MasterPartNumber with a part number: MasterPartNumber.pn, I use the navigation property ParentBOMs, which is given by the relationship: MasterPartNumber.pnID = MasterPartsList.parentPnID. This gives me all the child pnIDs under that parent assembly.

To get the child part numbers for that assembly, I use the ChildPn navigation property, defined by MasterPartsList.pnID = MasterPartNumber.pnID.

Please note that top level assembly items are NOT listed in MasterPartsList (they would have a parentPnID that is null).

My TreeView HierarchicalDataTemplate binding is:

<TreeView x:Name="AssemblyTreeView"
          ItemsSource="{Binding BOMItems}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate DataType="{x:Type local:MasterPartNumber}"
                              ItemsSource="{Binding ParentBOMs.ChildPn}">
      <TextBlock Text="{Binding pn}" />
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

Which I believe to be correct. I can step through the debugger and see that the entire BOMItem navigation properties are populated (ParentBOM.ChildPn.pn) for each item that has child information.

WHY am I unable to see these child properties populated in my TreeView?!

What I should get:

Root Assembly
--Sub Assembly
----Sub Assembly
------Child (n-levels deep)

And

What I actually get:

Root Assembly

Do I need an additional converter? Do I need to define my ObservableCollection object wrapper's "getter" further?

Known possible sources of the problem:
1. Entity Framework is lazy loading, and just hasn't loaded the navigation properties I see in
   the debugger being populated. (No, set LazyLoading to false.)
2. My HierarchicalDataTemplate isn't probing for children just on the fact that it has children
   -- aka it only understands to switch the binding path when a new DataType is available, or 
   something like that. (Not likely, because I've seen HierarchcialDataTemplates for self-referencing entities of a single entity type.)

What I have right:
1. I can cascade down the binding route I told my TreeView to take in the debugger. 
    Parent `pn` is populated as well as its `ParentBOMs.ChildPn.pn`. 

Please help! Thank you !

Frazzle answered 19/4, 2013 at 0:50 Comment(0)
L
0

Not able to get an idea of what the expected output should be ? Can you draw the tree and post it.

You may have to create a wrapper VM type for the domain type you want to present. say.. MasterPartVM. You can now define a property with the logic for the 2 routes e.g. Children. Your hierararchical data template will always expand the next level using this property.

This will put the onus of finding the right children on your implementation of MasterPartVM.Children - which you seem to have nailed down. Let me know if I have misunderstood the problem..

e.g. In the linked post, you can see that I used a wrapper property to combine Subgroups and Entries to collate a single list.

Here's another example

public class MyPart
    {
        public string Name { get; set; }
        public bool IsRoot { get; set; }
        public string[] ChildNames { get; set; }
        public IList<MyPart> Children { 
            get {
                if (IsRoot)
                    return ChildNames.Select(c => new MyPart { Name = c, ChildNames =new[]{c} }).ToList();
                else
                    return new List<MyPart>{new MyPart { Name = "No more children" }};
        } }
    }

MyPartsCollection = new ObservableCollection<MyPart>();
            MyPartsCollection.Add(new MyPart
            {
                Name = "Root1",
                IsRoot = true,
                ChildNames = new []{"Item1", "Item2", "Item3"}
            });
<TreeView ItemsSource="{Binding MyPartsCollection}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate DataType="{x:Type local:MyPart}"
                              ItemsSource="{Binding Children}">
      <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>
Lousy answered 22/4, 2013 at 13:42 Comment(4)
I completely rewrote this after thinking about what you said, and what the root of my problem is after looking through the debugger. The problem is that I can't see the difference between what I have the potential to bind to (my fully functioning hierarchical ObservableCollection), and what the HierarchicalDataTemplate is actually binding to.Frazzle
do you know all the ways HierarchicalDataTemplate understands when to create a new branch?Frazzle
@UB3571 - Check to see if you can see any Binding errors in the Output window. Also check to see if the return type of your ItemsSource property has the return type as the one that your hierarchical data template knows how to render. Finally try creating a similar toy example (without the Entity framework) - this will help you nail down a working hieararchical data template first. If you see issues again when using the real code, your problem lies somewhere else.. not in presentation.Lousy
thanks VERY much for this help. I ended up being able to use my ViewModel wrapper for each TreeView Item with a "children" collection property on it. Still figuring out the discrepancy between that and my plain old ObservableCollection of Entities. I will get back to this this weekend, but I am sure with the help you've provided I've got it.Frazzle

© 2022 - 2024 — McMap. All rights reserved.