Kilazur
Kilazur

Reputation: 3188

TreeView with inherited types

I want to display a TreeView containing elements implementing an interface. This interface is implemented by two main classes, which are the ones I want to display.

The schema is something like:

IElement
    Container : IElement
      ->public IEnumerable<IElement> Elements {get; set;}
    Element : IElement

So basically, this TreeView must be able to display Containers and Elements on any level. Containers should be "expandable" (since they contain other IElements), but Elements should not.

So this solution doesn't seem to fit, since it's setting two completely different levels (Enterprise/Employees).

I don't see how I can fill a TreeView with IElements while being able to check weither they're Containers or Elements, and how to prevent expansion of only one of these types.

Upvotes: 2

Views: 443

Answers (2)

eran otzap
eran otzap

Reputation: 12533

Is this something along the lines of what your looking for ? here's a sample :

CS :

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public List<IElement> Elements
    {
        get
        {
            var list = new List<IElement>();

            list.Add(BuildContainer());
            list.Add(BuildContainer());
            list.Add(new Element());

            return list;
        }
    }

    private Container BuildContainer()
    {
        var container = new Container();

        container.Elements.Add(new Element());
        container.Elements.Add(new Element());

        var sub_container = new Container();
        sub_container.Elements.Add(new Element());

        container.Elements.Add(sub_container);

        return container;
    }
}

public interface IElement
{
     string Title { get; }
}

public class Container : IElement
{
    public string Title
    {
        get { return "Container"; }
    }

    private ObservableCollection<IElement> elements;
    public ObservableCollection<IElement> Elements
    {
        get
        {
            if (elements == null)
            {
                elements = new ObservableCollection<IElement>();
            }
            return elements;
        }
    }
}

public class Element : IElement
{
    public string Title
    {
        get { return "Element"; }
    }
}

XAML :

<Window
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>

    <DataTemplate DataType="{x:Type local:Element}">
        <TextBlock Text="{Binding Title}" Foreground="Red" FontSize="14"/>
    </DataTemplate>

    <HierarchicalDataTemplate DataType="{x:Type local:Container}" ItemsSource="{Binding Elements}">
        <TextBlock Text="{Binding Title}" Foreground="Black" FontWeight="Bold" FontSize="16"/>
    </HierarchicalDataTemplate>
</Window.Resources>


<Grid>
    <TreeView ItemsSource="{Binding Elements}" />
</Grid>

Result :

enter image description here

Upvotes: 3

Nitin Joshi
Nitin Joshi

Reputation: 1668

Add one more property IsExpandable of type bool to your IElement interface. Set this property to true for Container class only and use this property in Binding or Trigger for your TreeViewItem.

Upvotes: 0

Related Questions