3

I am making a WPF application following MVVM. What I want in my application is that there is a View which contains some common buttons and text boxes and a TabControl. TabControl will basically host different UserControls. So for each UserControl I have a separate View and a ViewModel ready.

So structure of my application looks like this.

MainWindow.Xaml
    EntryView.Xaml
        Button1
        Button2
        TabControl
            UserControl1 (View)
            UserControl2 (View)
            UserControl3 (View)

Son in my EntryView I have the tab control. Now I need to bind this.

Here is what I have done.

EntryView.Xaml

<TabControl ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}">
    <TabControl.ContentTemplate>
        <DataTemplate DataType="{x:Type vm:UserControl1ViewModel}">
            <v:UserControl1View/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:UserControl2ViewModel}">
            <v:UserControl2View/>
        </DataTemplate>
    </TabControl.ContentTemplate>
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="Header"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

EntryViewModel.cs

private ObservableCollection<BaseViewModel> _tabs;
public ObservableCollection<BaseViewModel> Tabs
{
    get
    {
        if (_tabs == null)
        {
            _tabs = new ObservableCollection<BaseViewModel>();
            _tabs.Add(new UserControl1ViewModel());
            _tabs.Add(new UserControl2ViewModel());
        }
        return _tabs;
    }
}

But now when I run my application nothings happens. TabControl is empty. I put breakpoint inside Tabs in view model, but it didn't get hit. So question one is am I doing this right? If no then what should I do?

fhnaseer
  • 7,159
  • 16
  • 60
  • 112
  • You sure perform this: "EntryView.DataContext = new EntryViewModel()"? – Reza ArabQaeni Jun 12 '13 at 10:32
  • In Main window or other ways(binding) to fill DataContext property of EntryView. – Reza ArabQaeni Jun 12 '13 at 10:41
  • I have done that in MainWindow. I am able to see my buttons of EntryView. I can see TabControl as well. But there are no tabs present there. I have added tabs in my view model but I cannot see them when application runs. – fhnaseer Jun 12 '13 at 11:26
  • I suspect that you are leaving something out of your code / description that is the real culprit. If your getter for 'Tabs' isn't being hit, it is because the binding for it is never being evaluated. Are there any binding errors listed in your output window? – A.R. Jun 12 '13 at 12:12
  • @A.R. Ok, well I don't know. But now its working. I am still finding out what was the real CULPRIT. – fhnaseer Jun 12 '13 at 12:22

2 Answers2

5

For starters I don't know how it compiles on your machine as on my machine it gives me this error:

The property "ContentTemplate" can only be set once.

However when I move DataTemplates to TabControl.Resources it compiles and works fine:

<TabControl>
   <TabControl.Resources>
      <DataTemplate DataType="{x:Type vm:UserControl1ViewModel}">
         <v:UserControl1View/>
      </DataTemplate>
      <DataTemplate DataType="{x:Type vm:UserControl2ViewModel}">
         <v:UserControl2View/>
      </DataTemplate>
   </TabControl.Resources>
   <TabControl.ItemTemplate>
      <DataTemplate>
         <TextBlock Text="Header"/>
      </DataTemplate>
   </TabControl.ItemTemplate>
</TabControl>
dkozl
  • 32,814
  • 8
  • 87
  • 89
  • Your solution is working, but mine one is also working. I am still finding the real culprit. "The property "ContentTemplate" can only be set once." this may help me. – fhnaseer Jun 12 '13 at 12:43
0

The real culprit is simply that

<TabControl.ContentTemplate>

Takes only one DataTemplate element as content. That property cannot be set twice.

Instead giving a DataTemplate for each type in your TabControl's (or the window's) resources will do just fine.

Ideally it seems to me that you'd simply add the UserControlViews to your ItemsSource and the views can set their own DataContext to the ViewModels.

Benoit Dufresne
  • 318
  • 3
  • 9