简体   繁体   中英

Why are tab headers displayed in the content area of tabs in a XAML TabControl?

I've got a TabControl whose ItemsSource is bound to an observable collection of views (UserControls) each which have as its root element a TabItem . However, when it is displayed, the Header text is in content of each TabItem, as if UserControl wrapper is causing conflicts:

替代文字

The TabControl is in SmartFormView.xaml:

<UserControl x:Class="TestApp.Views.SmartFormView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel
        Margin="10">
        <TextBlock Text="{Binding Title}"
            FontSize="18"/>
        <TextBlock Text="{Binding Description}"
            FontSize="12"/>

        <TabControl
            Margin="0 10 0 0"
            ItemsSource="{Binding SmartFormAreaViews}"/>
    </StackPanel>
</UserControl>

What do I have to change so that TabItems are displayed as TabItems inside the TabControl?

Here are the TabItem views called SmartFormAreaView.xaml:

<UserControl x:Class="TestApp.Views.SmartFormAreaView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <TabItem Header="This is the header">
        <StackPanel Margin="10">
            <TextBlock Text="this is the content"/>
        </StackPanel>
    </TabItem>
</UserControl>

And here is where I create and load each view into the ObservableCollection :

var areas = from area in xmlDoc.Descendants("area")
            select area;
foreach (var area in areas)
{
    SmartFormArea smartFormArea = new SmartFormArea();
    smartFormArea.IdCode = area.Attribute("idCode").Value;
    smartFormArea.Title = area.Attribute("title").Value;
    SmartFormAreaPresenter smartFormAreaPresenter = new SmartFormAreaPresenter(smartFormArea);
    SmartFormAreaViews.Add(smartFormAreaPresenter.View as SmartFormAreaView);
}

For any ItemsControl, if the items added to its Items collection (either directly or via ItemsSource) are not instance of that control's item container, then each item is wrapped in an instance of the item container. The item container is a class such as TabItem or ListBoxItem. The item container is normally a ContentControl or HeaderedContentControl, and your actual item is assigned to its Content property, so you can use templates etc to control how the content is presented. You can also style the item container itself using the ItemControl's ItemContainerStyle property.

In this particular case, you should bind ItemsSource to a list of SmartFormAreaPresenters. Then use something like this for the tab control:

<TabControl ItemsSource="{Binding SmartFormAreaPresenters}">
  <TabControl.ItemContainerStyle>
    <Style TargetType="{x:Type TabItem}">
      <Setter Property="Header" Value="{Binding HeaderText}" />
    </Style>
  </TabControl.ItemContainerStyle>

  <TabControl.ContentTemplate>
    <DataTemplate DataType="{x:Type local:SmartFormAreaPresenter}">
      <local:SmartFormAreaView />
    </DataTemplate>
  </TabControl.ContentTemplate>
</TabControl>

where HeaderText is a suitable property on your SmartFormAreaPresenter. You should also remove the TabItem from your SmartFormAreaView definition. The DataContext of each View will automatically be set to the appropriate Presenter.

See Dr. WPF's blog for an excellent discussion of various ItemsControl related topics.

The TabControl will accept your controls as its controls only if they can be cast to TabItem , not UserControl, or SmartFormAreaView, etc.

So you either fill regular TabItems with your visual tree, or you subclass TabItems , or you subclass the TabControl to override its IsItemItsOwnContainerOverride method, to accept your type as the container.

The method should look as follows:

protected override bool IsItemItsOwnContainerOverride(object item)
{
    return item is YourControlTypeHere || item is TabItem;
}

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