How to get the visible size of control after margins are applied in WPF?

53 Views Asked by At

I have a grid whose width is set to 250. The Width of the Window is 600. The Left and Right margins of the grid are set to 50 and 400. So the rendered grid width is reduced to 600-(50+400) = 150.

I want to know how can I find the correct visible width of the first grid which is 150. However, none of the following properties is returning 150.

g1.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Debug.WriteLine($"g1.DesiredSize.Width={g1.DesiredSize.Width}"); // Returns 700
Debug.WriteLine($"g1.ActualWidth={g1.ActualWidth}"); //Returns 250
Debug.WriteLine($"g1.RenderSize.Width={g1.RenderSize.Width}"); //Returns 250
Debug.WriteLine($"g1.Width={g1.Width}"); //Returns 250

Xaml Code is

<Window Title="MainWindow" Width="600" Height="300">
    <StackPanel>
        <Grid Name ="g1" Margin="50,0,400,0" Background="GreenYellow" Width="250" Height="50"/>
        <Grid Name ="g2" Margin="50,0,400,0" Background="LightBlue" Width="150" Height="50"/>
    </StackPanel>
</Window>

Output is:

enter image description here

1

There are 1 best solutions below

0
Hemendr On BEST ANSWER

Ok, I think the issue is because of ClipToBounds issue. So actually the grid is rendered to the same size of 250 as defined, however, only portion of 150 width is visible and the remaining grid is clipped. More explanation can be found here on stackoverflow

If you don't want the Grid to be clipped so that the whole grid of 250 widths is visible then there are three choices

  • Replace Grid with Canvas control which is not affected by ClipToBounds issue.

  • Create a custom grid that overrides the GetLayoutClip() to return null when ClipToBounds=false

  • Place the grid inside the Canvas control

Things become more clear if you place a border inside your grid, then you can see that 1'st grid is infact clipped instead of rendered to width of 150.

Note: If you are overriding the GetLayoutClip() then make sure that you override it on the control that is getting clipped and not on the container. Like in the First example it was Grid inside StackPanel that was getting trimmed so we created CustomGrid MyGrid, while in the last example, it is the button that is getting clipped so we created custom button MyButton that overrides GetLayoutClip()

Here is the Output: enter image description here

Here is the MainWindow.xaml

<Window x:Class="ClipToBounds.Grid_And_Button_Trimmed_Problem"
        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" Height="500">
    <StackPanel>
        <TextBlock>Grid is affected by clipping issue</TextBlock>
        <Grid Margin="50,0,400,0" Background="GreenYellow" Width="250" Height="50">
            <Border BorderBrush="Blue" BorderThickness="2"></Border>
        </Grid>
        <TextBlock>Grid inside Canvas is not affected by clipping issue</TextBlock>
        <Canvas Width="600" Height="60">
            <Grid Margin="50,0,400,0" Background="GreenYellow" Width="250" Height="50">
                <Border BorderBrush="Blue" BorderThickness="2"></Border>
            </Grid>
        </Canvas>
        <TextBlock>CustomGrid that overrides GetLayoutClip() is now not affected by clipping issue </TextBlock>
        <local:MyGrid Margin="50,0,400,0" Background="GreenYellow" Width="250" Height="50">
            <Border BorderBrush="Blue" BorderThickness="2"></Border>
        </local:MyGrid>
        <TextBlock>Canvas itself is not affected by clipping issue</TextBlock>
        <Canvas  Margin="50,0,400,0" Background="GreenYellow" Width="250" Height="50">
            <Border BorderBrush="Blue" BorderThickness="2"  Width="250" Height="50"></Border>
        </Canvas>
        <TextBlock>Grid of width 150 for comparison</TextBlock>
        <Grid Margin="50,0,400,0" Background="LightBlue" Width="150" Height="50"/>
        <TextBlock>Button inside Grid is affected by clipping issue</TextBlock>
        <Grid Margin="50,0,400,0" Background="GreenYellow" Width="150" Height="50">
            <Button Width="200" Height="30">Some Text</Button>
        </Grid>
        <TextBlock>CusomButton that overrides GetLayoutClip() is now not affected by clipping issue</TextBlock>
        <Grid Margin="50,0,400,0" Background="GreenYellow" Width="150" Height="50">
            <local:MyButton Width="200" Height="30">Some Text</local:MyButton>
        </Grid>
    </StackPanel>
</Window>

Here is the code for CustomGrid MyGrid.cs

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 code for CustomButton MyButton.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ClipToBounds;

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