tags:

views:

134

answers:

2

So I've read that ActualWidth may equal 0 until it is fully loaded. I added the event handler, like so, to make sure it's fully loaded: text.AddHandler(TextBlock.LoadedEvent, new RoutedEventHandler(textBlock_Loaded)); In the textBlock_Loaded event, I have TextBlock tb = sender as TextBlock; textBlockWidth = tb.ActualWidth; I need to use the variable textBlockWidth in my main method, but everytime I write the value of textBlockWidth to output in my Main method, I get 0.

So this question is, how do I ensure that ActualWidth isn't 0 before performing my actions? Since WPF is event-driven, is there a way I can trigger some method when it's done, instead of before? Otherwise, it'll return 0.

+3  A: 

Why store the actual width? Why not store a reference to the control and get the actual width when you really need it?

Having said that I don't see why your code is failing as using the loaded event should be good enough. According to the Object Lifetime Events MSDN page:

The Loaded event is raised before the final rendering, but after the layout system has calculated all necessary values for rendering.

So all the controls should have their final position and size values set. Also:

the Loaded event is raised as a coordinated effort throughout the entire element tree (specifically, the logical tree). When all elements in the tree are in a state where they are considered loaded, the Loaded event is first raised on the root element. The Loaded event is then raised successively on each child element.

ChrisF
I think it fails because the TextBlock's loaded event triggers _after_ my code in Main() that uses it.
DMan
@ChrisF: Maybe "calculated all necessary values for rendering" means only that DesiredSize was calculated?
HCL
+1 store the reference
HCL
@HCL - could be. I couldn't find any more relevant information on that page or links that would explain that fully.
ChrisF
Can you tell me how I should store a reference to the control?
DMan
+2  A: 

You won't be able to get the ActualWidth. Since, it will not be updated at the time of loaded. So, you should use Dispatcher of the TextBlock or it's Parent to get the ActualWidth or ActualHeight.

this.textBlock.Dispatcher.BeginInvoke((Action)(() =>
            {
                textBlock = this.textBlock.ActualWidth;
            }));

HTH

Avatar
I've already tried an approach like this- but my problem is that it never is loaded when I need it. After I called this in my main and set the ActualWidth into a variable, I proceeded to use this variable (in my main method). It will still return zero, as it still wasn't loaded yet.
DMan
It should be working. Instead of control's dispatcher could you please try the parent windows dispatcher. That would help it looks.Like, this.Dispatcher.BeginInvoke((Action)... http://stackoverflow.com/questions/2452246/how-to-invoke-wpf-dispatcher-in-nunit
Avatar
My code is like this: `this.Dispatcher.BeginInvoke((Action)(() =>` `{` `Console.WriteLine(this.label1.ActualWidth);` `}));` `Console.WriteLine("Her");` 'Her' outputs to console before the actualwidth.
DMan
Hi DMan, I tried like this, inside the window Loaded event everything is fine. ` this.Loaded += (s, e) => { this.Dispatcher.BeginInvoke((Action)(() => { Console.WriteLine(this.textBlock.ActualWidth); Console.WriteLine("Her"); })); }; `
Avatar
Thanks, this worked!
DMan
Glad to know :)
Avatar