更新Silverlight bing贴图控件上的图钉位置

时间:2012-04-04 20:50:37

标签: silverlight windows-phone-7 bing-maps

我的问题是关于在Windows Phone 7中使用bing map。以下是我需要做的总结

  • 每隔x秒轮询一次服务以检索一组坐标
  • 如果这是第一次轮询服务

    • 将这些坐标绘制为地图上的自定义图钉(我正在使用Image和MapLayer)

      PinObject pin = new PinObject() //Custom object
                      {
                          Id = groupMember.Id,
                          PushPin = new Image()
                          {
                              Source = new System.Windows.Media.Imaging.BitmapImage(new Uri("blackpin.png", UriKind.Relative)),
                              Opacity = 0.8,
                              Stretch = System.Windows.Media.Stretch.None
                          },
                          PinLocation = new GeoCoordinate(groupMember.Latitude, groupMember.Longitude)
                      }; 
      imageLayer.AddChild(pin.PushPin, pin.PinLocation); //Initialized in constructor
                      pinObjects.Add(pin);// Add pin object to a list to provide a handle to the objects
      
    • 自动设置地图缩放级别,以便所有绘制的点都可见(我假设使用LocationRect.CreateLocationRect应该这样做)

                  var coords = pinObjects.Select(p => p.PinLocation).ToList();                        
                  myMap.SetView(LocationRect.CreateLocationRect(coords));
      
    • 否则根据获得的新坐标,更新地图上每个图钉的位置 PinObject pObj = pinObjects.FirstOrDefault(p => p.Id == groupMember.Id);

       MapLayer.SetPosition(pObj.PushPin, new GeoCoordinate(groupMember.Latitude, groupMember.Longitude));
      

引脚加载fiine和调用服务以使他们的新位置加载也很好,问题是他们在地图上的位置永远不会更新所以基本上他们只是坐着不动即使所有这些工作都在进行中背景,我调试了所以我知道它的工作原理。如何重置引脚的位置,如果使用图像不起作用,我可以使用图钉对象吗?这怎么样?

提前致谢。

3 个答案:

答案 0 :(得分:0)

我发现确保图钉更新的最佳方法是再次在地图上调用SetView()。您可以传入现有视图以基本上强制刷新。例如; MyMapControl.SetView(MyMapControl.BoundingRectangle);

答案 1 :(得分:0)

这是一个类似于Dispatcher.BeginInvoke的选项,但在某些情况下它对我来说效果更好。当我真的需要通过一些工作来摆脱当前线程时,我将使用私有静态类UICallbackTimer来稍微偏移执行。 (拼写错误和未经测试的代码,只需在此处删除部分,您必须在代码中进行调试)

UICallbackTimer不是我的代码,但它可以在Internet上找到。您可以通过搜索“private static class UICallbackTimer”

来获取有关此类的信息

以下是执行它的代码。

UICallbackTimer.DelayExecution(TimeSpan.FromSeconds(.01),
                                       () => (

MapLayer.SetPosition(pObj.PushPin,new GeoCoordinate(groupMember.Latitude,groupMember.Longitude))

);

这里是类(我将它放在当前对象中,因此它对我的类保持私有)为System.Threading添加using语句

private static class UICallbackTimer
    {
        private static bool _running = false;
        private static int runawayCounter = 0;

        public static bool running()
        {
            if (_running && runawayCounter++ < 10)
                return _running;

            runawayCounter = 0;
            _running = false;
            return _running;
        }

        public static void DelayExecution(TimeSpan delay, Action action)
        {
            _running = true;
            System.Threading.Timer timer = null;
            SynchronizationContext context = SynchronizationContext.Current;
            timer = new System.Threading.Timer(
                (ignore) =>
                {
                    timer.Dispose();
                    _running = false;
                    context.Post(ignore2 => action(), null);
                }, null, delay, TimeSpan.FromMilliseconds(-1));
        }
    }

答案 2 :(得分:0)

很棒的问题!

这是一些 realllly 丑陋的代码,但至少它的工作和起点。

我从here获得了主要结构。如果有人能够以适当的约束力和更少的代码发布答案,我将不胜感激。

 <Grid x:Name="LayoutRoot" Background="Transparent">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <!--RESOURCES-->
    <Grid.Resources>
        <DataTemplate x:Key="LogoTemplate">
            <maps:Pushpin Location="{Binding PinLocation}" />
        </DataTemplate>
        <maps:MapItemsControl x:Name="GroupAPins"
                    ItemTemplate="{StaticResource LogoTemplate}"
                    ItemsSource="{Binding PinsA}">
        </maps:MapItemsControl>
    </Grid.Resources>
    <Grid x:Name="ContentPanel" Grid.Row="0" Margin="12,0,12,0"/>
</Grid>

public partial class MapPage : PhoneApplicationPage
{
    private ObservableCollection<PinData> _pinsA = new ObservableCollection<PinData>();
    private Map MyMap;
    public ObservableCollection<PinData> PinsA { get { return this._pinsA; } }  

    public MapPage()
    {
        InitializeComponent();

        this.DataContext = this;
        //Create a map.
        MyMap = new Map();
        MyMap.CredentialsProvider = new ApplicationIdCredentialsProvider("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        //Remove the List of items from the resource and add it to the map
        this.LayoutRoot.Resources.Remove("GroupAPins");
        MyMap.Children.Add(GroupAPins);
        MyMap.Center = new GeoCoordinate(40.74569634433956, -73.96717071533204);
        MyMap.ZoomLevel = 5;
        //Add the map to the content panel.
        ContentPanel.Children.Add(MyMap);
        loadAPins_fromString();
    }

    //ADD PIN TO COLLECTION  
    private void addPin(String lat, String lon)
    {
        PinData tmpPin;
        tmpPin = new PinData()
        {
            PinLocation = new GeoCoordinate(System.Convert.ToDouble(lat), System.Convert.ToDouble(lon))
        };
        _pinsA.Add(tmpPin);

        var timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += delegate(object sender, EventArgs args)
                        {
                            PinsA.Remove(tmpPin);
                            tmpPin.PinLocation.Latitude += 1;
                            PinsA.Add(tmpPin);

                        };
        timer.Start();

    }

    //LOAD PINS ONE BY ONE  
    private string loadAPins_fromString()
    {
        //BAD  
        addPin("42.35960626034072", "-71.09212160110473");
        //addPin("51.388066116760086", "30.098590850830067");
        //addPin("48.17972265679143", "11.54910385608672");
        addPin("40.28802528051879", "-76.65668606758117");

        var coords = PinsA.Select(p => p.PinLocation).ToList();
        MyMap.SetView(LocationRect.CreateLocationRect(coords));

        return "A PINS LOADED - STRING";
    }
}

public class PinData 
{
    public GeoCoordinate PinLocation{get;set;}
}