Reputation: 97828
In WinForms, Form had a ClientSize property (inherited from Control), which returns the size of its client area, i.e., the area inside the title bar and window borders.
I'm not seeing anything similar in WPF: there's no ClientSize, ClientWidth, ClientHeight, GetClientSize(), or anything else that I can think to guess the name of.
How do I go about getting the client size of a WPF Window?
Upvotes: 20
Views: 34821
Reputation: 3312
All the suggested solutions are based on the idea to use the size of Windows.Content
to know what is the actual size available within the window, like this:
var h = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
This of course only works if Window.Content
is not null. Which is a problem if you want to set Window.Content
from your code and you already then need to know exactly how much space is available.
The other problem is that the above code only provides the available space once a first layout cycle has completed (i.e. in the Window_Loaded
event). But what do you do if you need to know the available space during the first layout cycle, for example because you draw to the window during Windows.OnRender()
?
The first control in the visual tree of any Window
is always a Border
, even if Window.Content
is null. Interestingly, Border.RenderSize
has already a value, even when RenderSize.ActualSize
might still be zero. I guess the reason is that the size of the Border does not depend on Window.Content
, but only on the size of the window (unless, of course, if Window.SizeToContent
is used).
I recommend to place your code into the Window.SizeChanged
event. Because each time the Window size changes, your content needs to change too. You cannot use the size provided in the event parameters, which gives you the size of the complete window, but you can get the the available size within the window like this:
var h = ((Border)GetVisualChild(0)).RenderSize.Height;
You can use that line of code also if you override Windows.OnRender()
.
Upvotes: 1
Reputation: 13417
I used a Grid
with VerticalAlignment=Top
. As a result the Grid unfortunately didn't fill the parent Window anymore (which is its default behaviour, but the VerticalAligment property spoils it).
I solved it by putting an empty Border
around the Grid. This border fills the complete content of the window, it has the same dimensions as the default border that a wpf window has anyways.
To get the Grid to fill the main window, I used the binding:
<Border BorderThickness="0" x:Name=Main>
<Grid VerticalAlignment="Top" Height="{Binding ElementName=Main, Path=ActualHeight}"> ...
</Grid>
</Border>
Upvotes: 1
Reputation: 96
One way to do it is with the code below. XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="Window1" Height="300" Width="300" Loaded="Window_Loaded">
<Canvas>
</Canvas>
</Window>
C#:
using System.Windows;
using System.IO;
using System.Xml;
using System.Windows.Controls;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
double dWidth = -1;
double dHeight = -1;
FrameworkElement pnlClient = this.Content as FrameworkElement;
if (pnlClient != null)
{
dWidth = pnlClient.ActualWidth;
dHeight = pnlClient.ActualHeight;
}
}
}
}
Upvotes: 2
Reputation: 301
var h = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
var w = ((Panel)Application.Current.MainWindow.Content).ActualWidth;
Upvotes: 10
Reputation: 16031
One way you could do it is to take the top most child element, cast this.Content
to its type, and call .RenderSize
on it, which will give you its size.
<Window x:Class="XML_Reader.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="400" Width="600" WindowStyle="SingleBorderWindow">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
</Grid>
</Window>
((Grid)this.Content).RenderSize.Height
((Grid)this.Content).RenderSize.Width
edit:
as Trent said, ActualWidth
and ActualHeight
are also viable solutions. Basically easier methods of getting what I put above.
Upvotes: 13