Tech Off Thread

25 posts

Finding height/width of wpf control

Back to Forum: Tech Off
  • User profile image
    kaul

    I have a textblock (wpf) which is being declared, initialized and filled-in programmatically (code behind).Because of some constraints I can't give this control a fixed size (I have declared minheight, maxheight and minwidth, maxwidth). I want to measure the height of the control after the text has been inserted but what I am getting is NaN. How can the exact height/width can be determined? 

    Alternatively can I determine height/width of the text in a line (assuming wrapping is enabled and font is same) can be determined?

  • User profile image
    footballism

        Actually you can query the TextBlock's ActualHeight and ActualWidth property to get the actual size which WPF layout engine assigns to your TextBlock, WPF has a very capable layout system, the actual size of  controls in WPF is finally determined by the layout, not by the properties set on them.

    Sheva

  • User profile image
    kaul

    Thanks for replying, but the problem is that the AbsoluteHeight/AbsoluteWidth property is showing control's height and width '0'. Whereas I am sure that the control exists and contains text.   

  • User profile image
    footballism

    Just test this xaml snippet, and see what prints out:

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
      <StackPanel>
        <TextBlock Text="Windows Presentation Foundation" Name="textBlock"/>
        <Label Content="{Binding Path=ActualWidth, ElementName=textBlock}"/>
        <Label Content="{Binding Path=ActualHeight, ElementName=textBlock}"/>
        <Label Content="{Binding Path=Width, ElementName=textBlock}"/>
        <Label Content="{Binding Path=Height, ElementName=textBlock}"/>
      </StackPanel>
    </Page>

    Sheva

  • User profile image
    kaul

    Thanks for ypur concern towards my problem, I got what you are trying to say, please see the following snippet for understanding my version-

    private void Test()

    {

    TextBlock tb = new TextBlock();

    tb.TextWrapping = TextWrapping.Wrap;

    tb.MaxHeight = 200;

    tb.MinHeight = 10;

    tb.MaxWidth = 100;

    tb.MinWidth = 100;

    tb.Text = "sahf ivdahy;fyia yiyficvaysdfyilaysilyfiluyhsdfylia asdafsbgtgsrgtyvteryhifl aybisyfi a";

    MessageBox.Show(tb.ActualHeight.ToString());

    spnl.Children.Add(tb);

    }

    spnl is any stackpanel I am using to display the textblock.

  • User profile image
    TommyCarlier

    What do you get if you ask the ActualHeight AFTER adding it to spnl?

  • User profile image
    kaul

    I get 0 (zero) no matter where I place the messagebox.Sad 

  • User profile image
    trun_gup

    May be you can use another function in which you can find out the actual height of textblock.

  • User profile image
    kaul

    I couldn't get you trun_gup please clarify.

  • User profile image
    trun_gup

    i trie it myself, it is still giving NaN, if give height or width as Auto and check it at runtime, may be we can count \r\n, but then again i am not sure 

  • User profile image
    kaul

    Thanks Sheva, for showing so much interest in my problem and for replying soon. I have following query Expressionless , hope you won't mind answering this one as well -

     The StackPanel control does not have the BeginInvoke() method.

     

  • User profile image
    footballism

        Hi, Kaul, the problem with your code is that you instantiate a textblock in the Test method, and you check its size immediately in the same method block, so there is no wonder why you ain't get the correct size value, the thing here is that when you instantiate a TextBlock, you should give the WPF layout engine an opporntunity to calculate the actual size for the newly instantiated TextBlock, but the WPF dispatcher is currently running in your method body, it cannot do the layout at the same time when it is still running inside the current method block, actually if you want to get the actual size of the newly instantiated TextBlock, you should do something like this in the Test method body:

                TextBlock tb = new TextBlock();
                tb.TextWrapping = TextWrapping.Wrap;
                tb.MaxHeight = 200;
                tb.MinHeight = 10;
                tb.MaxWidth = 100;
                tb.MinWidth = 100;
                tb.Text = "sahf ivdahy;fyia yiyficvaysdfyilaysilyfiluyhsdfylia asdafsbgtgsrgtyvteryhifl aybisyfi a";
                spnl.Children.Add(tb);
                spnl.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(Object state)
                {
                    MessageBox.Show(tb.ActualHeight.ToString());
                    return null;
                }), null);


       Sheva

  • User profile image
    footballism

    Sorry, bad typo, it shoud be:

    spnl.Dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(Object state)
    {
    	MessageBox.Show(tb.ActualHeight.ToString());
    	return null;
    }), null);

    Sheva

  • User profile image
    trun_gup

     it worked perfectly
    Big Smile

  • User profile image
    kaul

    Thanks Sheva.

    Smiley

  • User profile image
    kaul

    The snippet (above) works fine if the stackpanel (spnl) is child of some wpf control (i.e. code gives the actualheight when it's rendered on the xaml page.), if the stackpanel (spnl) is not child of any wpf control the code fails to give the desired output.

    My problem is that I don't have any xaml page associated with it as it's a class being used to create visuals. 

    Sorry for this delayed response, but I tried it just now after coming back from weekend.
    Sad   

  • User profile image
    footballism

        Hey, kaul, what you are trying to do is that you just want to know the actual size of the specified WPF control without adding it to the visual tree or even logical tree, right?
        Well, the problem is that WPF has a very sophisticated layout engine, to put it simple, WPF use two passes of layout operations to calculate the atual size and location of the child controls, they are Measure, and Arrange, Measure pass is responsible for figuring out how large the child control is desired to be, and the Arrange pass is finally responsible for positioning the control on the screen, and in the arrange pass, the actual size of the control is returned, and all those layout operations first happens on the root visual, typically its a Window, and immediately after the root visual, it will call the two passes of layout operations down the visual tree recursively on the child elements if they are present. so only if you add the control to the visual tree, its actual size can be calculated, and returned.

    Sheva

  • User profile image
    kaul

    Thanks again for replying to my problem, this time I got the point where I was making the mistake..and the solution (to use measure and arrange methods) did helped me finding a proper solution to this problem.
    Thanks again for your help.

    Regards,
    Sudeep Kaul

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.