Preventing the Pivot or Panorama controls from scrolling


The Panorama and Pivot are great, defining assets of the Windows Phone 7 user experience. Their main role is to display a wealth of information panning horizontally, and eventually enable item selection. Even though these controls are not designed to handle complex user input, you may stumble upon some scenarios where it might be necessary.

If you encounter such a scenario you will undoubtedly notice that the Panorama/Pivot will always take precedence when it comes to handling the panning manipulations. For example, placing a cursor within a TextBox will cause the hosting Panorama/Pivot to pan horizontally as the finger moves left or right to place the cursor. For the exact same reason Sliders and ToggleSwitches tend do not behave as expected.

image

I have implemented the BlocksPan.IsEnabled attached property to address this scenario. Setting it to true on a control makes any manipulation on the control block the panning of the hosting Panorama/Pivot. The usage is straightforward:

<controls:Panorama Title="MY APPLICATION" x:Name="panorama">

  <controls:PanoramaItem Header="First item">

    <TextBox pcExt:BlocksPan.IsEnabled="True" Text="This textbox blocks the panning"/>

Technically, the idea is to make the parent Panorama/Pivot invisible to hit test when a manipulation is started on a child control where this attached property is set. You can find the source code and an example attached to this post.

Note: Allowing complex user input within a Panorama or a Pivot is not a recommended UX practice on Windows Phone, furthermore expecting horizontal manipulations on controls hosted in a Panorama/Pivot results in an “ergonomic ambiguity”. This extension is only intended to target the few scenarios where creating another dedicated level of navigation does not make sense.

WP7BlocksPan.zip

Comments (16)

  1. BorisFR says:

    Really great ! Thanks a lot. I've test with Bingmap control and it is really a pleasure now.

  2. Tim says:

    Great thanks. It seems not working when using the GestureListener of the phone control toolkit. If I use :

    <Canvas Grid.Row="2" Width="400" Height="300" Background="Yellow" local:BlocksPan.IsEnabled="True">

      <toolkit:GestureService.GestureListener>

         <toolkit:GestureListener Flick="GestureListener_Flick" />

      </toolkit:GestureService.GestureListener>

    </Canvas>

    it never raise the GestureListener_Flick event.

    How can I correct this ?

  3. PokerDIY says:

    Interesting – we had a discussion on the recommended best practices for this: stackoverflow.com/…/4275001.

  4. payini says:

    Very Cool! Thanks.

  5. Drew DeVault says:

    This works great when the user is dragging their finger across the screen from left to right, but not the reverse.  Any suggestions to solve this?

  6. Greg Bray says:

    I had a similar problem where it was difficult to enter text into a textbox on a pivot control. I only had a few pages, so I ended up removing the other pivot pages when the textbox received focus and adding them back when it lost focus. Example:

    private void txtResult_GotFocus(object sender, RoutedEventArgs e)

    {

               //Disable ability to move to another page or use application bar

               pvtRoot.Items.Remove(pvtSendTo);

               pvtRoot.Items.Remove(pvtSettings);

               pvtRoot.Items.Remove(pvtHistory);

               ApplicationBar.IsVisible = false;

    }

    private void txtResult_LostFocus(object sender, RoutedEventArgs e)

    {

               //Re-Enable ability to move to another page or use application bar

               ApplicationBar.IsVisible = true;

               if (!pvtRoot.Items.Contains(pvtSendTo)) {

                   pvtRoot.Items.Add(pvtSendTo);

               }

               if (!pvtRoot.Items.Contains(pvtSettings))

               {

                   pvtRoot.Items.Add(pvtSettings);

               }

               if (!pvtRoot.Items.Contains(pvtHistory))

               {

                   pvtRoot.Items.Add(pvtHistory);

               }

    }

  7. Hannes Granat says:

    hmm, your example works great, when trying to implement this on my BING map control in an panorama i get the following error: "The attachable property 'IsEnabled' was not found in type 'BlocksPan'"

    Any clues?

  8. Hannes Granat says:

    no problem, after a rebuild it works 🙂 thanks man…

  9. Mike says:

    Hi this works great, and thanks for the solution.  The only problem is that this works for left and right gestures, but not for up and down.  When dragging up or down, the page scrolls.  One example is using a color picker in a pivot.  The user will naturally try to drag a point in the color picker, and the page will scroll if they drag up or down.

  10. Lee says:

    Hi, how to set the property isEnable in background(.cs File)?

  11. resul says:

    Thank you, great work!

  12. Alex says:

    Worked on WP7, does not work on WP8.

  13. Jcrada says:

    Genious!

  14. Robert says:

    @alex: did you find a solution that works for WP8 ???

  15. Evg says:

    Don't work, because static FrameworkeElement property (if (property == null),  it's static – never null) – throw ArgumentExeption

  16. Herberth Madrigal (hmadrigal) says:

    I was able to use a ToggleSwitch into a Panorama Item just by following this advice.

    stackoverflow.com/…/preventing-swiping-between-pivot-elements