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

前端 未结 3 1216
后悔当初
后悔当初 2021-02-06 17:05

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

相关标签:
3条回答
  • 2021-02-06 17:25

    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.

    0 讨论(0)
  • 2021-02-06 17:32

    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> 
    
    0 讨论(0)
  • 2021-02-06 17:34

    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.

    0 讨论(0)
提交回复
热议问题