简体   繁体   中英

How to make TreeView of unknown depth WPF and Silverlight in XAML?

coders!

UPDATE

Solution is easy: make sure the properties you read have explicit getter. Foo{ get; private set; }

I have a problem here: First thing you must know: I must use the same .xaml file for WPF and Silverlight.

I'd like to have a TreeView containing nodes of type "Employee", let's say. An employee can have employees working for him, or may not have any.

I have a list (Collection) which I can use as an ItemsSource. The Employee class contains a Collection of Employees: empty (not null) if nobody works for him and non-empty when he is a boss of some people.

Good examples I found: http://msdn.microsoft.com/en-us/library/cc165616(v=vs.110).aspx http://blogs.msdn.com/b/mikehillberg/archive/2009/10/30/treeview-and-hierarchicaldatatemplate-step-by-step.aspx

I have a " MyTreeView " class which I can use for WPF and Silverlight too, and same applies to " MyHierarchicalDataTemplate ", and also to " MyTreeViewItem ", so no problem here.

My Resources section contains this:

<local:MyHierarchicalDataTemplate x:Key="treeTemplate" ItemsSource="{Binding Employees}">
    <StackPanel Orientation="Horizontal">
        <MyControls:MyTreeViewItem Header="{Binding Name}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Width="40" Text="{Binding Age}" />
   <!-- and so on... -->
            </StackPanel>
            <ListBox ItemsSource="{Binding Employees}" />

            <!-- I tried to make it recursive this way. Result: exception or malfunction. -->
            <!--<MyControls:MyTreeView ItemsSource="{Binding Path=Relations}">
            </MyControls:MyTreeView>-->

        </MyControls:MyTreeViewItem>
    </StackPanel>
</local:MyHierarchicalDataTemplate>

Employee data structure:

Big "Boss" John
 -- Fred
 -- George
 -- Harry
 ---- Snape
 ---- Dumbledore
 ------ Alastor
 ------ Hermione
 -- Mark
 -- Steve
 ---- Stewie
 ------ Dad
 -------- Meg
 -------- Death
 ------ Mother
 ------ World

Question:

How can I fill the TreeView? Every node and leaf is of type " Employee " Remember: the hard part is to make it work in WPF AND also in Silverlight.

Notes I tried DataType="{x:Type local:Employee}" (or similar) but my x namespace does not seem to contain x:Type. It seems that I can't use XmlDataProvider . I want to keep MVC/MVVC model as much as I can.

related namespaces:

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

Code-behind for class Employee

public class Employee
    {
        public Employee()
        {
            this.StationFromId = "";
            this.StationFromName = "";
            this.StationToId = "";
            this.StationToName = "";

            this.BackGroundColor = Colors.White;
            this.ForeGroundColor = Colors.Black;
        }

        public Employee(string fromStationId, string name, int age, List<Employee> children)
        {
            this.Name = name;
            this.Age = age;

            if (children != null)
            {
                this.Employees = new Collection<Employee>(children);
            }
        }

        public string Name{ get; private set; }
        public int Age{ get; private set; }
        public Color BackGroundColor = Colors.White;
        public Color ForeGroundColor = Colors.Black;

        public Collection<ServiceIntentionRelation> Employees = new Collection<Employee>();
    }

I created a DataContext to all the stuff, this is used.

public class EmployeeDataContext
    {
        public EmployeeDataContext()
        {
            this.Fill();
        }

        public Collection<Employee> Employees = null; // I could use new Collection<Employee>(), does not matter (theoretically)

        private void Fill()
        {
            var e1 = new Employee("George", 34, null);
            var e2 = new Employee("Steve", 19, null);
            // e3, e4 and e5 is made the very same way

            var s6 = new Employee("Mike", 56, new List<Employee>(){e3,e4,e5});

            this.Relations = new Collection<ServiceIntentionRelation>() { e1, e2, e6 };
            // e6 has e3, e4, e5 as children.
        }
    }

Thanks for your answers!

Try defining the the hierarchical data template this way.

<local:MyHierarchicalDataTemplate x:Key="treeTemplate" ItemsSource="{Binding Employees}">           
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}" Margin="0,0,4,0"/>
            <TextBlock Width="40" Text="{Binding Age}" />  
        </StackPanel>
</local:MyHierarchicalDataTemplate>

This will set the header of your treeviewitem to be the information within the StackPanel and the ItemsSource of your treeviewitem to be Employees.

A treeviewitem's itemscontainer is another treeviewitem, so when an employee is encountered a treeview item is created using the same datatemplate. This is how the hierarchical structure is created.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM