locked
Preselecting a Treevieitem on usercontrol load RRS feed

  • Question

  •  

    Hi,

     

    I have a field selection wizard usercontrol in which I have a Treeview which gets populated using some Webservice. The user selects an item from the treeview and closes the wizard. Next time when the user launches this wizard, the treeview item need to be preselected on usercontrol load or any other appropriate event in this case. I bind the itemsource of the treeview in the Usercontrol loaded event. I invoke the preselection method as the last statement in the Loaded event.  In the preselection method, I tried itereating through the tree for finding the item recursively, but this did not yield any result. In my node search method I retreive the child TreeviewItem by calling the current node's

    ItemContainerGenerator.ContainerFromItem(item) method. But this yields null when invoked at this point of time. To verify, I put another button in the usercontrol just for invoking the preselection logic to see if it works , then it worked just fine.

     

    My thinking regarding the issue is that the Treeview items are not yet generated when I invoke the ItemContainerGenerator.ContainerFromItem(item) during the usercontrol Loaded event. I did not not find any help on this anywhere. Iam not sure if If Iam trying to do the right thing here. Anybody has any clue what I need to do to get this to work??

     

    Thanks in Advance

    Siva

    Friday, February 1, 2008 6:17 PM

Answers

  • This is because the TreeViewItem is not intialized, so we are unable to get its container. The following example shows how to do this. I hope this helps.

     

    Code Snippet

    namespace ForumProjects

    {

        public partial class MainWindow : Window

        {

            public MainWindow()

            {

                this.Persons = new List<Person>()

                {

                    new Person(){Name="A1"},

                    new Person(){Name="A2"},

                };

     

                this.Persons[0].Children.Add(new Person() { Name = "B1" });

                this.Persons[0].Children.Add(new Person() { Name = "B2" });

                this.Persons[1].Children.Add(new Person() { Name = "B3" });

                this.Persons[1].Children.Add(new Person() { Name = "B4" });

     

                this.Persons[0].Children[0].Children.Add(new Person() { Name = "C1" });

                this.Persons[0].Children[0].Children.Add(new Person() { Name = "C2" });

                this.Persons[0].Children[1].Children.Add(new Person() { Name = "C3" });

                this.Persons[0].Children[1].Children.Add(new Person() { Name = "C4" });

                this.Persons[1].Children[0].Children.Add(new Person() { Name = "C5" });

                this.Persons[1].Children[0].Children.Add(new Person() { Name = "C6" });

                this.Persons[1].Children[1].Children.Add(new Person() { Name = "C7" });

                this.Persons[1].Children[1].Children.Add(new Person() { Name = "C8" });

     

                this.toSelectPerson = this.Persons[1].Children[0].Children[1];

     

                InitializeComponent();

            }

     

            public List<Person> Persons { get; private set; }

     

            private Person toSelectPerson;

            private LinkedList<Person> linkedPersons;

     

            private void TreeView_Loaded(object sender, RoutedEventArgs e)

            {

                this.linkedPersons = new LinkedList<Person>();

                this.linkedPersons.AddFirst(this.toSelectPerson);

                FillLinkedPersons(this.toSelectPerson.Parent);

                ExpandAndSelect(this.linkedPersons.First, this.PersonList.ItemContainerGenerator);

            }

     

            private void FillLinkedPersons(Person person)

            {

                if (person != null)

                {

                    this.linkedPersons.AddBefore(this.linkedPersons.First, person);

                    FillLinkedPersons(person.Parent);

                }

            }

     

            private void ExpandAndSelect(LinkedListNode<Person> node, ItemContainerGenerator generator)

            {

                if (node != null)

                {

                    TreeViewItem item = (TreeViewItem)generator.ContainerFromItem(node.Value);

     

                    if (node.Value == this.toSelectPerson)

                    {

                        item.IsSelected = true;

                        return;

                    }

     

                    item.ItemContainerGenerator.StatusChanged += delegate

                    {

                        if (item.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

                        {

                            ExpandAndSelect(node.Next, item.ItemContainerGenerator);

                        }

                    };

     

                    item.IsExpanded = true;

                }

            }

        }

     

        public class Person

        {

            public Person()

            {

                this.Children = new ObservableCollection<Person>();

                this.Children.CollectionChanged += Children_CollectionChanged;

            }

     

            public string Name { get; set; }

            public Person Parent { get; private set; }

            public ObservableCollection<Person> Children { get; private set; }

     

            private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

            {

                foreach (Person child in e.NewItems)

                    child.Parent = this;

            }

        }

    }

     

    <Window

       x:Class="ForumProjects.MainWindow"

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

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

       xmlns:local="clr-namespace:ForumProjects"

       x:Name="Window" Title="MainWindow" Height="800" Width="600">

        <Window.Resources>

            <HierarchicalDataTemplate DataType="{x:Type local:Person}"

                                    ItemsSource="{Binding Children}">

                <TextBlock Text="{Binding Name}"/>

            </HierarchicalDataTemplate>

        </Window.Resources>

        <TreeView x:Name="PersonList" ItemsSource="{Binding ElementName=Window, Path=Persons}"

                Loaded="TreeView_Loaded"/>

    </Window>

     

     

    Best Regards,

    Wei Zhou

    Monday, February 4, 2008 8:15 AM

All replies

  • This is because the TreeViewItem is not intialized, so we are unable to get its container. The following example shows how to do this. I hope this helps.

     

    Code Snippet

    namespace ForumProjects

    {

        public partial class MainWindow : Window

        {

            public MainWindow()

            {

                this.Persons = new List<Person>()

                {

                    new Person(){Name="A1"},

                    new Person(){Name="A2"},

                };

     

                this.Persons[0].Children.Add(new Person() { Name = "B1" });

                this.Persons[0].Children.Add(new Person() { Name = "B2" });

                this.Persons[1].Children.Add(new Person() { Name = "B3" });

                this.Persons[1].Children.Add(new Person() { Name = "B4" });

     

                this.Persons[0].Children[0].Children.Add(new Person() { Name = "C1" });

                this.Persons[0].Children[0].Children.Add(new Person() { Name = "C2" });

                this.Persons[0].Children[1].Children.Add(new Person() { Name = "C3" });

                this.Persons[0].Children[1].Children.Add(new Person() { Name = "C4" });

                this.Persons[1].Children[0].Children.Add(new Person() { Name = "C5" });

                this.Persons[1].Children[0].Children.Add(new Person() { Name = "C6" });

                this.Persons[1].Children[1].Children.Add(new Person() { Name = "C7" });

                this.Persons[1].Children[1].Children.Add(new Person() { Name = "C8" });

     

                this.toSelectPerson = this.Persons[1].Children[0].Children[1];

     

                InitializeComponent();

            }

     

            public List<Person> Persons { get; private set; }

     

            private Person toSelectPerson;

            private LinkedList<Person> linkedPersons;

     

            private void TreeView_Loaded(object sender, RoutedEventArgs e)

            {

                this.linkedPersons = new LinkedList<Person>();

                this.linkedPersons.AddFirst(this.toSelectPerson);

                FillLinkedPersons(this.toSelectPerson.Parent);

                ExpandAndSelect(this.linkedPersons.First, this.PersonList.ItemContainerGenerator);

            }

     

            private void FillLinkedPersons(Person person)

            {

                if (person != null)

                {

                    this.linkedPersons.AddBefore(this.linkedPersons.First, person);

                    FillLinkedPersons(person.Parent);

                }

            }

     

            private void ExpandAndSelect(LinkedListNode<Person> node, ItemContainerGenerator generator)

            {

                if (node != null)

                {

                    TreeViewItem item = (TreeViewItem)generator.ContainerFromItem(node.Value);

     

                    if (node.Value == this.toSelectPerson)

                    {

                        item.IsSelected = true;

                        return;

                    }

     

                    item.ItemContainerGenerator.StatusChanged += delegate

                    {

                        if (item.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)

                        {

                            ExpandAndSelect(node.Next, item.ItemContainerGenerator);

                        }

                    };

     

                    item.IsExpanded = true;

                }

            }

        }

     

        public class Person

        {

            public Person()

            {

                this.Children = new ObservableCollection<Person>();

                this.Children.CollectionChanged += Children_CollectionChanged;

            }

     

            public string Name { get; set; }

            public Person Parent { get; private set; }

            public ObservableCollection<Person> Children { get; private set; }

     

            private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

            {

                foreach (Person child in e.NewItems)

                    child.Parent = this;

            }

        }

    }

     

    <Window

       x:Class="ForumProjects.MainWindow"

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

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

       xmlns:local="clr-namespace:ForumProjects"

       x:Name="Window" Title="MainWindow" Height="800" Width="600">

        <Window.Resources>

            <HierarchicalDataTemplate DataType="{x:Type local:Person}"

                                    ItemsSource="{Binding Children}">

                <TextBlock Text="{Binding Name}"/>

            </HierarchicalDataTemplate>

        </Window.Resources>

        <TreeView x:Name="PersonList" ItemsSource="{Binding ElementName=Window, Path=Persons}"

                Loaded="TreeView_Loaded"/>

    </Window>

     

     

    Best Regards,

    Wei Zhou

    Monday, February 4, 2008 8:15 AM
  • Hi Wei,

     

    Sorry for a late response to this post. Your solution solved the issue. I could try this out today only. I had to slightly modify the code for my need but the results have come out really good.

     

    Many thanks

    Siva

    Thursday, February 14, 2008 8:26 PM