10

I am working on an application which includes a registration form. The form contains multiple text entry boxes, and so a ScrollViewer is used to allow them all to be displayed on one page.

The following is a stripped down example of the XAML code I am using:

<Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
        <TextBlock x:Name="ApplicationTitle" Text="SCROLLVIEWER TEST" Style="{StaticResource PhoneTextNormalStyle}"/>
        <TextBlock x:Name="PageTitle" Text="registration" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
    </StackPanel>

    <ScrollViewer Grid.Row="1">
        <StackPanel>
            <TextBlock Text="Hello" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello1" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello2" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello3" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello4" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello5" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello6" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello7" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="Hello8" Margin="12,0,0,0"/>
            <TextBox />
            <TextBlock Text="END" Margin="12,0,0,0"/>
            <TextBox />
        </StackPanel>
    </ScrollViewer>
</Grid>

(Note that the ScrollViewer is inside a grid cell, which means that the title panel should stay OnScreen at all times)

The scrolling works perfectly fine, so that is not an issue. However, when the user selects a TextBox to enter data (i.e. the soft keyboard opens), the system pushes the content of the entire page around (including the registration title panel), which is not expected behaviour. [See the People app on Windows Phone and try adding a new contact. This contains a similar structure, but the ScrollViewer behaves correctly by only pushing content in the scrollviewer up]

Test Cases

  • Select a TextBox that is visible near the top of the screen, to open the keyboard.
  • Attempt to scroll to the bottom of the page with keyboard open.
  • Items at the bottom of the page are unreachable.

or

  • Select a TextBox that is visible near the bottom of the screen.
  • Content of entire page is pushed up.
  • Attempt to scroll to the top of the page with keyboard open.
  • Items at the top of the page are unreachable, and title panel never comes back into view until keyboard is closed.

Any help on resolving this issue would be appreciated. Thanks.

Jason H
  • 306
  • 1
  • 6
  • The following blog post might be a good starting point to solve this : http://sorokoletov.com/2011/08/windows-phone-70-handling-text-entry-screens/ – Paul Diston May 02 '12 at 11:49
  • @PaulDiston Thanks. I have read this blog before. I did try the demo app and it is not what I am looking for. The transition is very abrupt (i.e. the title panel just re-appears when the SIP animation finishes), not to mention that the implementation is excessive for something so simple. My intended implementation is to match that of the contact details forms that you find in the "People" app that is included on Windows Phone 7 for managing contacts and addresses. This not not a complicated example, and one would expect this to work out of the box and not cover the items in the form. – Jason H May 02 '12 at 12:06
  • Try this too if it can help with the scrolling issue. http://www.luisleo.net/2012/06/24/how-to-use-listbox-properly-with-windows-phone-7/ – 123 456 789 0 Jul 07 '12 at 16:10

4 Answers4

0

The problem is that the ScrollViwer height is not modified after the keyboard appears so it becomes clipped. One solution would be to modify the height of the scrollviwer (according to the keyboard height) and then reposition it (this might give you some headaches).

Another problem is knowing when the keyboard appears - you could register for the GotFocus/LostFocus events on all your TextBoxes but it's not a great solution. This might help you: http://blogs.msdn.com/b/jaimer/archive/2010/11/05/guessing-if-the-sip-is-visible-in-a-windows-phone-application.aspx

Hope this helps a little :)

Spiri
  • 1,283
  • 11
  • 24
  • Sounds like plausible hack. However, this only works if you select a box at the top of the screen (when the content at the bottom of the scrollviewer would be obscured). The text boxes physical position on the screen affects how much the page is pushed up. So if it's at the top, the content is only pushed up marginally. If it is at the bottom, the content is pushed up very far. As far as I know, it is impossible to determine how much the page is adjusted, meaning it is difficult to tidily compensate for this. Also the title pane will continue to be pushed off screen, which is not ideal. – Jason H Dec 25 '12 at 14:13
0

I think you can solve this by coming at the problem from another angle. The phone will scroll up the page so that the SIP (software keyboard) never covers up the TextBox which has focus.

However you can force the SIP to hide by detecting touch events on the top element contained in your ScrollViewer, e.g.:

<ScrollViewer Grid.Row="1">
    <StackPanel ManipulationDelta="OnScrollViewerGridManipulationDelta">`

Then, by giving the focus to a hidden button (0x0 pixels in size) this will force the SIP to close. Then it will be possible for your users to scroll up and down the scrollviewer as expected...

    private void OnScrollViewerGridManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
    {
        // This will hide the SIP if it is currently showing. 
        // We can't do this directly, but we can force this by taking focus away from any of the TextBoxes that may have it.
        this.hiddenButton.Focus();
    }
Paul Annetts
  • 9,554
  • 1
  • 27
  • 43
  • You can just call this.Focus() in the code behind to give focus to the Page to hide the SIP. There's no need to create an extra hidden object. – Styff Apr 05 '13 at 14:06
0

I've had the same issue with an app I've developed and the way I dealt with it was to find out the auto height of the panel containing the input textboxs and then manually set the height and add approximately 400 - 500 px to the bottom to make it scroll nicely. The effect is quite smooth and will not make your UI look "hackish" IMHO.

In your case you will have to find out the automatic height of the LayoutRoot Grid and then on RowDefinitionof Row 1 set the height manually - remembering to add an extra 400px (or whatever looks appropriate in your situation).

For ease of input I then handled each OnKeyDown event of each TextBox to change the focus to the next TextBox upon hitting Enter. On the last TextBox I set the focus to this.focus() which sets focus to the Page and hides the SIP.

Styff
  • 113
  • 1
  • 9
0

Have a look at my small library please - https://siphelper.codeplex.com/

It modifies height of scrollviewer and content can be scrolled to the topmost/bottommost point.

If you have any suggestions - feel free to contact me.

Grigory
  • 1,911
  • 1
  • 16
  • 29