Why do my panels clip all the way around the panel when made smaller than the explicit size?
Asked Answered
O

2

5

Probably a confusing question title.

The Grid with the Red Rectangle is an example of how it should look.

The Grid with the Blue Rectangle (not appearing in the image) has a margin that forces the second grid to be smaller than I've explicitly set it. Which appears to cause WPF to flip out and hide everything outside of it's arranged bounds.

enter image description here

I've tried setting the Clip to be larger than the Grid.

The only way I've been able to avoid this is to write a custom panel that measures it's children with a constraint of PositiveInfinity, but then arranges the children with the correct width. That method has lots of problems. It's not good to lie to your children.

Anyway, here's the code:

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="NegativeMarginTooMuchClipping.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640"
Height="400">

<Grid>
    <StackPanel Width="600" Height="300">
    <Grid Margin="40,50,60,50" Background="#FFB8B8B8" Width="500" Height="50">
        <Rectangle Fill="Red" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="50" Margin="0,-50,0,0"/>
    </Grid>
    <Grid Margin="40,50,61,50" Background="#FFB8B8B8" Width="500" Height="50">
        <Rectangle Fill="Blue" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="50" Margin="0,-50,0,0"/>
    </Grid>
    </StackPanel>
</Grid>

Known issue? Am I doing it wrong? Need more clarification?

Oslo answered 27/4, 2011 at 21:21 Comment(1)
First you move the blue Rectangle outside the Grid and then you even move it accross the StackPanel bounds, blue Rectangle is not amused.Uuge
H
10

There are three things that go into to determining how something clips. The first two are ClipToBounds and Clip, but the third is a little more annoying and that is GetLayoutClip.

By default, for UIElement the GetLayoutClip method will return either null or a RectangleGeometry the same size as the element, depending on the ClipToBounds property. FrameworkElement, and it's derivations, are much more complex though. Take a look in Reflector/ILSpy and you will see what I mean.

You can override this behavior though. If you use something like the following as your Grid for the blue rectangle, then it will no longer be clipped:

public class MyGrid : Grid {
    protected override Geometry GetLayoutClip(Size layoutSlotSize) {
        return null;
    }
}

There is a great blog post on this here.

Haemocyte answered 27/4, 2011 at 23:59 Comment(1)
Fantastic. Thank you! You save me more heart ache. That is indeed an annoying little method.Oslo
C
0

It took me some time to understand the issue and I am simplifying the issue using single grid control. Also to make the problem more clear I am hiding the Window title bar as Window Height includes the title bar height.

I set the window Height to 150. This 150 height is divided as

  • 50 for the Top Margin of the Grid Control
  • 50 for Grid Height
  • 50 for the Bottom Margin of the Grid Control.

I placed the blue border inside the grid to show that the Red rectangle disappears only when the window heights fall below 150 causing the grid to clip along height as we try to reduce the height of the window. The red rectangle reappears again as soon as the window height is equal to or above 150. A similar issue is explained with more examples here on Stackoverflow

Here is the MainWindow.xaml code for replicating the issue when window height=149.

<Window x:Class="ClipToBounds.Rectangle_With_Negative_Margin_Inside_Grid_Problem"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Width="600"
        WindowStyle="None"
        Height="149">
        <Grid Margin="0,50,0,50" Background="GreenYellow" Width="600" Height="50">
            <Border BorderBrush="Blue" BorderThickness="1"></Border>
            <Rectangle Fill="red" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="50" Margin="0,-50,0,0"/>
        </Grid>
</Window>

Here is the output: enter image description here

Fix-1: Placing Grid inside Canvas

<Window x:Class="ClipToBounds.Rectangle_With_Negative_Margin_Inside_Grid_Problem_Fix_Using_Canvas"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Width="600"
        WindowStyle="None"
        Height="149">
    <Canvas>
        <Grid Margin="0,50,0,50" Background="GreenYellow" Width="600" Height="50">
            <Border BorderBrush="Blue" BorderThickness="1"></Border>
            <Rectangle Fill="red" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="50" Margin="0,-50,0,0"/>
        </Grid>
    </Canvas>
</Window>

Here is the Output: enter image description here

Fix-2: Using CustomGrid that overrides GetLayoutClip() method.

<Window x:Class="ClipToBounds.Rectangle_With_Negative_Margin_Inside_Grid_Problem_Fix_Using_CustomGrid"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ClipToBounds"
        Title="MainWindow" Width="600"
        WindowStyle="None"
        Height="149">
    <local:MyGrid Margin="0,50,0,50" Background="GreenYellow" Width="600" Height="50">
        <Border BorderBrush="Blue" BorderThickness="1"></Border>
        <Rectangle Fill="red" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="50" Margin="0,-50,0,0"/>
    </local:MyGrid>
</Window>

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ClipToBounds;

public class MyGrid : Grid
{
    protected override Geometry GetLayoutClip(Size layoutSlotSize)
    {
        return ClipToBounds ? base.GetLayoutClip(layoutSlotSize) : null;
    }
}

Here is the Output: enter image description here

Camilla answered 5/3 at 21:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.