views:

107

answers:

1

Is it possible and if so what is the best way to implement the following hierarchical structure in a silverlight (4) TreeView control? (where Item and Group are classes which can exist in the tree).


Group
|
|-Item
|
|-Group
| |
| |-Item
| |
| |-Item
|
|-Item

The structure could of course be arbitrarily more complex than this, if needed.

HierarchicalDataTemplates appear to be the way to approach this, but I'm specifically having trouble understanding how I might apply the template to interpret the different classes correctly.

A similar question was asked for WPF, the answer for which made use of the TargetType property on the HierarchicalDataTemplate, but I am uncertain whether that property is available in the silverlight version since I don't appear to have access to it in my environment.

+1  A: 

For Silverlight, you might need to create a converter to help do this. For instance, a "target type data template selector" or similar.

Though you could get more advanced, here is an example from the Silverlight unit test framework that allows you to provide instances of data templates for hard-coded types. A generalized version could probably be made in about 20 minutes.

To use this, you'd provide instances of data templates - in your case though, you'd probably need to make them hierarchical.

<local:DataTemplateSelector 
    x:Key="DetailsViewDataTemplate"
    DefaultDataTemplate="{StaticResource DefaultDataTemplate}"
    TestMethodTemplate="{StaticResource TestMethodDataTemplate}"
    TestClassTemplate="{StaticResource TestClassDataTemplate}"/>

And here is the implementation:

/// <summary>
/// A specialized data template selector.
/// </summary>
public sealed class DataTemplateSelector : IValueConverter
{
    /// <summary>
    /// Gets or sets the default data template.
    /// </summary>
    public DataTemplate DefaultDataTemplate { get; set; }

    /// <summary>
    /// Gets or sets the test method template.
    /// </summary>
    public DataTemplate TestMethodTemplate { get; set; }

    /// <summary>
    /// Gets or sets the test class template.
    /// </summary>
    public DataTemplate TestClassTemplate { get; set; }

    /// <summary>
    /// Initializes a new instance of the DataTemplateSelector type.
    /// </summary>
    public DataTemplateSelector()
    {
    }

    /// <summary>
    /// Convert a value to a data template.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="targetType">The target parameter.</param>
    /// <param name="parameter">ConverterParameter value.</param>
    /// <param name="culture">The culture parameter.</param>
    /// <returns>Returns the object.</returns>
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            Type type = value.GetType();

            if (typeof(TestMethodData).TypeHandle == type.TypeHandle)
            {
                return TestMethodTemplate;
            }
            else if (typeof(TestClassData).TypeHandle == type.TypeHandle)
            {
                return TestClassTemplate;
            }
        }

        return DefaultDataTemplate;
    }

    /// <summary>
    /// No 2-way databinding support.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="targetType">The target parameter.</param>
    /// <param name="parameter">ConverterParameter value.</param>
    /// <param name="culture">The culture parameter.</param>
    /// <returns>Returns the object.</returns>
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}
Jeff Wilcox
Dan Wray