简体   繁体   中英

How to add controls in the tab item programmatically in wpf with MVVM

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...

Xaml for the above

            <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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM