0

I've been trying to auto-populate my TabControl, and have been looking at this question, though it doesn't quite cover wrapped VMs and I can't figure it out.

My MainViewModel

public class MainActionViewModel : ViewModelBase
{
    private readonly IDialogService dialogService;

    public ObservableCollection<ViewVM> Views { get; set; }

    public MainActionViewModel(IDialogService dialogService)
    {
        this.dialogService = dialogService;

        ObservableCollection<ViewVM> views = new ObservableCollection<ViewVM>
        {
            new ViewVM{ ViewDisplay="Inspections", ViewType = typeof(InspectionsView), ViewModelType = typeof(InspectionsViewModel)},
            new ViewVM{ ViewDisplay="Defects", ViewType = typeof(SecurityView), ViewModelType = typeof(SecurityViewModel)},
            new ViewVM{ ViewDisplay="Planned Works", ViewType = typeof(SecurityView), ViewModelType = typeof(SecurityViewModel)},
            new ViewVM{ ViewDisplay="Security", ViewType = typeof(SecurityView), ViewModelType = typeof(SecurityViewModel)}
        };
        Views = views;
        RaisePropertyChanged("Views");
    }
}

My MainView

<Window x:Class="AptAction.MainAction"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:AptAction"
      mc:Ignorable="d" 
      d:DesignHeight="500" d:DesignWidth="700"
      Title="AptAction">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TabControl Grid.Row="1"  ItemsSource="{Binding Views}" SelectedIndex="0">
            <TabControl.Resources>
                <DataTemplate DataType="{x:Type local:InspectionsViewModel}">
                    <local:InspectionsView/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type local:SecurityViewModel}">
                    <local:SecurityView/>
                </DataTemplate>
            </TabControl.Resources>
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ViewDisplay}" />
                </DataTemplate>
            </TabControl.ItemTemplate>
        </TabControl>
        <TextBlock x:Name="UIMessage" Text="" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,0,8,0" Foreground="{StaticResource DarkBrightBrush}"/>
        <ContentControl x:Name="Holder" Grid.Row="2" />
    </Grid>
</Window>

The content of the TabItems are display the description LibsView.ViewVM, what do I need to change/add to get it to display the actual view properly?

enter image description here

Hank
  • 2,456
  • 3
  • 35
  • 83
  • 1
    Try removing ` `. I think it's overriding the behavior you defined eariler that displays the view according to the model type. – TomerAgmon1 Feb 22 '18 at 09:36
  • 3
    You're doing this the hard(est) way. Your view models are of different types. Put them in an ObservableCollection and bind that to the Items property of the tab control. Then you can use the view model's type to select the correct DataTemplate. To do what you're trying to do, you'd have to create a custom DataTemplateSelector like in my answer here https://stackoverflow.com/questions/37328616/mvvm-binding-views-to-tabcontrolitems-views-dont-display/37329640#37329640 it's a huge pain in the ass. Don't bother. –  Feb 22 '18 at 15:23

1 Answers1

1

You should add instances of InspectionsViewModel and SecurityViewModel to your ObservableCollection instead of adding ViewVM objects to it.

Create a common base class (or interface) that both InspectionsViewModel and SecurityViewModel inherit from and change the type of your collection to ObservableCollection<BaseType>:

public MainActionViewModel()
{
    ObservableCollection<BaseType> views = new ObservableCollection<BaseType>
            {
                new InspectionsViewModel(),
                new SecurityViewModel()
            };
    Views = views;
}

You could also use an ObservableCollection<object> since both your classes already implicitly inherit from object.

mm8
  • 163,881
  • 10
  • 57
  • 88