0

I hope this is an easy question. (Been coding for years, but limited WPF experience.) I have a simple tab control.

<TabControl Name="TabControl">

That contains three tabs:

<TabItem Name ="View" Header="View">
   stuff here to view data
</TabItem>

<TabItem Name ="Add" Header="Add">
   a form to add data
</TabItem>

<TabItem Name ="Edit" Header="Edit">
   the same form to edit data
</TabItem>

Since I want Add/Edit to share the same controls I created a ContentTemplate per this answer.

<TabControl.ContentTemplate>
   <DataTemplate>
      stuff in here
   </DataTemplate>
</TabControl.ContentTemplate>

However, ALL my tabs share the DataTemplate. How to I hide/exclude the View tab from sharing these controls?

thatguy
  • 21,059
  • 6
  • 30
  • 40
Jeff
  • 8,020
  • 34
  • 99
  • 157

1 Answers1

1

Usually, you have a distinct view model type for each type of data that you want to display in an ItemsControl. Each of these view models would be displayed using a DataTemplate that defines their appearance, e.g.:

  • The View tab would have a view model of type ViewData
  • The Add and Edit tabs would have a view model of type ItemData

You would create data templates for each of these view model or data types for your TabControl.

<TabControl Name="TabControl" ItemsSource="{Binding MyItems}">
   <TabControl.Resources>
      <DataTemplate DataType="{x:Type local:ViewData}">
         <!--...your "View" tab controls.-->
      </DataTemplate>
      <DataTemplate DataType="{x:Type local:ItemData}">
         <!--...your "Add" and "Edit" tab controls.-->
      </DataTemplate>
   </TabControl.Resources>
</TabControl>

By only specifying a DataType the templates will automatically be applied to the corresponding item types in ItemsSource. This also works, if you add TabItems manually and set the data items as content, e.g.:

<TabItem Name ="View" Header="View">
   <MyTreeFolder:ViewData/>
</TabItem>

As an alternative to the implicit data templates, you can create a custom DataTemplateSelector and override SelectTemplate. This way, you can select data templates not only depending on the data type, but also individual properties, fields, methods or attributes, whatever you need.

public class TabControlDataTemplateSelector : DataTemplateSelector
{
   public override DataTemplate SelectTemplate(object item, DependencyObject container)
   {
      if (item == null || !(container is FrameworkElement frameworkElement))
         return null;

      if (item is ViewData)
         return (DataTemplate)frameworkElement.FindResource("ViewDataTemplate");

      if (item is ItemData)
         return (DataTemplate)frameworkElement.FindResource("ItemDataTemplate");

      return null;
   }
}

In XAML, you would create data templates with a key and add the data template selector.

<TabControl Name="TabControl">
   <TabControl.Resources>
      <DataTemplate x:Key="ViewDataTemplate" DataType="{x:Type local:ViewData}">
         <!--...your "View" tab controls.-->
      </DataTemplate>
      <DataTemplate x:Key="ItemDataTemplate" DataType="{x:Type local:ItemData}">
         <!--...your "Add" and "Edit" tab controls.-->
      </DataTemplate>
   </TabControl.Resources>
   <TabControl.ContentTemplateSelector>
      <local:TabControlDataTemplateSelector/>
   </TabControl.ContentTemplateSelector>
</TabControl>

Again this works both for an ItemsSource and manually added data items in a TabItem.

thatguy
  • 21,059
  • 6
  • 30
  • 40