Reputation: 4897
I've got a WPF window, and I'm trying to get the Width
property. No matter where I try to present the code, it always returns as NaN
. I have looked up on the internet and read that I should actually be using ActualWidth
instead, but this returns 0 no matter what.
How can I get rid of the lag and get an actual value for my window's width?
XAML:
<Window x:Name="TableWindow" x:Class="QueryBuilder.DatabaseTable"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
WindowStyle="None" Background="Transparent" SizeToContent="WidthAndHeight" ResizeMode="CanResize">
<Grid>
<DockPanel>
<StackPanel Name="titleBar" DockPanel.Dock="Top" Height="28" FlowDirection="RightToLeft" Orientation="Horizontal" Background="AliceBlue">
<Button x:Name="btnClose" Margin="0,0,5,0" Click="btnClose_Click">
</Button>
<Button>
</Button>
<Button>
</Button>
<Button x:Name="btnAll">ALL</Button>
<Label Name="lblTableName" FontSize="15" Margin="50,0,0,0"></Label>
</StackPanel>
<StackPanel Orientation="Vertical" Name="spFields">
</StackPanel>
</DockPanel>
</Grid>
</Window>
XAML.cs:
public DatabaseTableWindow(string tableName, DataTable fields, string primaryKey)
{
InitializeComponent();
this.tableName = tableName;
this.fields = fields;
this.primaryKey = primaryKey;
lblTableName.Content = tableName;
double x = this.ActualWidth;
}
Upvotes: 1
Views: 895
Reputation: 5671
As we've been chatting in the WPF room regarding this question, this was a compounded problem to seemingly easy thing.
If we set width / height on mdiChild, we end up losing resize functionality. so I've posted a gist with the fix that seems to have solved this issue as per our chat
so to get the size bound, I used normal bindings (this copy paste from my test project):
<Window x:Class="TestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:MDI="clr-namespace:WPF.MDI;assembly=WPF.MDI" xmlns:TestApplication="clr-namespace:TestApplication"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="MainWindow">
<MDI:MdiContainer Name="mainContainer">
<MDI:MdiChild x:Name="mdiChild" MaximizeBox="False" MinimizeBox="False" Resizable="True" ShowIcon="False" Width="{Binding Width, ElementName=childElement}" Height="{Binding Height, ElementName=childElement}">
<TestApplication:DatabaseTable x:Name="childElement"/>
</MDI:MdiChild>
</MDI:MdiContainer>
</Window>
this solves the primary width & height issue.
This piece of code needs to replace the MdiChild.cs Changeset 81799 resize handler source in WPF.MDI library (you can replace the existing relevant code in there with this):
/// <summary>
/// Handles the DragDelta event of the ResizeLeft control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.Controls.Primitives.DragDeltaEventArgs"/> instance containing the event data.</param>
private void ResizeLeft_DragDelta(object sender, DragDeltaEventArgs e)
{
if (ActualWidth - e.HorizontalChange < MinWidth)
return;
double newLeft = e.HorizontalChange;
if (Position.X + newLeft < 0)
newLeft = 0 - Position.X;
Width = ActualWidth - newLeft;
Position = new Point(Position.X + newLeft, Position.Y);
if (sender != null)
Container.InvalidateSize();
}
/// <summary>
/// Handles the DragDelta event of the ResizeTop control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.Controls.Primitives.DragDeltaEventArgs"/> instance containing the event data.</param>
private void ResizeTop_DragDelta(object sender, DragDeltaEventArgs e)
{
if (ActualHeight - e.VerticalChange < MinHeight)
return;
double newTop = e.VerticalChange;
if (Position.Y + newTop < 0)
newTop = 0 - Position.Y;
Height = ActualHeight - newTop;
Position = new Point(Position.X, Position.Y + newTop);
if (sender != null)
Container.InvalidateSize();
}
/// <summary>
/// Handles the DragDelta event of the ResizeRight control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.Controls.Primitives.DragDeltaEventArgs"/> instance containing the event data.</param>
private void ResizeRight_DragDelta(object sender, DragDeltaEventArgs e)
{
if (ActualWidth + e.HorizontalChange < MinWidth)
return;
Width = ActualWidth + e.HorizontalChange;
if (sender != null)
Container.InvalidateSize();
}
/// <summary>
/// Handles the DragDelta event of the ResizeBottom control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.Controls.Primitives.DragDeltaEventArgs"/> instance containing the event data.</param>
private void ResizeBottom_DragDelta(object sender, DragDeltaEventArgs e)
{
if (ActualHeight + e.VerticalChange < MinHeight)
return;
Height = ActualHeight + e.VerticalChange;
if (sender != null)
Container.InvalidateSize();
}
Upvotes: 1
Reputation: 1382
Assuming you are working with WPF Multiple Document Interface:
If its the MdiChild you need to do the Width-property calculation on then you can bind to the Loaded-Event of the MdiChild-object before you add it to the Container.
var mdiChild = new MdiChild
{
Title = "Window Using Code",
Content = new ExampleControl(),
Width = 714,
Height = 734,
Position = new Point(200, 30)
};
mdiChild.Loaded += new RoutedEventHandler(mdiChild_Loaded);
Container.Children.Add(mdiChild);
void mdiChild_Loaded(object sender, RoutedEventArgs e)
{
if (sender is MdiChild)
{
var width = (sender as MdiChild).Width;
Debug.WriteLine("Width: {0}", width);
}
}
Upvotes: 1
Reputation: 81233
Yeah, ActualWidth
you need to look for. But window's constructor is not the right place to get it since window is not rendered yet
. Instead use Loaded
event -
public DatabaseTableWindow(string tableName, DataTable fields, string primaryKey)
{
InitializeComponent();
this.tableName = tableName;
this.fields = fields;
this.primaryKey = primaryKey;
lblTableName.Content = tableName;
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
double x = this.ActualWidth;
}
EDIT
In place of Loaded
, try hooking to ContentRendered
event in your constructor -
this.ContentRendered += new EventHandler(MainWindow_ContentRendered);
void MainWindow_ContentRendered(object sender, EventArgs e)
{
double x = this.ActualWidth;
}
Upvotes: 2