views:

38

answers:

2

I am relatively new to the Silverlight experience and am trying to create a MVVM app with a DomainService that returns POCOs as the models. I have a UserControl that has a TreeView with the ItemsSource set to bind to an ObservableCollection of a type that has an ObservableCollection as one of it's properties, and that collection is of a type that has a property of ObservableCollection. So I'm using the HierarchicalDataTemplate as the ItemTemplate of the TreeView with TextBlocks to render the Name property of each item. I will include some code below.

So the classes would be something like this:

public class A
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ObservableCollection<B> Bs { get; set; }
}

public class B
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ObservableCollection<C> Cs { get; set; }
}

public class C
{
    public int ID { get; set; }
    public string Name { get; set; }
}

Basically, my collections are getting populated from a DataRepository with a method that gets lists of A,B, and C. Adds each instance appropriately with LINQ through foreach loops. And returns a List. The method works correctly as I have called it from the default.aspx.cs and stepped through to confirm that all data is correctly added.

But my problem is that when it is rendered on the screen, none of the collections are correct. For instance, the first item of "A"'s child collection of "B" should have a count of over 4000 and yet none are shown. And yet, the first item of "B" that is supposed to be in the collection "Bs" of the first "A" is shown for the second item of "A".

(example of what it should be)

  • a1

    • b1.1
      • c1.1.1
      • c1.1.2
      • c1.1.3
    • b1.2
      • c1.2.1
      • c1.2.2
  • a2

    • b2.4
      • c2.4.1
      • c2.4.2
      • c2.4.3
  • a3

    • b3.6
      • c3.6.1
      • c3.6.2
      • c3.6.3
  • a4

    • b4.8
      • c4.8.1
      • c4.8.2
      • c4.8.3

(example of what it is showing)

  • a1
  • a2
    • b2.2
      • c2.2.2
  • a3
  • a4
    • b4.4
      • c4.4.4

After some investigation, the only pattern that I see is that the hierarchy is based on the ID's being the same.

Here are the code samples:

(the DataContext is set by a UserControl Resource)

<sdk:TreeView ItemsSource="{Binding Path=As}" >
 <sdk:TreeView.ItemTemplate>`  
  <sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Bs}">
   <TextBlock Text="{Binding Path=Name}" />
   <sdk:HierarchicalDataTemplate.ItemTemplate>
    <sdk:HierarchicalDataTemplate ItemsSource="{Binding Path=Cs}">
     <TextBlock Text="{Binding Path=Name}" />
     <sdk:HierarchicalDataTemplate.ItemTemplate>
      <sdk:HierarchicalDataTemplate ItemsSource="{Binding}">
       <TextBlock Text="{Binding Path=Name}" />
      </sdk:HierarchicalDataTemplate>
     </sdk:HierarchicalDataTemplate.ItemTemplate>
    </sdk:HierarchicalDataTemplate>
   </sdk:HierarchicalDataTemplate.ItemTemplate>
  </sdk:HierarchicalDataTemplate>
 </sdk:TreeView.ItemTemplate>
</sdk:TreeView>

ViewModel

public class myViewModel
{
    private myDomainContext context = new myDomainContext();

    public ObservableCollection<A> As
    {
        get
        {
            LoadOperation<A> loadOp = context.Load(context.GetAsQuery());
            return new ObservableCollection<A>(loadOp.Entities);
        }
    }
}

I apologize about the length of this question, I was hoping to not be so vague and to get some helpful advise. This issue has been plaguing me for a few days now and I'm sooo ready to move on. Please help me get out of the muck. Thanks in advance. And if you have any good links that would be helpful for my MVVM knowledge I would greatly appreciate them as well.

My Environment is: - Asp.Net 4 - Silverlight 4 - VisualStudio 2010

A: 

I was under the impression that a HierarchicalDataTemplate is used hierarchically :) That is, you use one only and it recursively applies to any children.

This does mean that the data keys must be related and the data uniform (of the same type).

The template you have described above is basically nesting 3 templates inside each other, so you get the first record of each displayed (where there is child data).

Enough already
From what I've noticed recently is that you may be on to something. I'm starting to read about the ItemTemplateSelectors which may have something to do with getting me by this.
jhorton
After a couple days of looking into my issue, I discovered that my data/collections was being populated correctly on the server. But after the DomainService was called and the LoadOperation of the DomainContext completed the load, did I discover that the collections were wrong. And that is why nothing was rendering correctly. So I will start a new thread with a request for help on this matter. I have marked this as the answer because it was the actual truth to the matter. I was misusing the HierarchicalDataTemplate. So thank you Enough for your help. Happy codings everyone.
jhorton
A: 

I think that one thing you should definitely consider is to make the objects implement the INotifyPropertyChanged. See this example http://snipplr.com/view/13639/viewmodelbase-class/

In that case you have to alter the properties a little bit

private int _id;

public int Id
{
     get { return _id;}
     set { _id = value; NotifyChanged("Id");}
}

It doesn't have to be inside of a Property. When you update the child collection for instance the Bs you can call NotifyChanged("Bs")

This will signal that the property has been updated.

Jeppe Vammen Kristensen
@Jeppe Vammen Kristensen: re *NotifyChanged("Bs")*: Unless the Bs list is actually replaced itself, ObservableCollection already sends out change notifications for its own content changes.
Enough already
That is correct, but it's something you should be aware of if you indeed generate the ObservableCollection from a List, Queryable or Enumerable.
Jeppe Vammen Kristensen
Not to sound ungrateful for your comments, but I think you guys missed the context of the question. Basically the answer is that the hierarchical template has to use the same data type where I was wanting to display a tree with three data types. So my solution is that I'm creating a HierarchicalTreeView that will add new items based on the collections found within the original itemssource collection. I'll also paste my classes here in case anyone else comes across this situation. Plus I would like to get some feedback on the classes if possible. Thanks again for the comments.
jhorton