none
WP8.1 Map Control: How to prevent user scrolling and zooming RRS feed

  • Question

  • Using the WP8.1 map control (Windows.UI.Xaml.Controls.Maps) how can I prevent the user from scrolling and panning the map?  I've tried the following without success:

    • Setting Map.IsEnabled to false.
    • Hooking the Map.ManipulationStarting event and calling CancelDirectManipulations()
    • Setting Map.ManipulationMode = ManipulationModes.None;

    But none of these seem to prevent the user from altering the map view.

    Thursday, July 10, 2014 12:53 AM

Answers

  • There are two ways to do this. The first method is to make use of events and override the pan and zooming functions like this:

    var c  = MyMap.Center;
    MyMap.CenterChanged += (s, e) =>
    {
        if (!MyMap.Center.Equals(c))
        {
            MyMap.Center = c;
        }
    };
    
    var z = MyMap.ZoomLevel;
    MyMap.ZoomLevelChanged += (s, e) =>
    {
        if (MyMap.ZoomLevel != z)
        {
            MyMap.ZoomLevel = z;
        }
    };

    This does suffer from the same "jumpy" experience you noticed with overriding the heading.

    Another, more simple option is to put something in front of the map to catch the touch events. The following using a canvas that is pretty much invisible to catch the events.

    <Grid>
        <m:MapControl Name="MyMap"/>
        <Canvas Background="Black" Opacity="0.01"/>
    </Grid>

    http://rbrundritt.wordpress.com

    Thursday, July 10, 2014 10:08 AM

All replies

  • There are two ways to do this. The first method is to make use of events and override the pan and zooming functions like this:

    var c  = MyMap.Center;
    MyMap.CenterChanged += (s, e) =>
    {
        if (!MyMap.Center.Equals(c))
        {
            MyMap.Center = c;
        }
    };
    
    var z = MyMap.ZoomLevel;
    MyMap.ZoomLevelChanged += (s, e) =>
    {
        if (MyMap.ZoomLevel != z)
        {
            MyMap.ZoomLevel = z;
        }
    };

    This does suffer from the same "jumpy" experience you noticed with overriding the heading.

    Another, more simple option is to put something in front of the map to catch the touch events. The following using a canvas that is pretty much invisible to catch the events.

    <Grid>
        <m:MapControl Name="MyMap"/>
        <Canvas Background="Black" Opacity="0.01"/>
    </Grid>

    http://rbrundritt.wordpress.com

    Thursday, July 10, 2014 10:08 AM
  • Thought experiment: I'm trying to imagine using the second option of with a canvas over the map as a workaround...

    Let's imagine the user is manually repositioning waypoint icons.  If the touch point is close to a waypoint, then the waypoint gets dragged, and if the touchpoint is far from an existing waypoint then the map gets dragged.  I can imagine passing messages from the canvas through to manipulate the map for simple dragging like this.

    But will this strategy work for multitouch events like rotation, two finger drag for pitch control, and the like?  What about double tap?  Do any examples exist for dragging objects on the map?

    Even if this strategy could be made to work, it seems WAY MORE COMPLICATED than having a simple Boolean added to the map control which says "disable movement".  This is the way previous MSFT map controls have worked, and they were quite usable for these kinds of scenarios.

    If this scenario is unsupportable, it's a showstopper preventing me from using the map control.

    Sunday, July 20, 2014 4:53 AM
  • Actually, you could add the canvas to the map (make it the same size of the map and don't specify position) before any pushpins and add a bunch of touch events to catch them before they hit the map. You would then be able to touch the pushpins as they would be added to the map after the canvas and touchable.

    http://rbrundritt.wordpress.com

    Monday, July 21, 2014 8:48 AM
  • // gj microsoft, really
            private void ForceSetView(Geopoint center, double? zoomLevel=null, double? heading=null, double? desiredPitch=null, MapAnimationKind animationKind = MapAnimationKind.Default)
            {
                map.TrySetViewAsync(center, zoomLevel, heading, desiredPitch, animationKind).AsTask().ContinueWith((t) =>
                {
                    if (t.IsCanceled || !t.Result)
                    {
                        ForceSetView(center, zoomLevel, heading, desiredPitch, animationKind);
                    }
                });
            }
            private void ForceSetViewBounds(GeoboundingBox box, Thickness thickness, MapAnimationKind linear)
            {
                map.TrySetViewBoundsAsync(box, thickness, linear).AsTask().ContinueWith((t) =>
                {
                    if (t.IsCanceled || !t.Result)
                    {
                        ForceSetViewBounds(box, thickness, linear);
                    }
                });
            }
    
    If you need this to block user interaction while animate-viewing ..


    • Proposed as answer by n00b64 Wednesday, April 27, 2016 1:43 AM
    • Unproposed as answer by n00b64 Wednesday, April 27, 2016 1:44 AM
    • Edited by n00b64 Wednesday, April 27, 2016 1:45 AM
    Wednesday, April 27, 2016 1:42 AM