【问题标题】:Bing maps resizable polygonBing 映射可调整大小的多边形
【发布时间】:2012-10-02 11:31:37
【问题描述】:

我正在尝试实现用户在 Bing 地图控件上绘制和优化多边形的功能。

我添加了一个形状图层,并覆盖了点击事件以绘制一个简单的多边形,这一切都完美无缺。我想进一步完善控件,以便用户可以拖放所绘制多边形的任何 Location 对象以改变其形状,但我没有任何运气。

我尝试添加一个 MapItemControl,绑定到我的多边形的 Locations 属性,但没有成功 - 我看不到图钉出现在地图上,即使我的多边形渲染正确。大概 Locations 集合不会通知 UI 集合的任何更改,因此我可能必须为这些图钉维护一个单独的集合。

然而,一旦我开始这样做,我仍然需要能够拖放引脚来修改多边形。有没有人在 Windows 8 上实现了这个,可以分享一些想法吗?

编辑

现在我的图钉在地图上显示了 Locations 集合。理想情况下,我希望将这些与多边形的 Locations 集合联系起来,但乞丐不能成为选择者。我现在只需要能够拖动别针。

【问题讨论】:

    标签: xaml windows-8 bing-maps


    【解决方案1】:

    我向多边形添加了一个拖动手柄模块,以便编辑多边形中的每个点。这是我使用的演练。

    Drag Handle Module

    这是针对 7.0 版的。不确定您使用的是哪个版本,但它很容易适应。

    编辑我是在 javascript/html 中完成的。刚刚注意到您将其标记为 windows 8。好奇,您是在为 windows 8 手机制作银光控件吗?

    WPF C# 解决方案

    这是我想出的,它很容易实现,你需要做的就是把我的事件挂到你的MapPolygon对象上。代码背后的想法是,一旦您单击多边形,我们就会在多边形的每个顶点放置一个图钉(我们创建事件以便我们可以拖动它)。当我们拖放每个图钉时,我们会根据需要调整多边形。位置。

    polygon.MouseDown += new MouseButtonEventHandler(polygon_MouseDownResize);
    

    还有一种退出调整大小事件的方法,我选择只挂上键并使用“esc”停止编辑,但您可以通过右键单击或您选择的任何其他事件来执行此操作。您所做的只是清除pushPinVertices 列表并重置事件变量。

    // === Editable polygon Events ===
    
    private bool _shapeEdit;
    public MapPolygon selectedPoly { get; set; }
    public List<Pushpin> pushPinVertices { get; set; }
    
    
    void polygon_MouseDownResize(object sender, MouseButtonEventArgs e)
    {
    
        if (!_shapeEdit && selectedPoly == null)
        {
            _shapeEdit = true;
            selectedPoly = sender as MapPolygon;
            pushPinVertices = new List<Pushpin>();
            int i = 0;
            foreach (Microsoft.Maps.MapControl.WPF.Location vertice in selectedPoly.Locations)
            {
                Pushpin verticeBlock = new Pushpin();
                // I use a template to place a 'vertice marker' instead of a pushpin, il provide resource below
                verticeBlock.Template = (ControlTemplate)Application.Current.Resources["PushPinTemplate"];
                verticeBlock.Content = "vertice";
                verticeBlock.Location = vertice;
                verticeBlock.MouseDown += new MouseButtonEventHandler(pin_MouseDown);
                verticeBlock.MouseUp += new MouseButtonEventHandler(pin_MouseUp);
                myMap.Children.Add(verticeBlock);
                pushPinVertices.Add(verticeBlock);
                i++;
    
            }
        }
    
    }
    
    
    
    private void myMap_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == System.Windows.Input.Key.Escape)
        {
            if (_shapeEdit && selectedPoly != null)
            {
    
                foreach (Pushpin p in pushPinVertices)
                {
                    myMap.Children.Remove(p);
                }
    
                _shapeEdit = false;
                selectedPoly = null;
    
            }
    
        }
    }
    // Note: I needed my window to pass bing maps the keydown event
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        myMap_KeyDown(sender, e);
    }
    
    
    // === Editable polygon Events ===
    
    // ==== Draggable pushpin events =====
    Vector _mouseToMarker;
    private bool _IsPinDragging;
    public Pushpin SelectedPushpin { get; set; }
    
    void pin_MouseUp(object sender, MouseButtonEventArgs e)
    {
        LocationCollection locCol = new LocationCollection();
        foreach (Pushpin p in pushPinVertices)
        {
            locCol.Add(p.Location);
    
        }
    
        selectedPoly.Locations = locCol;
        bingMapRefresh();
    
        _IsPinDragging = false;
        SelectedPushpin = null;
    }
    
    void pin_MouseDown(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
        SelectedPushpin = (Pushpin)sender;
        _IsPinDragging = true;
        _mouseToMarker = Point.Subtract(
            myMap.LocationToViewportPoint(SelectedPushpin.Location),
            e.GetPosition(myMap));
    
    }
    
    private void myMap_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            if (_IsPinDragging && SelectedPushpin != null)
            {
                SelectedPushpin.Location = myMap.ViewportPointToLocation(Point.Add(e.GetPosition(myMap), _mouseToMarker));
                e.Handled = true;
            }
        }
    }
    // ==== Draggable pushpin events =====
    // Nice little maprefresh I found online since the bingmap WPF doesnt always seem to update elements after certain event orders
    private void bingMapRefresh()
    {
        //myMap.UpdateLayout();
        var mapCenter = myMap.Center;
        mapCenter.Latitude += 0.00001;
        myMap.SetView(mapCenter, myMap.ZoomLevel);
    }
    

    至于覆盖图钉图标的资源,我只是使用了ImageBrush 并做了一个白色的小方块。请注意,您可能需要调整 Margin 属性,具体取决于您制作标记的长度/宽度。这是因为通常图钉默认锚定在该位置上方。

    <Application.Resources>
        <ControlTemplate x:Key="PushPinTemplate">
            <Grid>
                <Rectangle Width="10" Height="10" Margin="0 35 0 0">
                    <Rectangle.Fill>
                        <ImageBrush ImageSource="pack://application:,,,/Images/DragIcon.gif"/>
                    </Rectangle.Fill>
                </Rectangle>
            </Grid>
        </ControlTemplate>
    </Application.Resources>
    

    【讨论】:

    • 我没有指定,但我在 Windows 8 中使用 XAML/C#。不过,感谢您对 JS 版本的提醒。
    • @ZombieSheep 抱歉刚刚注意到这一点,你还需要帮助吗?我刚自己移植到 xaml / c# :) 我的代码正在工作,但是 lmk,这比拖动句柄模块要容易得多。跨度>
    • 我现在不需要这个,但无论如何请发布,我相信它以后会帮助我,或者帮助别人。 :)
    • @ZombieSheep 为你发布了它:)
    猜你喜欢
    • 1970-01-01
    • 2011-01-22
    • 1970-01-01
    • 2016-06-16
    • 2014-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    相关资源
    最近更新 更多