具有有效负载实体的HierarchicalDataTemplate和多对多导航绑定问题

时间:2021-12-03 12:40:19

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

我有两个具有Payload实体的多对多,如下所示:

具有有效负载实体的HierarchicalDataTemplate和多对多导航绑定问题

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.

因此,为了使用部件号:MasterPartNumber.pn存储在MasterPartNumber中的程序集,我使用导航属性ParentBOMs,它由关系给出:MasterPartNumber.pnID = MasterPartsList.parentPnID。这给了我父汇编下的所有子pnID。

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

要获取该程序集的子部件号,我使用由MasterPartsList.pnID = MasterPartNumber.pnID定义的ChildPn导航属性。

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

请注意,顶层程序集项未列在MasterPartsList中(它们的parentPnID为null)。

My TreeView HierarchicalDataTemplate binding is:

我的TreeView HierarchicalDataTemplate绑定是:

<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.

我相信这是正确的。我可以单步执行调试器,看到为每个具有子信息的项目填充了整个BOMItem导航属性(ParentBOM.ChildPn.pn)。

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

为什么我无法在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?

我需要额外的转换器吗?我是否需要进一步定义我的ObservableCollection对象包装器的“getter”?

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 !

请帮忙!谢谢 !

1 个解决方案

#1


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.

您可能必须为要呈现的域类型创建包装器VM类型。说.. MasterPartVM。您现在可以使用2条路线的逻辑定义属性,例如儿童。您的层次结构数据模板将始终使用此属性扩展下一级别。

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..

这将使您在实施MasterPartVM.Children时找到合适的孩子的责任 - 您似乎已经确定了这一点。如果我误解了这个问题,请告诉我。

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>

#1


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.

您可能必须为要呈现的域类型创建包装器VM类型。说.. MasterPartVM。您现在可以使用2条路线的逻辑定义属性,例如儿童。您的层次结构数据模板将始终使用此属性扩展下一级别。

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..

这将使您在实施MasterPartVM.Children时找到合适的孩子的责任 - 您似乎已经确定了这一点。如果我误解了这个问题,请告诉我。

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>