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.