I am witting a new WPF application using C# with the help of Prism 6. and the MVVM design pattern.
I have a main windows with a Top
, Right
, and a Center
region. On the top region I have a toolbar, when a user clicks "Show Message" button, I show a view called "Message" in the center region. I am able to do that using RegionManager.RequestNavigate
method to show the "Message" view which is working fine.
However, my "Message" view have multiple tabs. When the user clicks on the TabControlItems, I want to be able to show different views in the tab-Content.
Here is how my Message
view look like. The idea here is to have a collection of ViewModels
, and display the tabs according to the collection.
<TabControl ItemsSource="{Binding ViewModelCollection}"
Background="Transparent">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<prism:InvokeCommandAction Command="{Binding TabSelectionChangedCommand}"
CommandParameter="{Binding ViewName}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabTitle}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl prism:RegionManager.RegionName="{x:Static foundation:RegionNames.TabContentRegionName}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Then in my MessageViewModel
I have the following code
public class MessageViewModel : BindableBase
{
public ObservableCollection<TabBasedNavigationAwareViewModel> ViewModelCollection { get; set; }
public DelegateCommand<string> ChangeTabContent { get; set; }
public MessageViewModel(IUnitOfWork unitOfWork, IPassportManager passportManager, ICoreRegionManager regionManager, IUnityContainer container)
: base(unitOfWork, passportManager, regionManager)
{
ViewModelCollection = new ObservableCollection<TabBasedNavigationAwareViewModel>();
ViewModelCollection.Add(container.Resolve<FirstViewModel>());
ViewModelCollection.Add(container.Resolve<SecondViewModel>());
ChangeTabContent = new DelegateCommand<string>(HandleChangeContent, CanChangeContent);
}
protected bool CanChangeContent(string viewName)
{
return true;
}
protected void HandleChangeContent(string viewName)
{
IRegion region = RegionManager.Regions[RegionNames.TabContentRegionName];
region.RequestNavigate(new Uri("Modules.Messages.Views." + viewName, UriKind.Relative));
}
public override void OnNavigatedTo(NavigationContext navigationContext)
{
ChangeTabContent.Execute("FirstView");
}
}
The problem is when the application starts I get an error
The region manager does not contain the TabContent region.
I clearly understand the error and why it is happening. But not sure how to solve it. May be Regions is the wrong way to do when using tab-controls inside a main region. I also tried to call the following code from the MessageViewModel
constructor RegionManager.RegisterViewWithRegion(RegionNames.TabContentRegionName, typeof(MessageView));
What is the correct way to manage/display the correct view when the user click on the tabs?
Please note that I am using Fody.PropertyChanged package so it automatically notify when the property changed.
UPDATED
I tried to remove regions from view, now I get the tabs and the content screen is showing the FirstViewModel
full name instead of the corresponding view.
Here is my code without regions
public class MessageViewModel : BindableBase
{
public ObservableCollection<TabBasedNavigationAwareViewModel> ViewModelCollection { get; set; }
public MessageViewModel(IUnitOfWork unitOfWork, IPassportManager passportManager, ICoreRegionManager regionManager, IUnityContainer container)
: base(unitOfWork, passportManager, regionManager)
{
ViewModelCollection = new ObservableCollection<TabBasedNavigationAwareViewModel>();
ViewModelCollection.Add(container.Resolve<FirstViewModel>());
ViewModelCollection.Add(container.Resolve<SecondViewModel>());
}
}
Here is the view
<TabControl ItemsSource="{Binding ViewModelCollection}"
Background="Transparent">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding TabTitle}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>