Search code examples
wpfbuttonuibuttontabcontrol

WPF - Why is my buttons content moving separately from the button itself?


I have created a TabControl in a WPF application I'm writing. I re-templated TabItem so that I could have a button on each tab header to close it. So far, all is well and good.

I decided that I now wanted shiny round buttons instead of the default square ugly things. Also, I wanted to use an image as my buttons content instead of simply setting the content to "X".

My XAML styles/templates:

<Style TargetType="{x:Type Button}" x:Key="EllipseButtonStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid>
                     <Ellipse Fill="{TemplateBinding Background}"
                         Stroke="{TemplateBinding BorderBrush}"
                         StrokeThickness="{TemplateBinding BorderThickness}"
                         Width="{TemplateBinding Width}"
                         Height="{TemplateBinding Height}"/>
                     <ContentPresenter HorizontalAlignment="Center" 
                         VerticalAlignment="Center"
                         Content="{TemplateBinding Button.Content}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<DataTemplate x:Key="ClosableTabItemTemplate">
    <DockPanel MinWidth="120" Margin="0,0,0,0">
        <ContentPresenter 
            Content="{Binding Path=DisplayName}" 
            VerticalAlignment="Center"
            HorizontalAlignment="Left"/>
        <Button
            Command="{Binding Path=UnSubscribeApplicationCommand}"
            CommandParameter="{Binding Path=DisplayName}"
            BorderBrush="Black"
            BorderThickness="2"
            VerticalContentAlignment="Center"
            VerticalAlignment="Center"
            HorizontalAlignment="Right"
            DockPanel.Dock="Right"
            Width="16" Height="16">
            <Image Source="closeicon.bmp" Height="8" Width="8" 
                VerticalAlignment="Center" HorizontalAlignment="Center"/>
                <Button.Style>
                    <Style TargetType="{x:Type Button}" 
                        BasedOn="{StaticResource EllipseButtonStyle}">
                        <Setter Property="Background"
                            Value="{StaticResource CloseOffButtonBrush}"/>
                        <Style.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Background" Value="{StaticResource CloseOnButtonBrush}"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>
        </DockPanel>
    </DataTemplate>

With the above code in place, however, a selected tabs content (and the background as well) seems to shift upwards because of what I assume is the TabItems content moving upwards due to it being selected. Why, then, is the ellipse not shifting with the other content? Anyone have any idea what is going on here?


Solution

  • Sorry for the delayed response - I ended up solving the issue by modeling my TabItem template after the one posted in this blogpost. I believe the issue surfaced due to the fact that my TabItem template was being defined as a DataTemplate, not as a ControlTemplate as it should have been. Here is the new template:

    <ControlTemplate x:Key="ClosableTabItemTemplate" TargetType="TabItem">
        <Grid SnapsToDevicePixels="true">
            <Border x:Name="Bd" Background="{StaticResource TabItemUnselectedBrush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" >
                <DockPanel x:Name="ContentPanel">
                    <Button Command="{Binding Path=UnSubscribeApplicationCommand}" BorderBrush="Black" HorizontalAlignment="Center" Margin="3,0,3,0" VerticalAlignment="Center" Width="16" Height="16" DockPanel.Dock="Right" ToolTip="Close Tab">
                        <Button.Content>
                            <Image Source="pack://application:,,,/Resources/Close.png" Height="8" Width="8" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        </Button.Content>
                        <Button.Style>
                            <Style TargetType="{x:Type Button}" BasedOn="{StaticResource EllipseButtonStyle}">
                                <Setter Property="Background" Value="{StaticResource CloseOffButtonBrush}"/>
                                <Style.Triggers>
                                    <Trigger Property="IsMouseOver" Value="True">
                                        <Setter Property="Background" Value="{StaticResource CloseOnButtonBrush}"/>
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </Button.Style>
                    </Button>
                    <ContentPresenter x:Name="Content" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{Binding Path=DisplayName}" RecognizesAccessKey="True" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
                </DockPanel>
            </Border>
        </Grid>
    
        <!-- bunch of ControlTemplate triggers to style the TabItem background color/position -->
    
    </ControlTemplate>