I had to cope with the same issue and I did the MVVM way.
First, you want to create a property that will represent whether the item is expanded or not in your view-model (that's mainly where MVVM helps you out).
In your node's view-model simply add something like Boolean IsNodeExpanded { get; set; }
.
Warning: The above is just the interface! you must notify changes with INotifyPropertyChanged.PropertyChanged
, otherwise it will not work!
Next you want to hook it up to your view and this is very similar to what Andy here suggested; use styles. However his markup wasn't enough for me (one reason is that it didn't work).
What you actually want to do is place the style in the tree-view's ItemContainerStyle
.
<TreeView ...>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Path=IsNodeExpanded, Mode=TwoWay}" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
And this did work for me in my case.
Note 1: Save yourself a headache, and make sure the binding in the style above is a two-way binding as it is presented. I had a project some time ago when I had to re-do this, I forgot to make it a two-way, and even debugging didn't help.
Note 2: You should use MVVM for this function, I have tried to use code-behind for it because it seemed shorter (I'm lazy) and it turned out to be a long mess, and not just because it requires a recursive function, also because hidden items don't seem to exist until their parent is opened. It's not pleasant, and it may seem like a quick way to do it, but my experience made it much longer.