I was under the impression that listening to the Loaded event will make sure that I can access the visual tree at that point. This seems to work fine in most situations and the visual tree is what I expect it to be. However when using a TabControl, controls on hidden tabs do not get their visual tree constructed before the loaded event fires.
Take this simple example:
<Window ...>
<Grid>
<TabControl>
<TabItem Header="Tab 1">
<my:MyTextBox />
</TabItem>
<TabItem Header="Tab 2">
<my:MyTextBox />
</TabItem>
</TabControl>
</Grid>
</Window>
MyTextBox
is a custom component, that just logs out when certain events occur.
public class MyTextBox : TextBox
{
public MyTextBox()
{
Loaded += (s,e) => {
Console.WriteLine("MyTextBox {0}: Loaded", s.GetHashCode());
Dispatcher.BeginInvoke(()=>Console.WriteLine("MyTextBox {0}: Loaded BeginInvoke", s.GetHashCode()));
};
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Console.WriteLine("MyTextBox {0}: OnApplyTemplate", this.GetHashCode());
}
}
And this is the output:
MyTextBox A: OnApplyTemplate
MyTextBox A: Loaded
MyTextBox B: Loaded
MyTextBox A: Loaded BeginInvoke
MyTextBox B: Loaded BeginInvoke
(changing tab to 2)
MyTextBox B: OnApplyTemplate
MyTextBox B: Loaded
MyTextBox B: Loaded BeginInvoke
As you can see, for B
, which is on the second tab, OnApplyTemplate
is only executed when you switch to its tab, but the loaded event is actually raised before.
The problem is now that my custom component is a look-less component that has its control template set. In the loaded event I now want to go through the visual tree and apply some additional default values, but as the template was not applied yet, the visual tree is empty.
Is there some way, from the outside (i.e. without modifying the component), to make sure that I can iterate through the visual tree as soon as it is loaded?