I have a main window with a tab control containing 2 tabItem
s:
I currently
I use a framework such as Prism, that allows you to define regions and use the RegionManager
. You can then define a ContentControl
as the 'ui' for the TabItem
Then you can use the RegionManager.RequestNavigate
to populate a named region with a particular view (and our views import a viewmodel and set their datacontext).
For people finding this page with the same question, I found a video on YouTube: WPF MVVM - Working with tab controls and tab content, by a guy from DCOM Engineering, LLC.
It gives a very good explanation of "how to bind a different ViewModel
to each TabItem
", step by step, with downloadable code.
"Learn how to create, open, and close tabs effectively using the MVVM pattern with WPF. Facilitates unit testing."
class MainViewModel
{
ObservableCollection<object> _children;
public MainViewModel()
{
_children = new ObservableCollection<object>();
_children.Add(new Tab1ViewModel());
_children.Add(new Tab2ViewModel());
}
public ObservableCollection<object> Children { get { return _children; } }
}
Now in XAML bind the Children to ItemsSource. It will generate each Tab for every viewmodel we have added into the observable collection
<TabControl ItemsSource="{Binding Children}"/>
No sure why the selected answer is suggesting to use ObservableCollection and create a collection of tabs and then reference them by index.
I find it more clean to do it this way:
MainViewModel tab1= ConfigViewModel Tab2 = UserProfileViewModel
in MainViewModel:
private ConfigViewModels _configVM;
public ConfigViewModels ConfigVM { get { return _configVM; } }
private UserProfileViewModel _userProfileVM;
public UserProfileViewModel UserProfileVM { get { return _userProfileVM; } }
public MainViewModel(){
_configVM = new ConfigViewModels();
_userProfileVM = new UserProfileViewModel ();
}
In th XAML file:
<TabControl>
<TabItem DataContext="{Binding ConfigVM }" >
<TabItem DataContext="{Binding UserProfileVM }" >
I'm not sure I understand the benefit of doing this through an observable collection.
You can indeed add the view models for your tabs to a main view model. You can then bind to the child view models in the XAML for your tabs.
Say that you have three viewmodels: MainViewModel
, Tab1ViewModel
, and Tab2ViewModel
. On your MainViewModel
you keep a collection of your tab viewmodels:
class MainViewModel
{
ObservableCollection<object> _children;
public MainViewModel()
{
_children = new ObservableCollection<object>();
_children.Add(new Tab1ViewModel());
_children.Add(new Tab2ViewModel());
}
public ObservableCollection<object> Children { get { return _children; } }
}
After setting the DataContext
of your main window to your MainViewModel
you can bind the DataContext
of your tabs by referencing the Children
property:
<TabControl>
<TabItem DataContext="{Binding Children[0]}" x:Name="Tab1" Header="Tab1" >
<!-- Tab content -->
</TabItem>
<TabItem DataContext="{Binding Children[1]}" x:Name="Tab2" Header="Tab2" >
<!-- Tab content -->
</TabItem>
</TabControl>