tags:

views:

122

answers:

1

This code example shows how to get the position of the scrollbar in a ScrollViewer (with ScrollToVerticalOffset) so that e.g. you can reset the scrollbar to this position if you need to recreate it.

Is there any way to do this for a TreeView control, i.e. get a collection of node indexes which the user has expanded?

+3  A: 

Hi Edward,

The easiest way to do this is to bind TreeViewItem.IsExpanded property to the ViewModel, and then go through model and calculate.

I wrote an example for you. It calculates number of expanded nodes, but you can do whatever you want with expanded guys...

C#:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace WpfApplication1
{
  public partial class TestBrowser : Window
  {
    private TreeViewItemViewModel[] _items;

    public TestBrowser()
    {
      InitializeComponent();

        var item1 = new TreeViewItemViewModel();
        var item2 = new TreeViewItemViewModel();
        var item3 = new TreeViewItemViewModel();

        item3.Children.Add(new TreeViewItemViewModel());
        item3.Children.Add(new TreeViewItemViewModel());
        var child3 = new TreeViewItemViewModel();
        child3.Children.Add(new TreeViewItemViewModel());
        item3.Children.Add(child3);

        _items = new[] {item1, item2, item3};
        tv.DataContext = _items;
    }

        private void CalculateExpandedClick(object sender, RoutedEventArgs e)
        {
            var expanded = 0;
            foreach (TreeViewItemViewModel item in _items)
            {
                expanded += GetNumberOfExpanded(item);
            }
            ExpandedNumber.Text = expanded.ToString();
        }

    private int GetNumberOfExpanded(TreeViewItemViewModel model)
    {
        var expandedCount = 0;
        if (model.IsExpanded)
        {
            expandedCount += 1;
            foreach (TreeViewItemViewModel child in model.Children)
            {
                expandedCount += GetNumberOfExpanded(child);
            }
        }
        return expandedCount;
    }
  }

    /// <summary>
    /// Single tree view item view model.
    /// </summary>
    public class TreeViewItemViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<TreeViewItemViewModel> Children
        {
            get; private set;
        }

        private bool _isExpanded;
        private string _text;

        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                _isExpanded = value;
                OnPropertyChanged("IsExpanded");
            }
        }

        public string Text
        {
            get { return _text; }
            set
            {
                _text = value;
                OnPropertyChanged("Text");
            }
        }

        public TreeViewItemViewModel()
        {
            Children = new ObservableCollection<TreeViewItemViewModel>();
            Text = DateTime.Now.ToLongTimeString(); // Just fake data.
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string name)
        {
            var changed = PropertyChanged;
            if (changed != null)
            {
                changed(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

XAML:

<Window x:Class="WpfApplication1.TestBrowser"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Expanded Test"
        Height="300"
        Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <TreeView x:Name="tv"
              ItemsSource="{Binding}">
            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
                </Style>
            </TreeView.ItemContainerStyle>
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Children}">
                    <TextBlock Text="{Binding Text}" />
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>

        <StackPanel Grid.Column="1">
            <Button Content="Get number of expanded items" 
                            Click="CalculateExpandedClick"/>
            <TextBlock x:Name="ExpandedNumber" />
        </StackPanel>
    </Grid>
</Window>

Hope this helps.

Anvaka