简体   繁体   English

为什么选项卡标题显示在XAML TabControl的选项卡的内容区域中?

[英]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 . 我有一个TabControl,其ItemsSource绑定到一个可观察的视图集合 (UserControls),每个视图都有一个TabItem作为其根元素。 However, when it is displayed, the Header text is in content of each TabItem, as if UserControl wrapper is causing conflicts: 但是,当它显示时, Header文本位于每个TabItem的内容中,就像UserControl包装器导致冲突一样:

替代文字

The TabControl is in SmartFormView.xaml: TabControl在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? 我需要更改哪些TabItems在TabControl中显示为TabItems?

Here are the TabItem views called SmartFormAreaView.xaml: 以下是名为SmartFormAreaView.xaml的TabItem视图

<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 : 这里我创建并将每个视图加载到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. 对于任何ItemsControl,如果添加到其Items集合中的项目(直接或通过ItemsSource)不是该控件的项容器的实例,则每个项目都包含在项目容器的实例中。 The item container is a class such as TabItem or ListBoxItem. item容器是一个类,如TabItem或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. 项容器通常是ContentControl或HeaderedContentControl,并且您的实际项目已分配给其Content属性,因此您可以使用模板等来控制内容的呈现方式。 You can also style the item container itself using the ItemControl's ItemContainerStyle property. 您还可以使用ItemControl的ItemContainerStyle属性设置项容器本身的样式。

In this particular case, you should bind ItemsSource to a list of SmartFormAreaPresenters. 在这种特殊情况下,您应该将ItemsSource绑定到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. 其中HeaderText是SmartFormAreaPresenter上的合适属性。 You should also remove the TabItem from your SmartFormAreaView definition. 您还应该从SmartFormAreaView定义中删除TabItem。 The DataContext of each View will automatically be set to the appropriate Presenter. 每个View的DataContext将自动设置为适当的Presenter。

See Dr. WPF's blog for an excellent discussion of various ItemsControl related topics. 有关各种ItemsControl相关主题的精彩讨论,请参阅WPF博士的博客

The TabControl will accept your controls as its controls only if they can be cast to TabItem , not UserControl, or SmartFormAreaView, etc. 只有将TabControlTabItem ,而不是UserControl或SmartFormAreaView等时, TabControl才会接受控件作为控件。

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. 因此,您可以使用可视树填充常规TabItems ,或者IsItemItsOwnContainerOverride TabItems子类,或者IsItemItsOwnContainerOverride TabControl以覆盖其IsItemItsOwnContainerOverride方法,以接受您的类型作为容器。

The method should look as follows: 该方法应如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM