Bradford Fisher
Bradford Fisher

Reputation: 151

Sizing Content to Fill `Client Area` of Window

I am having trouble sizing a WPF control (I'll use the Grid control in this example) to the size of the Client area of a Window. I realize that the Grid automatically fills all available space by default, however I require the Grid's Width to be set manually so that I may bind to it from another control (a DataGrid with one of its column's Width's set to Star if it makes any difference).

Please consider the following XAML:

<Window x:Class="TestApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="768" Width="1024"
        x:Name="mainWindow">

    <ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto">
        <Grid x:Name="testGrid" Background="DarkGray">
        </Grid>
    </ScrollViewer>

</Window>

And the following Code-Behind:

using System.Windows;

namespace TestApplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            testGrid.Width = mainWindow.Width - (SystemParameters.BorderWidth * 2);
        }
    }
}

When running this simple application, the Grid has a width that is slightly larger than the Client area of the Window, resulting in a Horizontal Scroll Bar being displayed. If SystemParameters.BorderWidth does not accurately calculate the width of the Window's border, what does?

As per the most recent MSDN documentation, SystemParameters.BorderWidth: Gets the metric that determines the border width of the nonclient area of a nonminimized window.

Upvotes: 3

Views: 1701

Answers (3)

Bradford Fisher
Bradford Fisher

Reputation: 151

After having fought with this sizing issue for quite some time, I have finally found an elegant solution to the problem. Though I have alread selected @Rick Sladkey's response as the answer (and answer my question it did), I thought I might post my updated understanding in hopes that it might help someone else down the line.

The real frustration point, it turns out, was in dealing with the ScrollViewer. While sizing my content to the ActualWidth of the ScrollViewer worked wonderfully when it's VerticalScrollBar was not visible, things began to break down as soon as my content grew to a vertically scrollable height. Though I had expected the binding on ActualWidth to resize my contol to fit within the viewable area of the ScrollViewer, in reality it remained the same width and became horizontally scrollable as well.

As it turns out, the fix was actually quite simple. Rather than binding the height or width of a control to the ActualHeight or ActualWidth of the ScrollViewer (respectively), bind the height or width of the control to the ViewportHeight or ViewportWidth of the ScrollViewer.

Upvotes: 1

Rick Sladkey
Rick Sladkey

Reputation: 34250

Here is one way of binding the size of the client width with no code-behind:

<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Auto">
    <Grid x:Name="testGrid" Background="DarkGray" Width="{Binding Content.ActualWidth, ElementName=mainWindow}">
    </Grid>
</ScrollViewer>

This uses your named top-level Window and gets with actual width of it's content, a ScrollViewer in this case. If for some reason you want to want the content of the window to be a different size than the window you can enclose it in an empty Grid so this technique still works.

Upvotes: 5

J Cooper
J Cooper

Reputation: 5008

Instead of setting the width manually, how about binding to the grid's ActualWidth property instead (this will give you an actual value)

Upvotes: -1

Related Questions