If you want to be all MVVMy, you would derive your child VMs from a common base class:
public ChildViewModel1 : ChildViewModelBase (which is derived from ViewModelBase or whatever)
public ChildViewModel2 : ChildViewModelBase
then in your MainWindowVM, you would have:
public ObservableCollection<ChildViewModelBase> ChildViews
in your MainWindowVM, if you wanted to open a view, you'd new up a ChildViewModel1 for example and stick it in the list. Closing a view by removing it, etc.
The MainViewView.xaml's TabControl ItemsSource would bind to the ChildViews prop. You can have a Title property in ChildViewBase that specifies the tab text.
You wouldn't use a ViewLocator in this implementation because you are going the other way. You only new up the VMs.
You would map the VM back to a view by defining DataTemplates that say for a type ChildViewModel1, I want to instantiate ChildView1 or whatever.
That doesn't happen automatically, so you'd either derive from TabControl or use an attached property where you monitor the TabControl ItemSource collection and look up the DataTemplate for the type of VM and new up the view and set its DataContext to the content of the tab (the VM) and then the tab's content to the view.
Not really. Its mostly basic WPF concepts put together. Data templates, data binding, monitoring changes in a collection through INotifyCollectionChanged / OnItemsSourceChanged subscribing / unsubscribing to the collection changes.
As for doing the code that implements the add / remove tabs, you could do it via an attached property or deriving from the TabControl.
Concept is, if you get a new item in the collection, its going to be a ChildViewModelBase, it's going to be assigned to the tab content. So you'd do a GetType() on it and try to find a DataTemplate that is specified for that type, then you can create the child view automatically. You'd set that as the content and set the DataContext of the view as the VM.
I've used a separate 'controller' class for this kind of scenario.
Let the viewmodel know about this controller class and then let this 'controller' or 'loader' class decide which view needs to be loaded.
Been messing around with this all day and its not working for some reason. I know as you expand a node, you have to wait for the ItemContainerGenerator to do its thing, which is what I'm doing, but its only expanding one level for some reason:
internalvoid ExpandAll(TreeViewItem tvi)
for (int nIndex = 0; nIndex < tvi.Items.Count; nIndex++)
TreeViewItem tviCurrent = tvi.ItemContainerGenerator.ContainerFromIndex(nIndex) as TreeViewItem;
if ((object)tviCurrent != null)
if (tvi.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated)
EventHandler handler = null;
handler = new EventHandler(delegate
if (tvi.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
// ONLY GETS IN HERE ONCE tvi.ItemContainerGenerator.StatusChanged -= handler;
tvi.ItemContainerGenerator.StatusChanged += handler;
So I only get inside the EventHandler one time. It doesn't get in there for the child nodes. If I expand the child node manually, THEN the handler code is called.
Also tried the built in .Net ExpandSubTree and it has the same issue. Only expands one level down.
I used this article [^]as the basis of my treeview item, it binds the IsExpanded to a property and that drives the tree. I extended it somewhat to meet my needs but it was an excellent concept and worked very well.
Never underestimate the power of human stupidity
Yeah, I have support for binding the IsExpanded property to a property in the data object in my customized TreeView control, but... I dunno... just seems like a hokey requirement to require the user of my control to maintain item state. My custom TreeView control also has built in support for displaying checkboxes next to each item. I can see binding the checkbox to a property in the data object since that kind of seems like a legit requirement. If the user is using checkbox mode, he is going to want to know the checked state of each item. He isn't really going to care about whether a node is expanded or not. Now he *might* if he wants to save the tree state, so I definitely want to keep that as an option, but I was trying to avoid relying on that to make the treeview work in general.
Can someone point me to a decent tutorial on how to override a WPF TextBox? I tried Googling, but the answers are all over the board. not sure what I'm looking for. I just want to add various functionality, and I'm looking for a starting point