views:

606

answers:

2

Hi, I have the following class structure:

class Organization
{
    string Name;
    List<User> users;
    List<Organization> Children;
}

class User
{
    string Name;
}

I cannot modify these classes. I need to display all the information about organizations and users in one TreeView control. I.e., organization nodes should contain suborganization and user nodes. The question is how can I do this having no CompositeCollections or Multibindings in Silverlight?

A: 

I misread the question - I don't know of a way for the SL tree to display both the Children property and the Users property as child nodes. You may want to create a wrapper class with an AllChildren property that returns Users and Organizations in the same collection. The SL tree's HierarchialDataTemplate has a single property called ItemsSource that should be bound to a single child collection. Sorry I couldn't be more help - I'd delete this answer but I don't see a way to do that.

James Cadd
This XAML doesn't do what the user is looking for. Where is it showing any details on the Users collection and what is ShortTitle?
Ray Booysen
+1  A: 

The tricky part of this solution is having to deal with two collections underneath each node and TreeView's HierarchicalDataTemplate only supports binding to a single ItemsSource.

One option is to create a ViewModel that merges the collections into a single class that represents an entry in the TreeView that you can then bind to inside your HierarchicalDataTemplate.

First I created my ViewModel class:

public class TreeViewEntry
{
    public string Name { get; set; }
    public IEnumerable<TreeViewEntry> Children { get; set; }
    public object Model { get; set; }
}

Then I used a function, some Linq and some recursion to pull all the objects into a single collection:

private IEnumerable<TreeViewEntry> OrganizationsToTreeViewEntries(IEnumerable<Organization> orgs)
{
    return (from o in orgs
            select new TreeViewEntry
            {
                Name = o.Name,
                Model = o,
                Children = (from u in o.Users
                            select new TreeViewEntry
                            {
                                Name = u.Name,
                                Model = u
                            }
                            ).Concat(OrganizationsToTreeViewEntries(o.Children))
            });
}


public MainPage()
{
    InitializeComponent();

    var items = OrganizationsToTreeViewEntries(existingOrganizationData);
    OrgTree.ItemsSource = items;
}

Now that I have a merged ItemsSource it's easy to style my HierarchicalDataTemplate:

<UserControl.Resources>
    <common:HierarchicalDataTemplate x:Key="OrgTemplate" ItemsSource="{Binding Children}">
        <StackPanel>
            <TextBlock Text="{Binding Name}"  />
        </StackPanel>
    </common:HierarchicalDataTemplate>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource SampleDataSource}}">
    <controls:TreeView x:Name="OrgTree" HorizontalAlignment="Left" Margin="8,8,0,8" Width="225" ItemTemplate="{StaticResource OrgTemplate}" />
</Grid>

You can use a ValueConverter to tweaks things like FontWeight if you want to adjust the visual style of certains elements (for example in my testing I created a ValueConverter on FontWeight that was bound to the Model property of TreeViewEntry).

Shawn Oster