Question

Whenever I try to make a window and I set the SizeToContent to WidthAndHeight, on opening the window correctly sizes to it's contents, but it adds a small border to the right and the bottom. On resizing this disappears, and when using a set height and width this problem also doesn't occur.

This is a sample of what I mean:

enter image description here

You could say this is not a huge problem, though I find it makes my application look unprofessional, especially when I need to present this. Does anybody know why this is happening, or whether there is a workaround? I am coding this project in C#.

XAML Code:

<Window x:Class="FPricing.InputDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="InputDialog" Width="400" Height="300" SizeToContent="WidthAndHeight">
    <StackPanel>
        <Label x:Name="question">?</Label>
        <TextBox x:Name="response"></TextBox>
        <Button Content="OK" IsDefault="True" Click="Button_Click" />
    </StackPanel>
</Window>

Values are passed on on creation of the class.

However I experience this problem on every window I have ever created, even without custom underlying code.

Was it helpful?

Solution 2

Using this tool (it's good, btw) I found that the Border control of the Window (it's immediate child) doesn't fill the whole window, leaving that "border", which is actually the background of the Window control.

I've found a workaround. Width and Height of the Border are NaN. If you set those to an integer value, the "border" disappears.

Let's use the values of ActualWidth and ActualHeight, but rounded to an integer.

Define the converter:

C#

[ValueConversion(typeof(double), typeof(double))]
public class RoundConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        return Math.Ceiling((double)value);
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        return value;
    }
}

XAML (remember to include your namespace, in this case "c")

<c:RoundConverter x:Key="RoundConverter"/>

Then create a style binding the size to the actual size using the converter. It's important to use a Key, so it won't apply to every Border (most controls use it):

<Style TargetType="{x:Type Border}" x:Key="WindowBorder">
    <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={StaticResource RoundConverter}}"/>
    <Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Self}, Path=ActualHeight, Converter={StaticResource RoundConverter}}"/>
</Style>

Finally, apply this style to the first child of the window (the Border control):

private void Window_Loaded(object sender, RoutedEventArgs e) {
    GetVisualChild(0).SetValue(StyleProperty, Application.Current.Resources["WindowBorder"]);
}

If someone can do this in a simpler way, please share too.

OTHER TIPS

<Window UseLayoutRounding="True" /> works for me.

managed to solve it, by combining Gabriel and smg answers. Upon loading the window, get the border in question, and set its LayoutRounding to true.

this.Loaded += (sender, args) =>           
{
    var border = this.GetVisualChild(0) as Border;
    if (border != null)
        border.UseLayoutRounding = true;
};

Okay, heres a related answer in which you can refer to a great answer.

Automatic resizing when border content has changed

So basically you want to add something like this, but put it to the values that you want:

<Border x:Name="border"
            BorderBrush="Cornsilk"
            BorderThickness="1">
        <Ellipse Width="40"
                 Height="20"
                 Fill="AliceBlue"
                 Stroke="Black" />
    </Border>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top