Is it possible to Left-Align headers in a WPF TabControl? - wpf

Right now, I have a WPF window where all the tab labels of the TabControl are centered.
I'd like the tab levels of the TabControl to be left-aligned.
Is this possible without completely redoing the ControlTemplate?
I tried messing with HorizontalAlignment, HorizontalContentAlignment, etc., but nothing I tried had the desired effect.
If I try this solution (offered by T Levesque):
<TabControl...>
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</TabControl.ItemContainerStyle>
...
</TabControl>
...I get this:
All the tab labels of the TabControl are left-aligned, but the tabs don't stretch properly
Which is close, but it ends up looking kind of like a histogram.

The following will give you the look you are after.
<TabControl TabStripPlacement="Left" HorizontalContentAlignment="Left" >
<TabItem HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Header="Header 1">
<TabItem.Content>Test</TabItem.Content>
</TabItem>
<TabItem HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Header="Header 2" >
<TabItem.Content>Test</TabItem.Content>
</TabItem>
<TabItem HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Header="Header Longer Version">
<TabItem.Content>Test</TabItem.Content>
</TabItem>
</TabControl>

What sort of Control are you using for the TabItem.Header property? If you are simply using a Label, are you specifying the width of the Label to some common value? If the Label is sizing to content then it will appear as you have shown. Try the following with a common width for the labels used to display the header text:
<TabControl TabStripPlacement="Left" >
<TabItem>
<TabItem.Header>
<Label Width="100">test tab 1</Label>
</TabItem.Header>
<TabItem.Content>
xyz
</TabItem.Content>
</TabItem>
<TabItem>
<TabItem.Header>
<Label Width="100">test t2</Label>
</TabItem.Header>
<TabItem.Content>
abc
</TabItem.Content>
</TabItem>
<TabItem>
<TabItem.Header>
<Label Width="100">test tab three</Label>
</TabItem.Header>
<TabItem.Content>
abc
</TabItem.Content>
</TabItem>
</TabControl>

You can define the horizontal alignment for all tab headers :
<TabControl...>
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</TabControl.ItemContainerStyle>
...
</TabControl>

Simply adding the attribute HorizontalContentAlignment="Left" to the TabControl will align tab headers left.
<TabControl
Margin="0,5,0,0"
HorizontalContentAlignment="Left"
TabStripPlacement="Left">
<TabItem
Header="Perform System Administration">
...
<TabItem
Header="Perform Setup Tasks">
...

Related

How to remove the line between Header and ContentPresenter when TabControl.TabItem has fixed value?

Look at the difference if I replace this code:
<TabControl TabStripPlacement="Left">
<TabItem Header="Example"/>
</TabControl>
with this one:
<TabControl TabStripPlacement="Left">
<TabItem Header="Example" Width="57" />
</TabControl>
In the second case, how can I avoid the drawing of the vertical line between Header and ContentPresenter of the TabControl.TabItem?
You could use the HeaderTemplate instead and put the fixed size within the DataTemplate.
<TabControl TabStripPlacement="Left">
<TabItem Header="Example">
<TabItem.HeaderTemplate>
<DataTemplate>
<TextBlock Text="Example" TextAlignment="Center" Width="57" />
</DataTemplate>
</TabItem.HeaderTemplate>
</TabItem>
</TabControl>

Styles in XAML doesn't work

Why the color of the TabItems is always black? I want black Background and white letters. Also the Button should be white, but it's black too and not visible. There is some conflict but can't find where. Any ideas? Thx in advance for your help.
<UserControl x:Class="Test.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cal="http://www.caliburnproject.org"
xmlns:cm="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
mc:Ignorable="d" d:DesignHeight="252" d:DesignWidth="894" Background="#FF111111">
<Grid>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Foreground="White" FontSize="48" Margin="70,-14.668,0,0" FontWeight="Light"><Run Language="de-at" Text="test test"/></TextBlock>
<Button x:Name="Close" Content="➔" HorizontalAlignment="Left" VerticalAlignment="Top" Width="58" Foreground="White" Height="58" RenderTransformOrigin="0.5,0.5" FontSize="40" Margin="-7.625,-8,0,0" Padding="1,-5,1,1" Clip="M50.333,8 L-1.667,8 L-1.667,59.843 L50.333,59.843 z" cm:Message.Attach="Close()">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1" ScaleX="-1"/>
<SkewTransform AngleY="0" AngleX="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>
<TabControl Margin="42,52,0,0">
<TabItem Header="Start">
</TabItem>
<TabItem Foreground="White" Header="Start 1" >
</TabItem>
<TabItem Foreground="White" Header="Start 1">
</TabItem>
<TabItem Foreground="White" Header="Start 1">
</TabItem>
<TabItem Foreground="White" Header="Start 1">
</TabItem>
</TabControl>
</Grid>
I tried many things and it didn't work. So what i did is put a TextBlock inside the TabItem.Header:
<TabItem>
<TabItem.Header>
<TextBlock FontSize="25" Text="Start1" />
</TabItem.Header>
</TabItem>
Now I can change the color of the TextBlock with Foreground. But don't know how to change the TextBlock color if I click on the TabItem. Maybe I should open a new topic for that. Thanks all for your contribution.
You're not setting the Background or Foreground properties of your TabControl at all, so it's using the default colors.
The default color of the Background property of any Control object is Brushes.Transparent (source), while the default Foreground property is based on your system colors (source).
You can use an implicit style in your UserControl.Resources to set a property for all objects of the specified type, such as using this style for all Control objects:
<UserControl.Resources>
<Style TargetType="{x:Type Control}">
<Setter Property="Background" Value="Black" />
<Setter Property="Foreground" Value="White" />
</Style>
</UserControl.Resources>
Or if you can add a new Brush to your .Resources and set it's x:Key to the System Key of one of the SystemColors , like this:
<UserControl.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.WindowColorKey}" Color="Black"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrush}" Color="White"/>
</UserControl.Resources>
(You might need to test a bit to figure out which is the correct SystemColors Key to use. You can find a list of them here)

How to reuse layouts in WPF

I'm trying to create a application that will be tabbed where each tab will have a button area and a view area.
Now each tab will essentially have the same layout just different things in the layout and I wanted to be able to reuse the same layout so that I won't have to change at many places ( it's just not good programming ). Can I accomplish this using resources or perhaps Styles.
Please supply a light code example if possible.
EDIT: I've decided to add an example of what I'm trying to do because I'm still not getting it.
Under each TabItem I'm trying to recreate this grid (It's a bit more complicated but you get the idea ):
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Margin="10"
BorderBrush="{StaticResource MediumColorBrush}"
CornerRadius="10"
BorderThickness="2"
Grid.Row="0">
<!-- First content goes here -->
</Border>
<Border Margin="10"
BorderBrush="{StaticResource MediumColorBrush}"
CornerRadius="10"
BorderThickness="2"
Grid.Row="1">
<!-- Second content goes here -->
</Border>
</Grid>
as you can see also the 2 borders are the same. Now I need to put some content placeholder where my comments are. I wan't to declare this Grid layout in a resource dictionary and then where I use it put seperate content into each border.
I may have alot of TabItems so repeating this code isn't a good idea and each Tab page will have different content in the 2 placeholders.
I'm able to use the
<ContentPresenter Content="{Binding}" />
thing but only for 1 content, what happens when there will be more.
Ingo,
Code is always available on MSDN. Check this: UserControl, Custom controls, DataTemplates.
Here are some examples of each approach. For sake of simplicity, let's assume the layout you want to replicate is one line of text with green foreground (in reality it may be really different, but you get the idea).
1. User Control
Xaml:
<UserControl x:Class="WpfApplication1.GreenTextUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBlock x:Name="txt" Foreground="Green"/>
</UserControl>
C#:
using System.Windows.Controls;
namespace WpfApplication1
{
public partial class GreenTextUserControl : UserControl
{
public string Text
{
get { return txt.Text;}
set { txt.Text = value; }
}
public GreenTextUserControl()
{
InitializeComponent();
}
}
}
Tab control:
<TabControl>
<TabItem Header="Tab 1">
<loc:GreenTextUserControl Text="This is Tab 1"/>
</TabItem>
<TabItem Header="Tab 2">
<loc:GreenTextUserControl Text="This is Tab 2"/>
</TabItem>
<TabItem Header="Tab 3">
<loc:GreenTextUserControl Text="This is Tab 3"/>
</TabItem>
</TabControl>
2. Custom control
C#:
public class GreenTextBlock : TextBlock
{
public GreenTextBlock()
{
Foreground = Brushes.Green;
}
}
TabControl:
<TabControl>
<TabItem Header="Tab 1">
<loc:GreenTextBlock Text="This is Tab 1"/>
</TabItem>
<TabItem Header="Tab 2">
<loc:GreenTextBlock Text="This is Tab 2"/>
</TabItem>
<TabItem Header="Tab 3">
<loc:GreenTextBlock Text="This is Tab 3"/>
</TabItem>
</TabControl>
If your layout is more complex than textblock, custom controls also allows you to define it in XAML but it differs from UserControls.
3. DataTemplate
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<x:Array x:Key="GreenText" Type="{x:Type System:String}">
<System:String>This is Tab 1</System:String>
<System:String>This is Tab 2</System:String>
<System:String>This is Tab 3</System:String>
</x:Array>
<!--Tab item content data template-->
<DataTemplate x:Key="GreenTextTemplate">
<TextBlock Text="{Binding}" Foreground="Green"/>
</DataTemplate>
</Window.Resources>
<Grid>
<TabControl ItemsSource="{StaticResource GreenText}">
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="ContentTemplate" Value="{StaticResource GreenTextTemplate}"/>
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
</Grid>
</Window>
That's it :). Hope it helps.
TabItem is a ContentControl which allows any child content, but also allows templating of the content, which is exactly what you're trying to do. You can use a DataTemplate like this to do your shared layout. ContentPresenter is the placeholder for the different content of each TabItem.
<DataTemplate x:Key="ButtonViewerTemplate">
<DockPanel>
<Button DockPanel.Dock="Bottom" Content="OK"/>
<Button DockPanel.Dock="Bottom" Content="Cancel"/>
<Border Background="Aqua" BorderBrush="Red" BorderThickness="2" Padding="5">
<ContentPresenter Content="{Binding}" />
</Border>
</DockPanel>
</DataTemplate>
To use the template just set it to each TabItem's ContentTemplate. This works with anything derived from ContentControl.
<TabControl>
<TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="Some Buttons">
<UniformGrid>
<Button Content="XXXXX"/>
<Button Content="XXXXX"/>
<Button Content="XXXXX"/>
<Button Content="XXXXX"/>
</UniformGrid>
</TabItem>
<TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="All Blue">
<Border Background="Blue" MinHeight="50"/>
</TabItem>
<TabItem ContentTemplate="{StaticResource ButtonViewerTemplate}" Header="Image">
<Image Source="http://i.msdn.microsoft.com/Platform/Controls/StoMastheadMSDN/resources/logo_msdn.png"/>
</TabItem>
</TabControl>

WPF TabItem Content alignment is always centered

I'm trying to put some content inside my TabItem, but I can't add a container that fills the space of the TabItem. Anything that I add shows up centered.
I'm using a Theme from WPF Toolkit (WhistlerBlue.xaml), so I think that maybe it's that what is causing me this issue.
I cannot remove the Theme, because I need it. At most I could change something in it, but I'm new to WPF, and don't know what should I be changing.
My TabControl looks like this:
<TabControl Margin="0,71.25,0,206.25" Name="tabControl1" TabStripPlacement="Left">
<TabItem Name="tabItem1" FlowDirection="LeftToRight" FontSize="22" Height="200" Width="60" >
<TabItem.Header>
<StackPanel Orientation="Horizontal" >
<Image Height="40" Width="40" Margin="20,0,0,0" VerticalAlignment="Center"></Image>
<TextBlock Margin="15,0,25,0" VerticalAlignment="Center" FontWeight="Bold">
Header
</TextBlock>
</StackPanel>
</TabItem.Header>
<TabItem.Content>
<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,0,0,0" >
<TextBlock>Test</TextBlock>
</StackPanel>
</TabItem.Content>
</TabItem>
</TabControl>
There is similar question, but it don't has the answer: In WPF, how do I get the content of a tabItem to fill available space?
Can someone help me?
Thanks.
Ok, I found the answer.
The .xaml of the theme started with these settings for TabItem:
<Style d:IsControlPart="True" TargetType="{x:Type TabItem}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
I've changed Center to Stretch, and the problem was solved.
I really need to learn WPF from a book, instead of just trying things out.
Use <controls1:TabItem HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" >

How to put WPF Tab Control tabs on the side

I am trying to create a Tab Control in WPF that has the tabs arranged down the right side of the control, with the text rotated 90 degrees The look is similar to those plastic tabs you can buy and use in a notebook. I have tried changing the TabStripPlacement to Right, but it just stacks the tabs up on the top right side of the control - not at all what I had in mind.
The effect I believe you are seeking is achieved by providing a HeaderTemplate for the TabItem's in you Tab collection.
<TabControl TabStripPlacement="Right">
<TabControl.Resources>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Padding" Value="4" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<ContentPresenter Content="{TemplateBinding Content}">
<ContentPresenter.LayoutTransform>
<RotateTransform Angle="90" />
</ContentPresenter.LayoutTransform>
</ContentPresenter>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TabControl.Resources>
<TabItem Header="Tab Item 1" />
<TabItem Header="Tab Item 2" />
<TabItem Header="Tab Item 3" />
<TabItem Header="Tab Item 4" />
</TabControl>
Hope this helps!

Resources