在WinForms中,Form有一个ClientSize属性(从Control继承),它返回其客户区域的大小,即标题栏和窗口边框内部的区域。
我在WPF中没有看到类似的东西:没有ClientSize、ClientWidth、ClientHeight、GetClientSize()或其他任何我可以想到猜测名称的东西。
我该如何获取WPF窗口的客户区域大小?
你可以通过获取最顶层的子元素,将this.Content
转换为其类型,并调用.RenderSize
方法来获得其大小。
<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
编辑:
如Trent所说,ActualWidth
和ActualHeight
也是可行的解决方案。基本上是获取我上面提到内容的更简单方法。
var h = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
var w = ((Panel)Application.Current.MainWindow.Content).ActualWidth;
以下是一种实现方式。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;
}
}
}
}
Grid
且设置了VerticalAlignment=Top
。结果是,该Grid不再填充父级窗口(这是它的默认行为,但VerticalAligment属性破坏了它)。Border
解决了这个问题。该Border填充整个窗口内容,它具有与WPF窗口默认边框相同的尺寸。<Border BorderThickness="0" x:Name=Main>
<Grid VerticalAlignment="Top" Height="{Binding ElementName=Main, Path=ActualHeight}"> ...
</Grid>
</Border>
所有建议的解决方案都基于使用 Windows.Content
的大小来知道窗口内实际可用的大小,就像这样:
var h = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
当然,这仅在Window.Content
不为null时才有效。如果您想从代码中设置Window.Content
,那么问题就来了,您需要知道有多少可用空间。
另一个问题是,上面的代码仅在第一次布局循环完成后提供可用空间(即在Window_Loaded
事件中)。但是,如果您需要在第一次布局循环期间知道可用空间怎么办?例如,因为您在Windows.OnRender()
期间绘制到窗口中?
任何Window
的可视树中的第一个控件始终是一个Border
,即使Window.Content
为null。有趣的是,即使RenderSize.ActualSize
可能仍为零,Border.RenderSize
已经有一个值。我猜原因是Border的大小不取决于Window.Content
,而只取决于窗口的大小(除非当然使用Window.SizeToContent
)。
我建议将代码放置在 Window.SizeChanged
事件中。因为每次窗口大小改变时,您的内容也需要相应更改。您不能使用事件参数提供的大小,这会给您整个窗口的大小,但您可以像这样获取窗口内可用大小:
var h = ((Border)GetVisualChild(0)).RenderSize.Height;
如果你重写 Windows.OnRender()
,你也可以使用那行代码。