Dot NET
Dot NET

Reputation: 4897

Unable to get window width

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

Answers (4)

Maverik
Maverik

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

pdvries
pdvries

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

ZSH
ZSH

Reputation: 913

try snoop the window and go over the tree to see the values

snoop

Upvotes: 0

Rohit Vats
Rohit Vats

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

Related Questions