2015-03-30 4 views
0

После my first question, я остался со следующим XAML:Как создать пользовательский заголовок TabItem в триггере стиля?

<Window 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <TabControl> 
      <TabControl.Resources> 
       <Style TargetType="{x:Type TabItem}"> 
        <Setter Property="RenderTransformOrigin" Value="0.5,0.5"/> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate TargetType="{x:Type TabItem}"> 
           <Border BorderBrush="Transparent" Background="Transparent"> 
             <ContentPresenter x:Name="TabItemContent" VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True"/>          
           </Border> 
           <ControlTemplate.Triggers> 
            <Trigger Property="IsSelected" Value="True"> 
             <Setter Property="TextElement.Foreground" Value="DarkOrange" TargetName="TabItemContent"/> 
            </Trigger> 
           </ControlTemplate.Triggers> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter>  
       </Style> 
      </TabControl.Resources> 
      <TabItem> 
       <TabItem.Header> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="First"/> 
        <TextBlock Text="Tab"/> 
       </StackPanel> 
       </TabItem.Header> 
       <TextBlock Text="TextBlock"/>      
      </TabItem> 
      <TabItem Header="TAB2"> 
       <TextBlock Text="TextBlock too"/> 
      </TabItem> 
     </TabControl> 
    </Grid> 
</Window> 

Моделирование хорошо работает на второй вкладке (которая имеет простой заголовок), но не для первого (с «комплексом ').

Есть ли способ обойти это поведение? Я не могу думать о себе; Я попытался заменить «TextElement» на «TabItem» без успеха.

EDIT: удалены несоответствующие части XAML.

ответ

1

Да, это сложная проблема; наследование работает логическим деревом, а логическим родителем сложного заголовка является TabItem. Если вы установите Foreground в TabItem, содержимое tabitem также наследует этот передний план, и это то, чего вы не хотите.

К счастью, есть простое решение: поместите пользовательский интерфейс в HeaderTemplate вместо свойства заголовка. Корень шаблона не имеет логического родителя, но у него есть ContentPresenter как его TemplatedParent, и, очевидно, наследование также распространяется от шаблонного родителя к корню в шаблоне.

+0

Это действительно работает, но это явно не удовлетворяет меня. Это хак-иш. И что, если мне пришлось использовать фактический заголовок в стиле? – Kilazur

+0

Что вы имеете в виду под заголовком «HeaderTemplate в стиле»? Но это правда, если вы, как автор контроля, не контролируете то, что помещено в заголовок/шаблон, то это не лучшее решение. Проблема здесь в том, что TabItem является логическим родителем для сложного заголовка и сложного содержимого. Таким образом, еще одним решением было бы установить Foreground явно в пользовательском интерфейсе в Content TabItem и установить Foreground для TabItem в триггере. –

+0

Да, это, скорее всего, лучшее решение здесь, пока не будет доказано обратное ... Спасибо – Kilazur

1

Итак, я придумал несколько элегантное решение, хотя и ограниченное (он будет использоваться только в том случае, если ваши пользовательские заголовки предназначены только для размещения 2 текстовых элементов, если вы хотите больше, это не сработает, хотя это не представляется невозможным заменить TextBlock на изображение, но да, 2 элемента).

Я только что добавил установщик HeaderTemplate в стиле TabItem и сделаю здесь свои темные ставки, привязанные к тегу, чтобы получить имя вкладки.

Вот как это происходит:

<Style TargetType="{x:Type TabItem}"> 
    <Setter Property="HeaderTemplate"> 
     <Setter.Value> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=TabItem}}" Margin="2,0"/> 
        <TextBlock Text="{Binding}" Margin="2,0"/> 
       </StackPanel> 
      </DataTemplate> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TabItem}"> 
       <ContentPresenter x:Name="TabItemContent" ContentSource="Header" HorizontalAlignment="Center" Margin="4" RecognizesAccessKey="True"/> 
       <ControlTemplate.Triggers> 
        <Trigger Property="IsSelected" Value="True"> 
         <Setter TargetName="TabItemContent" Property="TextElement.Foreground" Value="DarkOrange"/> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

И как она используется (размещение выше стиля в окне/UserControl/ресурсов TabControl в):

<TabItem Header="{Binding SomeValue}" Tag="TabName"> 
    <some:Controls/> 
</TabItem> 

Благодаря использованию StackPanel, если SomeValue имеет значение null, ваш TabItem будет показывать только «TabName».