silverlighttreeviewtreeviewitemitemcontainergenerator

Getting the TreeViewItem on newly created items


There has to be a better way then the following for getting "childItem"

    TaskItem task = (sender as Canvas).DataContext as TaskItem;
    TaskItem child = Tasks.CreateTask("New task", task);
    TreeViewItem item = treeView.ItemContainerGenerator.ContainerFromItem(task) as TreeViewItem;            

    item.UpdateLayout();
    TreeViewItem childItem = null;
    foreach (var i in item.GetDescendantContainers())
    {
        if (i.GetItem() == child)
            childItem = i;
    }

For some reason item.ItemGenerator.ContainerFromItem(child) does not work (must be due to the item having just been created)


Solution

  • Item container generation is asynchronous, so you cannot assume the container will exist as soon as the item was added. You will need to attach a handler to the ItemContainerGenerator.StatusChanged event so your code will be informed when container generation is complete.

    Dr. WPF's blog entry "ItemsControl: 'G' is for Generator" has a good description of the problem and provides an example of using StatusChanged:

    private void AddScooby()
    {
        _scooby = new Character("Scooby Doo");
        Characters.Add(_scooby);
        CharacterListBox.ItemContainerGenerator.StatusChanged
            += OnStatusChanged;
    }
    
    private void OnStatusChanged(object sender, EventArgs e)
    {
        if (CharacterListBox.ItemContainerGenerator.Status
            == GeneratorStatus.ContainersGenerated)
        {
            CharacterListBox.ItemContainerGenerator.StatusChanged
                -= OnStatusChanged;
            ListBoxItem lbi = CharacterListBox.ItemContainerGenerator
                .ContainerFromItem(_scooby) as ListBoxItem;
            if (lbi != null)
            {
                lbi.IsSelected = true;
            }
        }
    }