Ok. Delete all your code and start all over.
If you're working with WPF, you really need to leave behind all the archaic practices from dinosaur technologies (such as winforms) and understand and embrace The WPF Mentality.
In WPF, You don't "select a TreeViewItem" programatically, simply because UI is Not Data.
The UI is not responsible for keeping track of the selection state of your Data items, which are displayed in a TreeView, or any other UI element.
Instead, you create a proper DataModel and a ViewModel
to hold the data and the application logic, respectively.
There is a very interesting article by Josh Smith explaining how to deal with a TreeView in WPF, the right way.
Basically something like this:
<Window x:Class="MiscSamples.MVVMTreeViewSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVMTreeViewSample" Height="300" Width="300">
<DockPanel>
<Button Content="Select All" Click="SelectAll" DockPanel.Dock="Top"/>
<Button Content="Select None" Click="SelectNone" DockPanel.Dock="Top"/>
<TreeView ItemsSource="{Binding}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding DisplayName}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>
</Window>
Code Behind:
public partial class MVVMTreeViewSample : Window
{
private ObservableCollection<HierarchicalData> Data;
public MVVMTreeViewSample()
{
InitializeComponent();
DataContext = Data = CreateData();
}
private void Select(IEnumerable<HierarchicalData> items, bool isselected)
{
while (items.Any())
{
items.ToList().ForEach(x => x.IsSelected = isselected);
items = items.SelectMany(x => x.Children);
}
}
private void SelectAll(object sender, RoutedEventArgs e)
{
Select(Data, true);
}
private void SelectNone(object sender, RoutedEventArgs e)
{
Select(Data, false);
}
private ObservableCollection<HierarchicalData> CreateData()
{
return new ObservableCollection<HierarchicalData>
{
//... Dummy Data here
}
}
}
Data Item:
public class HierarchicalData : System.ComponentModel.INotifyPropertyChanged
{
public string DisplayName { get; set; }
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
public ObservableCollection<HierarchicalData> Children { get; private set; }
public HierarchicalData()
{
Children = new ObservableCollection<HierarchicalData>();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Result:

- See how there is NOT a single line of code that manipulates ANY UI element. Everything is done via DataBinding to Simple, Simple Properties and INotifyPropertyChanged. That's how you program in WPF. No need for complicated
VisualTreeHelper.Whatever()
stuff, no need for complicated manipulations which incur in all sorts of issues due to UI virtualization or the like.
- In the
SelectAll()
and SelectNone()
methods, I'm just iterating thru Data Items
rather than UI elements, and setting their values accordingly. WPF then updates the UI via the DataBinding engine.
- See how there is no need to cast anything to anything, and how I'm working with my own simple classes rather than having to deal with the complex, arcane WPF Object Model.
- forget winforms. it'a useless dinosaur that doesn't support anything.
- WPF Rocks. Just copy and paste my code in a
File -> New Project -> WPF Application
and see the results for yourself. Notice that you will need to add items to the collection in the CreateData()
method.
- Let me know if you need further help.