【问题标题】:Update the location of pushpins on Silverlight bing maps control更新 Silverlight bing 地图控件上图钉的位置
【发布时间】:2012-04-13 05:54:44
【问题描述】:

我的问题是关于在 windows phone 7 上使用必应地图。这是我需要做的总结

  • 每 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));
      

引脚加载正常,调用服务以获取他们的新位置也加载正常,问题是他们在地图上的位置永远不会更新,所以即使所有这些工作都在进行,他们基本上只是静止不动背景,我已经调试过了,所以我知道它可以工作。如何重置图钉的位置,如果使用图像不起作用,我可以使用图钉对象吗?这将如何工作?

提前致谢。

【问题讨论】:

  • 我在您的代码中看不到您确保在 UI 层上执行位置更改的位置。
  • 抱歉 BPerreault,我不明白你的问题。
  • 嗨,所以我使用 this.Dispatcher.BeginInvoke(() => {});但它仍然没有更新地图上的图钉位置
  • 嗯。好的,当事情很顽固时,我还有另一个选择,也许它会有所帮助。我会在下面发布。

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


【解决方案1】:

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

【讨论】:

  • 谢谢 MrMDavidson,我已经尝试过了,但还是不行。我会假设由于图钉在 MapLayer 上,我们应该更新它或它们自己的图钉,但显然我错了。还有其他想法吗?
  • 我正在将我的图钉绑定到 MapItemsControl ItemsSource 属性,其中 Pushpin 项目在 DataTemplate 中创建。图钉将GeoCoordinate 属性绑定到它们的Location 属性。更新属性后,我打电话给SetView(),如我的回答中所述,一切正常。您可以尝试发布您的 XAML 吗?
【解决方案2】:

这是一个类似于 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));
        }
    }

【讨论】:

  • 嗯,有趣!我需要对此进行一些研究。谢谢指出
【解决方案3】:

好问题!

这是一些真的丑陋的代码,但至少它可以工作并且可以开始。

我从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;}
} 

【讨论】:

  • 这看起来不错,我会试一试。尽管我已经在某种程度上进行了这项工作,但随着每次调用 MyMap.SetView(LocationRect.CreateLocationRect(coords)); 时地图缩放级别会降低,它仍然有点跳跃!一旦我的工作代码顺利运行,我肯定会回来。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多