Reputation: 5083
I have a TabControl and am attempting to get the headers to look nice. I have the following XAML:
(In Resources.xaml
:)
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel LastChildFill="True" MinWidth="200" Height="20" HorizontalAlignment="Stretch" behaviors:MouseClickBehavior.ClickCommand="{Binding Path=CloseCommand}">
<Image Source="{Binding Path=Image}" Height="16" VerticalAlignment="Center" />
<Button Background="Transparent"
BorderBrush="Transparent"
Command="{Binding Path=CloseCommand}"
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontSize="9"
FontWeight="Bold"
Margin="3,0,0,0"
Padding="0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Width="16" Height="16" />
<TextBlock Text="{Binding Path=Header}" DockPanel.Dock="Left" VerticalAlignment="Center" />
</DockPanel>
</DataTemplate>
(In MainWindow.xaml
:)
<TabControl Grid.Column="1"
ItemsSource="{Binding Path=Tabs}"
ItemTemplate="{DynamicResource ClosableTabItemTemplate}" />
Here is a visual example of my problem:
I like the actual width of the tabs for now, but the fact that my dockpanel for the header isn't filling up all the space is bothersome. Same thing happens if I use a Grid
, too (presumably any container control).
Upvotes: 7
Views: 4948
Reputation: 6209
ContentPresenter.HorizontalAlignment
in the default style for TabItem
is bound to ItemsControl.HorizontalContentAlignment
. Here it is, taken from Aero.NormalColor.xaml:
<ContentPresenter Name="Content"
ContentSource="Header"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
HorizontalAlignment="{Binding Path=HorizontalContentAlignment,RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
VerticalAlignment="{Binding Path=VerticalContentAlignment,RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
RecognizesAccessKey="True"/>
Setting TabControl.HorizontalContentAlignment
to Stretch
fixes the issue for me.
<TabControl HorizontalContentAlignment="Stretch" />
Upvotes: 8
Reputation: 91
I ran into the same visual issue with closable tabs and resolved it by extending both the TabControl
(to be used later in XAML) and TabItem
classes. I overrode GetContainerForItemOverride()
in the former, and OnApplyTemplate()
in the latter. I created a DependencyObject
extension method to find the ContentPresenter
element of the TabItem
and set its HorizontalAlignment
property to HorizontalAlignment.Stretch
:
public class MyTabControl : TabControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new MyTabItem();
}
}
public class MyTabItem : TabItem
{
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var content = this.GetFirstDescendantOfType<ContentPresenter>();
if (content != null)
{
content.HorizontalAlignment = HorizontalAlignment.Stretch;
}
}
}
public static class DependencyObjectExtensions
{
public static T GetFirstDescendantOfType<T>(this DependencyObject parent) where T : DependencyObject
{
if (parent == null)
{
return null;
}
else
{
var children = parent.GetChildren();
T descendant = children.FirstOrDefault(child => child is T) as T;
if (descendant == null)
{
foreach (var child in children)
{
if ((descendant = child.GetFirstDescendantOfType<T>()) != null) break;
}
}
return descendant;
}
}
public static IEnumerable<DependencyObject> GetChildren(this DependencyObject parent)
{
var children = new List<DependencyObject>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
children.Add(VisualTreeHelper.GetChild(parent, i));
}
return children;
}
}
My XAML appears as the following:
(In MainWindowResources.xaml
):
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel>
<Button Command="{Binding Path=CloseCommand}"
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontFamily="Courier"
FontSize="9"
FontWeight="Bold"
Margin="8,1,0,0"
Padding="0"
VerticalContentAlignment="Bottom"
Width="16"
Height="16"
ToolTip="Close" />
<TextBlock Text="{Binding Path=DisplayName}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DockPanel>
</DataTemplate>
(In MainWindow.xaml
): Note the use of the custom MyTabControl
control
<MyTabControl IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=ClosableViewModels}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4" />
Upvotes: 3
Reputation: 132548
Try overwritting the ItemContainerStyle.Template
instead of the ContentTemplate
I did something like this in the past, although I overwrote the entire TabControl
template so it's a bit hard to see what I was doing. My code looked like this:
<ControlTemplate x:Key="CurvedTabItemTemplate" TargetType="{x:Type TabItem}">
<DockPanel Width="200">
<ContentPresenter x:Name="ContentSite" ContentSource="Header" RecognizesAccessKey="True" />
</DockPanel>
</ControlTemplate>
<Style x:Key="CurvedTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template" Value="{StaticResource CurvedTabItemTemplate}" />
</Style>
<TabControl Grid.Column="1" ItemsSource="{Binding Path=Tabs}"
ContentTemplate="{DynamicResource ClosableTabItemTemplate}"
ItemContainerStyle="{DynamicResource CurvedTabItemStyle}" />
Upvotes: 2