Почему заголовки вкладок отображаются в области содержимого вкладок в XAML TabControl?

StackOverflow https://stackoverflow.com/questions/1226622

Вопрос

У меня есть TabControl ( Табуляция ) чей ItemsSource привязан к наблюдаемая коллекция представлений (UserControls), каждый из которых имеет в качестве своего корневого элемента ТабИтем.Однако, когда он отображается, Заголовок текст находится в содержимом каждой вкладки, как если бы Пользовательский контроль оболочка вызывает конфликты:

alt text

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>

Что я должен изменить, чтобы TabItems отображались как TabItems внутри TabControl?

Вот представления TabItem, называемые 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>

И вот здесь я создаю и загружаю каждое представление в Наблюдаемая коллекция:

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);
}
Это было полезно?

Решение

Для любого ItemsControl, если элементы, добавленные в его коллекцию Items (напрямую или через ItemsSource), не являются экземплярами контейнера item этого элемента управления, то каждый элемент оборачивается экземпляром контейнера item.Контейнер элемента - это класс, такой как TabItem или ListBoxItem.Контейнером элемента обычно является ContentControl или HeaderedContentControl, и ваш фактический элемент присваивается его свойству Content, поэтому вы можете использовать шаблоны и т.д. Для управления представлением содержимого.Вы также можете стилизовать сам контейнер item, используя свойство ItemContainerStyle ItemContainerStyle от ItemControl.

В этом конкретном случае вам следует привязать ItemsSource к списку SmartFormAreaPresenters.Затем используйте что-то вроде этого для элемента управления tab:

<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>

где HeaderText является подходящим свойством в вашем SmartFormAreaPresenter.Вам также следует удалить TabItem из вашего определения SmartFormAreaView.DataContext каждого представления будет автоматически присвоен соответствующему презентатору.

Обратитесь к докторуWPF's Блог за отличное обсуждение различных тем, связанных с ItemsControl.

Другие советы

Тот самый TabControl примет ваши элементы управления в качестве своих только в том случае, если они могут быть приведены к TabItem, а не UserControl, или SmartFormAreaView, и т.д.

Таким образом, вы либо заполняете обычную TabItems с вашим визуальным деревом, или вы создаете подкласс TabItems, или вы относите к подклассу TabControl чтобы переопределить его IsItemItsOwnContainerOverride метод, позволяющий принять ваш тип в качестве контейнера.

Метод должен выглядеть следующим образом:

protected override bool IsItemItsOwnContainerOverride(object item)
{
    return item is YourControlTypeHere || item is TabItem;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top