I have created a tab control and Created the tabItems dynamically, but i dont know how to add controls into the tabItems using MVVM. Could any one help me
There are a few ways to programmatically add Tab Items in WPF
and I am going to show you a simple example on how I deal with this in my application.
First I host a collection of the ViewModels
for the TabItems
(or Workspaces
as I refer to them) in my MainWindowViewModel.cs
:
private ObservableCollection<WorkspaceViewModel> _workspaces;
public ObservableCollection<WorkspaceViewModel> Workspaces
{
get
{
if (_workspaces == null)
{
_workspaces = new ObservableCollection<WorkspaceViewModel>();
}
return _workspaces;
}
}
Next I add a reference to the various controls in my MainWindow.xaml
. This is important as we want to make sure that whenever the collection contains a ViewModel
that it displays the appropriate View
for that Model.
<Window.Resources>
<DataTemplate DataType="{x:Type vm:MyUserControlViewModel}">
<vw:MyUserControlView/>
</DataTemplate>
</Window.Resources>
If you have multiple types of UserControls you simply add them all here like this:
<Window.Resources>
<DataTemplate DataType="{x:Type vm:FirstUserControlViewModel}">
<vw:FirstUserControlView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SecondUserControlViewModel}">
<vw:SecondUserControlView/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:ThirdUserControlViewModel}">
<vw:ThirdUserControlView/>
</DataTemplate>
</Window.Resources>
Next we add the TabControl
and bind it to our Workspace
Collection.
<TabControl ItemsSource="{Binding Workspaces}"/>
Then I simply add my ViewModels
to the Collection to have them show up in the TabControl
.
Workspaces.Add(new FirstUserControlViewModel());
Workspaces.Add(new SecondUserControlViewModel());
Workspaces.Add(new ThirdUserControlViewModel());
My WorkspaceViewModel
that I base the TabItem
collection of is very simple and looks something like this:
public abstract class WorkspaceViewModel : BaseViewModel
{
public String HeaderText { get; set; }
public override string ToString()
{
return HeaderText;
}
}
Adding a TabItem:
To create a TabItem
you simply create a UserControl
and ViewModel
like you normally would using WPF and the MVVM pattern.
namespace MyApplication.ViewModel
{
public class FirstUserControlViewModel : WorkspaceViewModel
{
public FirstUserControlViewModel ()
{
base.HeaderText = "My First Tab";
}
}
}
Next you need to bind a View
to your new ViewModel
.
<DataTemplate DataType="{x:Type vm:FirstUserControlViewModel }">
<vw:FirstUserControlView/>
</DataTemplate>
Then you create an instance of the ViewModel
and add it to the collection in your MainWindowViewModel
.
FirstUserControlViewModel firstvm = new FirstUserControlViewModel();
Workspaces.Add(firstvm);
And now the TabItem
should show up in your TabControl
.
Loading TabItems dynamically using Extensions:
In some cases you might even need to load TabItems
from plugins dynamically without the host application first knowing about the TabItem
. In these cases you need to have the plugin register the View
and ViewModel
with the application domain.
This is very easy to do, and actually something I do for one of my MEF
based projects. I have an post here, with some additional details as well.
All you need to do is add a Resource Dictionary
to your plugin/extension and make sure that the host application loads it once the plugin has been imported.
To show you a fast example I would have a View.xaml
in my extensions:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vw="clr-namespace:MyExtension.Test">
<DataTemplate DataType="{x:Type vw:TestViewModel}">
<vw:TestView/>
</DataTemplate>
</ResourceDictionary>
I then expose the ResourceDictinary using MEF to the Host like this:
private ResourceDictionary _viewDictionary = new ResourceDictionary();
public ResourceDictionary Dict
{
get
{
return _viewDictionary;
}
}
_viewDictionary.Source =
new Uri("/MyExtension.Test;component/View.xaml",
UriKind.RelativeOrAbsolute);
Last you use Application.Current.Resources.MergedDictionaries.Add
to load the View.xaml into the host.
You Dont have to add controls you just have to specify the UserControl.
TabControl has two properties ItemTemplate
&& Content Template
ItemTemplate is for how the Tab
will look where as
ContentTemplate is how the Tab Content will Look... so...
<TabControl Grid.Row="1"
ItemsSource="{Binding Path=TabList}"
SelectedItem="{Binding Path=SelectedTab,
Mode=TwoWay}"
<!--This is How tab will look--> >
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="20"
Height="20"
Margin="0,0,2,0"
Source="Images\TreeView\yourFavImg.png" />
<TextBlock Margin="0,4,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding Path=TabText}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<!--This will be the content for the tab control-->
<TabControl.ContentTemplate>
<DataTemplate>
<!--This User Control will contain the controls you like-->
<ViewLayer:YourFavUserControl />
</DataTemplate>
</TabControl.ContentTemplate>
you dont have to add controls if you use mvvm. you just have to create datatemplates for your viewmodel objects you wanna display.
all you need is a contentcontrol/presenter which is bind to your viewmodel and the datatemplate will show what you want.