简体   繁体   中英

WPF Iterate TreeView right after adding to collection

I have a TreeView. If it's relevant, i use MVVM and Caliburn Micro. I want that the selected node before the clearing will be selected after adding the node. I added DependencyProperty to the TreeView called TreeViewSelectedItemProperty for setting the SelectedItem property. see the code (NOTE: i simplified the code that would be easier to read):

In the ViewModel:

Nodes.Clear(); 
Nodes.Add(globalNode);
SelectedNode = node;

In the DependencyProperty file (TreeViewSelectedItemChanged method):

Collection<TreeViewItem> c=GetAllItemContainers(myTreeView);
foreach (var treeViewItem in c)
{
      if (treeViewItem.DataContext == beforeClearingSelectedNode)
      {
          treeViewItem.IsSelected = true;
          return;
      }
}

Where GetAllItemContainers defined like this:

private static Collection<TreeViewItem> GetAllItemContainers(ItemsControl itemsControl)
{
        Collection<TreeViewItem> allItems = new Collection<TreeViewItem>();
        for (int i = 0; i < itemsControl.Items.Count; i++)
        {
            // try to get the item Container  
            TreeViewItem childItemContainer =  itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
            // the item container maybe null if it is still not generated from the runtime  
            if (childItemContainer != null)
            {
                allItems.Add(childItemContainer);
                Collection<TreeViewItem> childItems = GetAllItemContainers(childItemContainer);
                foreach (TreeViewItem childItem in childItems)
                {
                    allItems.Add(childItem);
                }
            }
        }
        return allItems;
}

The problem is that although the tree has 4 nodes, the size of the collection c is 1. I tried to use Loaded event of TreeView but also there the size of the collection was 1 when invoking. The size of the collection is correct (4) only when opening the view (The dependency property method TreeViewSelectedItemChanged is invoked. i debugged it and saw that c.Count() is 4).

Any help will be appreciated.

Have you tried creating a ViewModel for your nodes?

public class NodeViewModel : PropertyChangedBase
{
    private bool isSelected;

    public NodeViewModel(string displayName)
    {
        this.DisplayName = displayName;
        this.Children = new ObservableCollection<NodeViewModel>();
    }

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

    public string DisplayName { get; private set; }

    public bool IsSelected
    {
        get { return this.isSelected; }
        set
        {
            if (value.Equals(this.isSelected))
            {
                return;
            }
            this.isSelected = value;
            this.NotifyOfPropertyChange(() => this.IsSelected);
            Console.WriteLine(value);
        }
    }
}

You can bind your TreeViewItem s to the ViewModels using a ItemContainerTemplate :

<TreeView ItemsSource="{Binding Tree}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected}" />
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding DisplayName}" />
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

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