While investigating an issue with application I'm working on, I've came across one behavior I don't quite understand. It seems that when you have a TextBox (for example) with bound Text property the system takes one more layout pass than when you have a static Text.
Could anyone, please, explain why this extra pass is happening? Does the engine lay the unbound control first then binds it and then lays it once again?
To test this I've built such test case:
I've declared a class inherited from TextBox (so I can override ArrangeOverride):
public class MultiBoundTextBox : TextBox
{
protected override Size ArrangeOverride(Size arrangeBounds)
{
Console.WriteLine("TextBox.Arrange");
return base.ArrangeOverride(arrangeBounds);
}
}
Then I placed an instance of this text box in a window:
<local:MultiBoundTextBox x:Name="tb">
Some text
</local:MultiBoundTextBox>
And added some code for the window for testing:
public Window11()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("Window.Loaded");
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
Console.WriteLine("Window.Arrange");
return base.ArrangeOverride(arrangeBounds);
}
private void Window_Initialized(object sender, EventArgs e)
{
Console.WriteLine("Window.Initialized");
tb.DataContext = DateTime.Now;
}
Now when I run this I get this output:
Window.Initialized
Window.Arrange
TextBox.Arrange
Window.Arrange
Window.Loaded
But if I change Text property to be bound like this:
<local:MultiBoundTextBox x:Name="tb">
<Binding Path="Day" Mode="OneWay" />
</local:MultiBoundTextBox>
I get this in the output:
Window.Initialized
Window.Arrange
TextBox.Arrange
Window.Arrange
TextBox.Arrange
Window.Arrange
Window.Loaded
Notice the extra pair of TextBox.Arrange and Window.Arrange. Why is this extra pass necessary?