I was updating my sample on how to simulate a Window environment in Silverlight, after having implemented some fixes to the resize functions and having added the support for scrollbars inside a window, I realized a simple test form with a series of textboxes.

During the horizontal resize operation I encountered a very strange behavior: only the first textbox changed its width according to the new windows size...while all the others retained their previous value; when you start a vertical resize operation all the textboxes were redrawn with the correct width.

To be sure it wasn’t my control template’s fault and to try to reproduce this situation I prepared a simple test page, something like:

   1: <ScrollViewer x:Name="ScrollBox" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
   2:  
   3:     <StackPanel MinWidth="300" x:Name="ScrollContent">
   4:         <TextBlock>TextBoxes</TextBlock>
   5:         <TextBox Margin="0,2,0,2" x:Name="t1" />
   6:         <TextBox Margin="0,2,0,2" x:Name="t2" />
   7:         <my:MyTextBox Margin="0,2,0,2" x:Name="mt1" />
   8:         <my:MyTextBox Margin="0,2,0,2" x:Name="mt2" />
   9:         <TextBlock>PasswordBoxes</TextBlock>
  10:         <PasswordBox />
  11:         <PasswordBox />
  12:         <TextBlock>Buttons</TextBlock>
  13:         <Button Content="BTN1" />
  14:         <Button Content="BTN2" />
  15:     </StackPanel>
  16:  
  17: </ScrollViewer>

Some controls inside a ScrollViewer with both scrollbars set on Auto (you can download the whole code at the end of the article). If you open this page in a small browser window and the you resize it horizontally you can see what I was talking about:

ScrollViewControlLayoutBug1 ScrollViewControlLayoutBug2

As an information it seems that the layout arrange operations aren’t performed for the controls that follow the first one inside the children collection of the StackPanel; to see that I have just derived a new TextBox class and overridden the default behavior of the protected ArrangeOverride() function to report in the debug window some information regarding the size of the controls. If you run the example you can see that we have logs only for the first control inside the StackPanel.

I was able to find a workaround for this and it is to set explicitly the size of the first container inside the ScrollViewer: we ca write some code for the ScrollViewr’s SizeChanged() event in which we set the dimensions of the contained element, here’s the snippet.

   1: void ScrollBox_SizeChanged(object sender, SizeChangedEventArgs e)
   2: {
   3:      ScrollContent.Width = Math.Max(ScrollBox.ViewportWidth - 1.0, 0);
   4: }

I have also added a small offset to avoid another graphic artifact: sometimes during shrink operations a disabled horizontal scrollbar used to appear, making the container a little smaller avoid this problem.

I have to admit I haven’t done the same tests in WPF yet.

Example Solution:

 

 

Related Content