silverlight   发布时间:2022-05-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了ArcGIS API for Silverlight开发入门(2):一个基础地图实例大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

这节在一个地图实例的基础上,来对Silverlight API中的一些基本概念做一个总体了解,顺便熟悉一下Silverlight的开发知识。 点击这里,直接看效果。 下载 (722.07 KB) 2009-4-13 15:24 根据上一节的知识,可以知道这个Silverlight程序里包含了一个Map控件,并且里面至少有一个WorldImagery的图层。那么Page.xaml里的关键代码开起来应
这节在一个地图实例的基础上,来对Silverlight API中的一些基本概念做一个总体了解,顺便熟悉一下Silverlight的开发知识。
点击这里,直接看效果

ArcGIS API for Silverlight开发入门(2):一个基础地图实例

ArcGIS API for Silverlight开发入门(2):一个基础地图实例

下载 (722.07 KB)
2009-4-13 15:24

根据上一节的知识,可以知道这个Silverlight程序里包含了@L_364_0@map控件,并且里面至少有一个WorldImagery的图层。那么Page.xaml里的关键代码开起来应该是这样的
  1. <Grid x:Name="LayoutRoot">
  2. <esri:Map x:Name="Map1">
  3. <esri:Map.Layers>
  4. <esri:ArcGISTiledMapserviceLayer ID="WorldImageLayer" x:Name="WorldImageLayer" Initialized="WorldImageLayer_Initialized"
  5. Url="http://services.arcgisonline.com/ArcGIS/rest/services/ESRi_iR_152_11845@agery_World_2D/MapServer" />
  6. </esri:Map.Layers>
  7. </esri:Map>
  8. </Grid>
复制代码
所有的布局工作都在一个Grid中进行,给它起个名字叫LayoutRoot。Grid里面放了一个esri:Map元素(Map控件),它继承自Silverlight的Control,所以拥有Width和Height属性认是Auto,自动填充整个Grid。Map.Layers是一个集合,可以往里面添加layer,这里的layer指的是arcgis server或其他软件发布的地图服务,目前SilverlightAPI中支持的能够直接使用的有ArcGISDynamicMapserviceLayer,ArcGISTiledMapserviceLayer,ArcGISImageserviceLayer,分别对应arcgis server发布的动态地图服务,缓存地图服务(两种Map service)和Imageservice,这三种图层是拿来即用的,如果你想加入别的地图服务,比如WMS服务,则需要自己继承相应类型的的Layer;此外还有GraphicsLayer,ElementLayer,SilverlightAPI特有的FeatureLayer等。这些都会在之后的小节中讲到。强调一下,与ADF开发里MapresourceManager一样,在Map中加入的内容实际上是地图服务,但当做一个layer处理。
下面就对这个例子中的每一部分来做说明(与上图中的序号相对应)。

1、当地图移动时获取地图范围。
当地图范围改变后,显示出当前地图范围的边界值。
这部分的页面布局是这样的
  1. <Grid x:Name="Gridright" Margin="0,15,20,0" HorizontalAlignment="Right" VerticalAlignment="Stretch">
  2. <!--extent-->
  3. <Canvas Width="215" Height="110" VerticalAlignment="Top">
  4. <Rectangle Style="{Staticresource rectBottom}" />
  5. <Rectangle Style="{Staticresource rectMiddlE}" />
  6. <Rectangle Style="{Staticresource rectTop}" />
  7. <TextBlock x:Name="TBextent" Margin="20,0" Text="范围:" textwrapping="Wrap" FontWeight="Bold" />
  8. </Canvas>
  9. </Grid>
复制代码
有关xaml中详细的布局知识请大家参照其他例子学习,这里稍作讲解。外面的Gridright这个Grid就是页面右边1、2、3、6的父容器,之所以不用StackPanel是因为6需要贴着页面底部,StackPanel中的元素都会flow贴到一起。三个矩形组合便构成了整体轮廓,由于它们都在一个Canvas中,所以会产生压盖效果。最先加入的rectBottom这个矩形便是最底下的阴影效果,中间的矩形是蓝色框,最上面的矩形是白色的文字显示区域。“{ }”里的内容在xaml中称作markupextention,Staticresource是使用在别处已经定义好的资源(resource)来对本元素的一些属性进行自动赋值,这里用来修饰Rectangle的外观。xaml中除了Staticresource这种markupextention之外还有Binding和TemplateBinding两种markup extention,分别用于数据绑定(databinding)和自定义control的外观。上面的Staticresource是在App.xaml中定义的,这样就可以在本工程的任何页面中使用,当然也可以定义为LayoutRoot这个Grid的resource。贴出来大家一看就明白了:
  1. <Application.resources>
  2. <Style x:Key="rectBottom" TargetType="Rectangle">
  3. <Setter Property="RadiusX" Value="10" />
  4. <Setter Property="RadiusY" Value="10" />
  5. <Setter Property="Fill" Value="#22000000" />
  6. <Setter Property="Canvas.Left" Value="5" />
  7. <Setter Property="Canvas.Top" Value="5" />
  8. <Setter Property="Width" Value="215" />
  9. <Setter Property="Height" Value="110" />
  10. </Style>
  11. <Style x:Key="rectMiddle" TargetType="Rectangle">
  12. <Setter Property="RadiusX" Value="10" />
  13. <Setter Property="RadiusY" Value="10" />
  14. <Setter Property="Fill" Value="#775C90B2" />
  15. <Setter Property="Canvas.Left" Value="0" />
  16. <Setter Property="Canvas.Top" Value="0" />
  17. <Setter Property="Width" Value="215" />
  18. <Setter Property="Height" Value="110" />
  19. <Setter Property="stroke" Value="Gray" />
  20. </Style>
  21. <Style x:Key="rectTop" TargetType="Rectangle">
  22. <Setter Property="RadiusX" Value="5" />
  23. <Setter Property="RadiusY" Value="5" />
  24. <Setter Property="Fill" Value="#FFFFFFFF" />
  25. <Setter Property="Canvas.Left" Value="10" />
  26. <Setter Property="Canvas.Top" Value="10" />
  27. <Setter Property="Width" Value="195" />
  28. <Setter Property="Height" Value="90" />
  29. <Setter Property="stroke" Value="DarkGreen" />
  30. </Style>
  31. </Application.resources>
复制代码
它们就相当于网页中的css。如果不使用Staticresource,那么三个矩形看起来应该是这样的
  1. <Rectangle RadiusX="10" RadiusY="10" Fill="#22000000" Canvas.Left="5" Canvas.Top="5" Width="215" Height="110" />
  2. <Rectangle RadiusX="10" RadiusY="10" Fill="#775C90B2" Canvas.Left="0" Canvas.Top="0" Width="215" Height="110" stroke="Gray" />
  3. <Rectangle RadiusX="5" RadiusY="5" Fill="#FFFFFFFF" Canvas.Left="10" Canvas.Top="10" Width="195" Height="90" stroke="DarkGreen" />
复制代码
你猜的没错,在其他矩形框部分也使用到了这些属性。通过实践可以感受到,xaml中的布局在一般使用中比html+css的布局要简单和灵活许多。好了,继续。
Map控件里面已经封装了一些事件来供我们使用,我们可以在需要的时候捕获它们来进行处理。如果做过ArcGIS产品的二次开发,你应该已经想到我们要捕获的就是Map的ExtentChanged事件;而要在地图移动或者缩放的过程中也实时显示地图范围,则还要对ExtentChanging事件做处理。细心的你可能已经发现,在上面的xaml代码中已经对世界地图这个图层的Initialized事件添加一个hanlder:WorldImageLayer_Initialized。当然可以像这样一样给Map的这两个事件添加handler,但这里并不这么做,而是在世界地图图层的Initialized事件里来绑定它们(移动地图时出发ExtentChanged事件,网速过慢导致图层并未加入到Map中,则会报错)。来看看Page.xaml.cs中的code-behind代码
  1. private void WorldImageLayer_Initialized(object sender,EventArgs E)
  2. {
  3. @H_426_42@map1.ExtentChanged += new EventHandler<ESRI.ArcGIs.ExtentEventArgs>(Map1_ExtentChangE);
    @H_426_42@map1.ExtentChanging += new EventHandler<ESRI.ArcGIs.ExtentEventArgs>(Map1_ExtentChangE);
  4. }
复制代码
没错,把两个事件绑定到同一个handler即可。再看看Map1_ExtentChange中的代码
  1. private void Map1_ExtentChange(object sender,ESRI.ArcGIs.ExtentEventArgs E)
  2. {
  3. TBextent.Text = String.Format("地图范围:\nMinX:{0}\nMinY:{1}\nMaxX:{2}\nMaxY:{3}",
  4. e.NewExtent.XMin,e.NewExtent.ymin,e.NewExtent.XMax,e.NewExtent.ymaX);
  5. }
复制代码
很简单吧?顺便提一下,ExtentEventArgs里既然有NewExtent,当然就有OldExtent了,通过比较这两个变量就可以分析出当前进行的是放大、缩小还是平移操作了。其实还有个更简单的办法,查查看Map的Resolution属性吧。
对于Silverlight API中内容,是不是感觉很容易呢(当然你得做够xaml的功课才行)?那么赶快来看第二部分。

2、当鼠标移动时获取鼠标坐标。
包括屏幕坐标和地图坐标。外观样式方面是这样的
  1. <!--mouse coords-->
  2. <Canvas Width="215" Height="110" Margin="0,120,0" VerticalAlignment="Top">
  3. <Rectangle Style="{Staticresource rectBottom}" />
  4. <Rectangle Style="{Staticresource rectMiddlE}" />
  5. <Rectangle Style="{Staticresource rectTop}" />
  6. <StackPanel Orientation="Vertical" Margin="20,0">
  7. <TextBlock x:Name="TBscreencoords"
  8. HorizontalAlignment="Left" VerticalAlignment="Center" Text="屏幕坐标:" textwrapping="Wrap" FontWeight="Bold" />
  9. <TextBlock x:Name="TBmapcoords"
  10. HorizontalAlignment="Left" VerticalAlignment="Center" Text="地图坐标:" textwrapping="Wrap" FontWeight="Bold" />
  11. </StackPanel>
  12. </Canvas>
复制代码
那么接下来要捕捉那个事件呢?当然就是MouseMove啦。不过如果查看SilverlightAPI中的Map类,发现并没有这个事件。但要记住Map是继承自xaml中的Control,Control继承自FrameworkElement,FrameworkElement继承自UIElement,这里就有@L_364_0@mouseMove事件了。所以Map控件的MouseMove是xaml中而不是Siverlight API中的事件(当然整个SilverlightAPI都是建立在xaml基础上的)。在esri:Map标签添加@L_364_0@mouseMove事件(MouseMove="Map1_MouseMove"),来看看code-behind代码
  1. private void Map1_MouseMove(object sender,MouseEventArgs E)
  2. {
  3. if (Map1.Extent != null)
  4. {
  5. System.Windows.Point screenPnt = e.GetPosition(Map1);
  6. TBscreencoords.Text = String.Format("屏幕坐标:\nX:{0},Y:{1}",screenPnt.X,screenPnt.Y);

  7. ESRI.ArcGIs.Geometry.MapPoint mapPnt = Map1.ScreenToMap(screenPnt);
  8. TBmapcoords.Text = String.Format("地图坐标:\nX:{0}\nY:{1}",Math.round(R_152_11845@apPnt.X,4),Math.round(R_152_11845@apPnt.Y,4));
  9. }
  10. }
复制代码
可以看到Map控件提供了屏幕与地图坐标之间转换的方法,好比开发人员的一座桥梁,用来往返于Silverlight特性与地图之间,非常方便。需要说明的是,这里GetPosition(Map1)获得的屏幕坐标是相对于Map控件的,而不是显示器的左上角。ok,继续来看第三部分。

3、Map里的动画效果
当地图放大和平移时都可以看到平滑的效果,这归功于Silverlight的动画功能。Map在封装完动画效果后,给了我们两个属性来对它们进行设置:PanDuration和ZoomDuration,用于设置这两个动作持续的时间。它们都是TimeSpan类型的变量,合理的设置可以带来良好的用户体验。看看这部分的布局:
  1. <!--map animation slider-->
  2. <Canvas Width="215" Height="130" Margin="0,240,0" VerticalAlignment="Top">
  3. <Rectangle Style="{Staticresource rectBottom}" Height="130" />
  4. <Rectangle Style="{Staticresource rectMiddlE}" Height="130" />
  5. <Rectangle Style="{Staticresource rectTop}" Height="110" />
  6. <StackPanel Orientation="Vertical" Margin="20,0">
  7. <TextBlock HorizontalAlignment="Left" Text="设置地图缩放动作持续时间:" textwrapping="Wrap" FontWeight="Bold" />
  8. <TextBlock x:Name="TBzoomdurationvalue" HorizontalAlignment="Left" Text="当前值:" textwrapping="Wrap" FontWeight="Bold" />
  9. <Slider x:Name="sliderzoomanimation" Orientation="Horizontal" Minimum="0" Maximum="20" smallChange="1"
  10. LargeChange="5" cursor="Hand" ValueChanged="slideranimation_ValueChanged" Width="180" />
  11. <TextBlock HorizontalAlignment="Left" Text="设置地图平移动作持续时间:" textwrapping="Wrap" FontWeight="Bold" />
  12. <TextBlock x:Name="TBpandurationvalue" HorizontalAlignment="Left" Text="当前值:" textwrapping="Wrap" FontWeight="Bold" />
  13. <Slider x:Name="sliderpananimation" Orientation="Horizontal" Minimum="0" Maximum="20" smallChange="1"
  14. LargeChange="5" cursor="Hand" ValueChanged="slideranimation_ValueChanged" Width="180" />
  15. </StackPanel>
  16. </Canvas>
复制代码
主要用到了两个slider控件。再看看拖动滑块时的事件代码,为了省事,这两个事件也用了同一个handler:
  1. private void slideranimation_ValueChanged(object sender,RoutedPropertyChangedEventArgs E)
  2. {
  3. Slider s=sender as Slider;
  4. if (s.Name == "sliderzoomanimation")
  5. {
  6. @H_426_42@map1.ZoomDuration = new TimeSpan(0,Convert.ToInt32(sliderzoomanimation.value));
  7. TBzoomdurationvalue.Text = String.Format("当前值{0}秒",Convert.ToInt32(sliderzoomanimation.value));
  8. }
  9. else
  10. {
  11. @H_426_42@map1.PanDuration = new TimeSpan(0,Convert.ToInt32(sliderpananimation.value));
  12. TBpandurationvalue.Text = String.Format("当前值{0}秒",Convert.ToInt32(sliderpananimation.value));
  13. }
  14. }
复制代码
对应着地图效果,应该很容易理解。继续第四部分。

4、对地图服务可见性与动态地图服务中图层可见性的控制。
还是要强调一下,WorldImagery和StreetMap两个能看到的地图实际上都是地图服务,当作layer加入到了Map控件中;而动态地图服务USA中的图层Cities,Rivers,States才是与ArcMap中图层相对的概念。对于WorldImagery和StreetMap之间的切换,主要用到了Silverlight API里Layer的
Visible属性;而动态服务中图层可见性的操作,主要是对ArcGISDynamicMapserviceLayer的VisibleLayers数组做了设置。
StreetMap这个服务其实一开始就加入了地图(在esri:Map标签中):
  1. <esri:ArcGISTiledMapserviceLayer ID="StreetMapLayer"
  2. Url="http://services.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer" Visible="false" />
复制代码
而设置了Visible="false"。图层不可见时地图不会对它做任何处理,所以不用担心会耗费流量或加重程序负担。
看看布局部分:
  1. <StackPanel HorizontalAlignment="Left" Margin="20,0">
  2. <Canvas x:Name="Canvasleft" Width="165" Height="90" HorizontalAlignment="Left" VerticalAlignment="Top">
  3. <Rectangle Style="{Staticresource rectBottom}" Width="165" Height="90" />
  4. <Rectangle Style="{Staticresource rectMiddlE}" Fill="#7758FF00" Width="165" Height="90" />
  5. <Rectangle Style="{Staticresource rectTop}" Width="145" Height="70" />
  6. <!--change layer-->
  7. <StackPanel Margin="20,0">
  8. <TextBlock Text="切换图层:" textwrapping="Wrap" FontWeight="Bold" />
  9. <StackPanel Orientation="Horizontal">
  10. <ToggleButton x:Name="TBimagery" Content="Imagery" Click="TBimagery_Clicked" cursor="Hand" />
  11. <ToggleButton x:Name="TBstreetmap" Content="StreetMap" Click="TBstreetmap_Clicked" cursor="Hand" />
  12. </StackPanel>
  13. <checkBox Margin="0,5,0" x:Name="chkBoxDynamicLayer" Content="添加一个动态图层吧" Ischecked="false" Click="chkBoxDynamicLayer_Click" cursor="Hand" />
  14. </StackPanel>
  15. </Canvas>
  16. </StackPanel>
复制代码
这里使用了ToggleButton,checkBox和RadioButton都由它派生而来。Silverlight2中的ToggleButton不能设置Group(一个Group中自动限定同时只能有一个控件处于激活状态),不如Flex里的ToggleButton来的方便,所以code-behind中多做了些工作。当然这里使用RadioButton也是可以的
  1. private void TBimagery_Clicked(object sender,RoutedEventArgs E)
  2. {
  3. if (TBstreetmap.Ischecked==truE)
  4. {
  5. @H_426_42@map1.Layers["WorldImageLayer"].Visible = true;
    @H_426_42@map1.Layers["WorldImageLayer"].opacity = 0;
  6. TBstreetmap.Ischecked = false;
  7. Storyboard sbworldmapshow = makestoryboard("WorldImageLayer",1);
  8. Storyboard sbstreetmaphide = makestoryboard("StreetMapLayer",1,0);
  9. sbworldmapshow.begin();
  10. sbstreetmaphide.begin();
  11. hidelayername = "StreetMapLayer";
  12. timer.begin();
  13. }
  14. TBimagery.Ischecked = true;
  15. }

  16. private void TBstreetmap_Clicked(object sender,RoutedEventArgs E)
  17. {
  18. if (TBimagery.Ischecked==truE)
  19. {
  20. @H_426_42@map1.Layers["StreetMapLayer"].Visible = true;
    @H_426_42@map1.Layers["StreetMapLayer"].opacity = 0;
  21. TBimagery.Ischecked = false;
  22. Storyboard sbstreetmapshow = makestoryboard("StreetMapLayer",1);
  23. Storyboard sbworldmaphide = makestoryboard("WorldImageLayer",0);
  24. sbstreetmapshow.begin();
  25. sbworldmaphide.begin();
  26. hidelayername = "WorldImageLayer";
  27. timer.begin();
  28. }
  29. TBstreetmap.Ischecked = true;
  30. }

  31. private void timer_Tick(object sender,EventArgs E)
  32. {
  33. @H_426_42@map1.Layers[hidelayername].Visible = false;
  34. }

  35. public Storyboard makestoryboard(String layername,double from,double to)
  36. {
  37. Storyboard sb = new Storyboard();
  38. ESRI.ArcGIs.ArcGISTiledMapserviceLayer layer = Map1.Layers[layername] as ESRI.ArcGIs.ArcGISTiledMapserviceLayer;
  39. DoubleAnimation doubleAnim = new DoubleAnimation();
  40. doubleAnim.Duration = new TimeSpan(0,5);
  41. doubleAnim.From = from;
  42. doubleAnim.To = to;
  43. Storyboard.SetTarget(doubleAnim,layer);
  44. Storyboard.SetTargetProperty(doubleAnim,new PropertyPath("Opacity"));
  45. sb.Children.Add(doubleAnim);

  46. return sb;
  47. }
复制代码
当切换两个地图服务时能够看到一个渐变的效果,这里用到了Silverlight中的动画,它们都是在StoryBoard里面进行的,以后的小节中会讲Silverlight中的动画,这里不再废话了,有兴趣的朋友可以自己参帮助学习。hidelayername是这个一个公用的String变量,用来在切换的动画效果完成后设置不可见的图层Visible属性。timer也是一个StoryBoard:
  1. <Storyboard x:Name="timer" Completed="timer_Tick" Duration="0:0:5" />
复制代码
这里可以看出把StoryBoard也能巧妙的用作计时器。到了特定时间(5秒)后会自动timer_Tick函数,当然也可以使用.net中的各种timer类。
下面是添加动态服务的部分。
  1. private void chkBoxDynamicLayer_Click(object sender,RoutedEventArgs E)
  2. {
  3. if (chkBoxDynamicLayer.Ischecked == truE)
  4. {
  5. @H_426_42@map1.Layers.Add(california);
    @H_426_42@map1.ZoomTo(california.FullExtent);

  6. if (california.IsInitialized == falsE)
  7. {
  8. chkBoxDynamicLayer.IsEnabled = false;
  9. }
  10. chkBoxDynamicLayer.Content = "去掉它";
  11. SVlayers.Visibility = Visibility.Visible;
  12. }
  13. else
  14. {
  15. @H_426_42@map1.Layers.Remove(california);
  16. chkBoxDynamicLayer.Content = "添加一个动态图层吧";
  17. SVlayers.Visibility = Visibility.Collapsed;
  18. }
  19. }

  20. private void dynamiclayer_initialized(object s,EventArgs E)
  21. {
  22. //若图层没有初始化好就移除图层,当然会报错了,所以这样做就不会了
  23. chkBoxDynamicLayer.IsEnabled = true;
  24. @H_426_42@map1.ZoomTo(california.InitialExtent);
  25. SVlayers.Visibility = Visibility.Visible;
  26. california.ID = "layercalifornia";

  27. ESRI.ArcGIs.ArcGISDynamicMapserviceLayer dynamicserviceLayer = s as ESRI.ArcGIs.ArcGISDynamicMapserviceLayer;
  28. if (dynamicserviceLayer.VisibleLayers == null)
  29. dynamicserviceLayer.VisibleLayers = GetDefaultVisibleLayers(dynamicserviceLayer);
  30. updateLayerList(dynamicserviceLayer);
  31. }
复制代码
添加了动态服务后,会自动弹出一个listBox,当然这些也都是在xaml中定义好的(加在上面的Canvas后面):
  1. <ScrollViewer x:Name="SVlayers" Width="165" Visibility="Collapsed" Height="120">
  2. <ListBox x:Name="LayerVisibilityListBox" >
  3. <ListBox.ItemTemplate>
  4. <DataTemplate>
  5. <checkBox Margin="2" Name="{Binding LayerIndex}" Content="{Binding LayerNamE}"
  6. Tag="{Binding servicename}" Ischecked="{Binding VisiblE}"
  7. Clickmode="Press" Click="chkBoxToggleVilible_Click" />
  8. </DataTemplate>
  9. </ListBox.ItemTemplate>
  10. </ListBox>
  11. </ScrollViewer>
复制代码
这里把ListBox放到了ScrollVierwer中,固定了它的高度,当内容过多时可以自动显示纵向滚动条。这里要提一下,ListBox内容用到了数据绑定(参xaml中的DataBinding,有OneTime,OneWay和TwoWay三种模式,这里使用的是认的OneWay),看起来里面只有一个checkBox,但它相当于一个模板,在code-behind中设置了ListBox.Itemsource之后,根据该属性内容自动生成多个checkBox代码自定义一个LayerListData类,它的几个属性分别与上面的checkBox属性绑定;将一个List赋给了ListBox.Itemsource,则会自动生成ListBox中的内容。通过一个List类型变量,来控制动态服务的可见图层。代码如下:
  1. public class LayerListData
  2. {
  3. public bool Visible { get; set; }
  4. public String servicename { get; set; }
  5. public String LayerName { get; set; }
  6. public int LayerIndex { get; set; }
  7. }

  8. privatE int[] GetDefaultVisibleLayers(ESRI.ArcGIs.ArcGISDynamicMapserviceLayer dynamicservicE)
  9. {
  10. List<int> visibleLayerIDList = new List<int>();

  11. ESRI.ArcGIs.LayerInfo[] layerInfoArray = dynamicservice.Layers;

  12. for (int index = 0; index < layerInfoArray.Length; index++)
  13. {
  14. if (layerInfoArraY[index].DefaultVisibility)
  15. visibleLayerIDList.Add(indeX);
  16. }

  17. return visibleLayerIDList.ToArray();
  18. }

  19. private void updateLayerList(ESRI.ArcGIs.ArcGISDynamicMapserviceLayer dynamicserviceLayer)
  20. {
  21. int[] visibleLayerIDs = dynamicserviceLayer.VisibleLayers;

  22. if (visibleLayerIDs == null)
  23. visibleLayerIDs = GetDefaultVisibleLayers(dynamicserviceLayer);

  24. List<LayerListData> visibleLayerList = new List<LayerListData>();

  25. ESRI.ArcGIs.LayerInfo[] layerInfoArray = dynamicserviceLayer.Layers;

  26. for (int index = 0; index < layerInfoArray.Length; index++)
  27. {
  28. visibleLayerList.Add(new LayerListData()
  29. {
  30. Visible = visibleLayerIDs.Contains(indeX),
  31. servicename = dynamicserviceLayer.ID,
  32. LayerName = layerInfoArraY[index].Name,
  33. LayerIndex = index
  34. });
  35. }

  36. LayerVisibilityListBox.Itemssource = visibleLayerList;
  37. }

  38. void chkBoxToggleVilible_Click(object sender,RoutedEventArgs E)
  39. {
  40. checkBox tickedcheckBox = sender as checkBox;

  41. String servicename = tickedcheckBox.Tag.ToString();
  42. bool visible = (bool)tickedcheckBox.Ischecked;

  43. int layerIndex = Int32.Parse(tickedcheckBox.Name);

  44. ESRI.ArcGIs.ArcGISDynamicMapserviceLayer dynamicserviceLayer = Map1.Layers[servicename] as
  45. ESRI.ArcGIs.ArcGISDynamicMapserviceLayer;

  46. List<int> visibleLayerList =
  47. dynamicserviceLayer.VisibleLayers != null
  48. ? dynamicserviceLayer.VisibleLayers.ToList() : new List<int>();

  49. if (visiblE)
  50. {
  51. if (!visibleLayerList.Contains(layerIndeX))
  52. visibleLayerList.Add(layerIndeX);
  53. }
  54. else
  55. {
  56. if (visibleLayerList.Contains(layerIndeX))
  57. visibleLayerList.Remove(layerIndeX);
  58. }

  59. dynamicserviceLayer.VisibleLayers = visibleLayerList.ToArray();
  60. }
复制代码
5、比例尺。
Silverlight API提供了一个ScaleBar类,可以方便的设置地图比例尺。
  1. <!--scale bar 放在LayoutRoot Grid中-->
  2. <Canvas HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="10,20">
  3. <esri:ScaleBar x:Name="scalebar" MapUnit="decimaldegrees" DisplayUnit="Kilometers" Foreground="Black" FillColor1="White" FillColor2="Blue" />
  4. </Canvas>
复制代码
需要在初始化的时候设置scalebar的Map属性,顺便来看看整个页面的初始化工作:
  1. namespace demo_02_extendedmap
  2. {
  3. public partial class Page : UserControl
  4. {
  5. private ESRI.ArcGIs.ArcGISDynamicMapserviceLayer california = new ESRI.ArcGIs.ArcGISDynamicMapserviceLayer();
  6. private String hidelayername;

  7. public Page()
  8. {
  9. InitializeComponent();

  10. scalebar.Map = Map1;
  11. scalebarstoryboard.begin();
  12. TBzoomdurationvalue.Text = String.Format("当前值{0}.{1}秒",Map1.ZoomDuration.Seconds,Map1.ZoomDuration.Milliseconds);
  13. TBpandurationvalue.Text = String.Format("当前值{0}.{1}秒",Map1.PanDuration.Seconds,Map1.PanDuration.Milliseconds);
  14. california.Url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Specialty/ESRI_StatesCitiesRivers_USA/MapServer";
  15. california.opacity = 0.5;
  16. california.Initialized += new EventHandler<EventArgs>(dynamiclayer_initialized);

  17. TBimagery.Ischecked = true;
  18. @H_426_42@makestoryboard("WorldImageLayer",1).begin();
  19. //切换全屏/窗口
  20. Application.Current.Host.Content.FullScreenChanged += new EventHandler(fullscreen_changed);
  21. }
  22. }
  23. }
复制代码
scalebarstoryboard是xaml里自定义一个动画,效果见比例尺旁的单位。

6、地图相关操作。
Map控件已经内置了一些键盘鼠标事件,但目前不能像JavascriptAPI中那样禁用这些事件。这里还用到了Silverlight程序的一个全屏特性,其实是对Application.Current.Host.Content的一个属性做了设置。直接看代码吧:
  1. <!--operation info-->
  2. <Canvas Width="215" Height="110" Margin="0,30" VerticalAlignment="Bottom">
  3. <Rectangle Style="{Staticresource rectBottom}" />
  4. <Rectangle Style="{Staticresource rectMiddlE}" Fill="#77FF0000" />
  5. <Rectangle Style="{Staticresource rectTop}" />
  6. <TextBlock Margin="20,0" textwrapping="Wrap"
  7. Text="地图操作提示:双击放大 Shift+拖拽:放大到指定范围 Ctrl+Shift+拖拽:缩小到指定范围" />
  8. <ToggleButton x:Name="TBfullscreen" Content="点击切换地图全屏" HorizontalAlignment="Center" Canvas.Left="100" Canvas.Top="15" Height="30" Click="TBfullscreen_Click" />
  9. </Canvas>
复制代码
放到Gridright Grid中,
  1. private void TBfullscreen_Click(object sender,RoutedEventArgs E)
  2. {
  3. System.Windows.Interop.Content content = Application.Current.Host.Content;
  4. content.IsFullScreen=!content.IsFullScreen;
  5. }

  6. private void fullscreen_changed(object o,EventArgs E)
  7. {
  8. System.Windows.Interop.Content content=Application.Current.Host.Content;
  9. TBfullscreen.Ischecked = content.IsFullScreen;
  10. }
复制代码
7、进度条。
最后还剩下地图中的这个进度条。利用了Map控件内置的一个Progress事件。
  1. <!--progressbar 放在LayoutRoot中-->
  2. <Grid HorizontalAlignment="Center" x:Name="progressgrid" VerticalAlignment="Center" Width="200" Height="20" Margin="5,5">
  3. <ProgressBar x:Name="MyProgressBar" Minimum="0" Maximum="100" />
  4. <TextBlock x:Name="ProgressvalueTextBlock" Text="100%" HorizontalAlignment="Center" VerticalAlignment="Center" />
  5. </Grid>
复制代码
在esri:Map标签中加入一个事件:Progress="Map1_Progress",
  1. private void Map1_Progress(object sender,ESRI.ArcGIs.ProgressEventArgs E)
  2. {
  3. if (e.Progress < 100)
  4. {
  5. progressgrid.Visibility = Visibility.Visible;
  6. @H_426_42@myProgressBar.Value = e.Progress;
  7. ProgressvalueTextBlock.Text = String.Format("正在处理 {0}%",e.Progress);
  8. }
  9. else
  10. {
  11. progressgrid.Visibility = Visibility.Collapsed;
  12. }
  13. }
复制代码
好了到此就已经讲完了整个地图功能。尽管想尽可能详细说明每段代码便于初学的朋友学习,但也不可能面面俱到。没有讲明白的地方大家可以自己思,查帮助。学习的过程中,不思,无进步。
原文地址: @L_489_203@

大佬总结

以上是大佬教程为你收集整理的ArcGIS API for Silverlight开发入门(2):一个基础地图实例全部内容,希望文章能够帮你解决ArcGIS API for Silverlight开发入门(2):一个基础地图实例所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。