Novitchi S
Novitchi S

Reputation: 3741

WPF negative margins are not displayed correctly

I am trying to simulate a tab control with a nice TabHeader and TabContent. The control should look something like this:

desired header border

This is achieved by setting the `Margin' of the first Header - "HOME" to Margin="2 0 2 -1".

ISSUE: if I re-size the window to a certain smaller width, the header item visually clips its content. Here is the result:

undesired border

I really would like to know why this is happening and how ca i avoid this.

The sample xaml to prove the problem:

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="550" Width="525">
<Grid Margin="0 50">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <Border  BorderThickness="1" BorderBrush="Black" Grid.Row="1"/>

    <StackPanel Orientation="Horizontal" Grid.Row="0">
        <Border Width="50" Margin="2 0 2 -1" BorderThickness="1 1 1 0" BorderBrush="Black" Background="White">
            <TextBlock Text="HOME" />
        </Border>
        <Border Width="150" Margin="2 -20" Height="20" BorderThickness="1 1 1 0" >
            <TextBlock Text="EDIT" />
        </Border>
    </StackPanel>
</Grid>

Upvotes: 4

Views: 4795

Answers (3)

Mike Strobel
Mike Strobel

Reputation: 25623

I would theorize that this is an oddity in the layout code of StackPanel. You should be able to work around it by moving the negative margin to the StackPanel itself, as opposed to the tabs within:

<Grid Margin="0 50" UseLayoutRounding="True">
  <Grid.RowDefinitions>
    <RowDefinition Height="auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <Border BorderThickness="1" BorderBrush="#7FFF0000" Grid.Row="1" />
  <StackPanel Orientation="Horizontal" Grid.Row="0" Margin="0,0,0,-1">
    <Border Width="50" Margin="2 0 2 0" BorderThickness="1 1 1 0" BorderBrush="Lime" Background="Yellow">
      <TextBlock Text="HOME" />
    </Border>
    <Border Width="150" Margin="2 0 2 0" Height="20" BorderBrush="Blue" BorderThickness="1 1 1 0" Background="Yellow">
      <TextBlock Text="EDIT" />
    </Border>
  </StackPanel>
</Grid>

Note that I changed the colors to assist with visual debugging. It's a useful technique, but you'll probably want to change them back :).

Upvotes: 0

HichemSeeSharp
HichemSeeSharp

Reputation: 3318

When you resize the window, XAML renderer redraw any flexible (still can be resized or moved relatively). when you reach the StackPanel width limit (limited by what it contains or a fixed Width) the control is ignored at redrawing (even what it contains) and the renderer keeps redrawing other flexible controls; in your case : the first border. that's why comes suddenly on the top of the others.

Moving the margin to the StackPanel will do the trick :

<StackPanel Orientation="Horizontal" Grid.Row="0" Margin="2 0 2 -1">
            <Border Width="50"  BorderThickness="1 1 1 0" BorderBrush="Black" Background="White">
                <TextBlock Text="HOME" />
            </Border>
            <Border Width="150" Height="20" BorderThickness="1 1 1 0" >
                <TextBlock Text="EDIT" />
            </Border>
        </StackPanel>

Upvotes: 2

baueric
baueric

Reputation: 386

Here is a solution with 2 columns

   <Grid Margin="0,50">
    <Grid.RowDefinitions>
        <RowDefinition Height="auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Border Grid.ColumnSpan="2"  BorderThickness="1" BorderBrush="Black" Grid.Row="1" />

    <StackPanel Orientation="Horizontal" Grid.Row="0">
        <Border Width="50" Margin="2,0,2,-1" BorderThickness="1,1,1,0" BorderBrush="Black" Background="White">
            <TextBlock Text="HOME" />
        </Border>
        <Border Width="50" Margin="2" Height="20" BorderThickness="1,1,1,0" >
            <TextBlock Text="EDIT" />
        </Border>
    </StackPanel>
</Grid>

This makes the grid not get clipped by the window size.

EDIT added additional column to push the border to the edge.

Cheers, Eric

Upvotes: 1

Related Questions