zoukankan      html  css  js  c++  java
  • [专家讲座] ArcGIS API for Silverlight开发入门(3):Widgets(转)

    转载地址:http://www.cnblogs.com/SunYu/archive/2010/04/30/1724718.html

    Widgets翻译过来是小玩具。如果使用过Dojo或者ExtJS等js框架肯定会了解到这个“小玩具”也有大用处,能够在很大程度上减少我们的工作量,快速完成功能需求。能减少多大工作量呢?让我们先来,点击这里,看一个例子。


            前两节的地图中,总感觉少点什么……对,就是一个sliderbar,有了它感觉就像汽车有了方向盘一样,能够控制方向了。那么来看看实现上面这个例子中的滑块条需要做什么工作吧。
    在silverlight中创建一个UserControl,把上面sliderbar的外观和功能都封装在里面。
    来看具体工作。vs中,在silverlight工程上右键单击,add,new item,选择silverlight user control,起名叫mapslider,在mapslider.xaml中填如下代码:

    1. <Grid x:Name="slidergrid" HorizontalAlignment="Left" VerticalAlignment="Center" Background="Azure" Margin="20">
    2.         <StackPanel Orientation="Vertical">
    3.             <Button x:Name="btnzoomin" Content="+" Click="btnzoomin_Click" />
    4.             <Slider x:Name="sliderLOD" Orientation="Vertical"  Height="200" SmallChange="1" LargeChange="1"  Minimum="0" Cursor="Hand" ValueChanged="slider1_ValueChanged" />
    5.             <Button x:Name="btnzoomout" Content="-" Click="btnzoomout_Click" />
    6.         </StackPanel>
    7.     </Grid>
    复制代码

    上面这些就是滑块条的外观,接下来看功能部分。大致思路是在mapslider类中设置一个公共属性Map,就是需要操作的地图了,但这个属性不是ESRI.ArcGIS.Map,而是另一个自定义类。为什么要这么做?因为这个自定义类需要实现INotifyPropertyChanged接口,当我们把自己的Map控件作为mapslider的属性赋值的时候,这个Map需要做另外一些工作。看代码吧,不太明白的话就要加强对silverlight中data binding的学习。在mapslider.xaml.cs页面中填入一下代码:

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Net;
    5. using System.Windows;
    6. using System.Windows.Controls;
    7. using System.Windows.Documents;
    8. using System.Windows.Input;
    9. using System.Windows.Media;
    10. using System.Windows.Media.Animation;
    11. using System.Windows.Shapes;
    12. using System.ComponentModel;
    13. namespace customcontrol
    14. {
    15.     public partial class mapslider : UserControl
    16.     {
    17.         private mymap map = new mymap();
    18.         public ESRI.ArcGIS.Map Map
    19.         {
    20.             get
    21.             {
    22.                 return map.Map;
    23.             }
    24.             set
    25.             {
    26.                 map.Map=value;
    27.                 if (map.Map != null)
    28.                 {
    29.                     Map.ExtentChanged += new EventHandler<ESRI.ArcGIS.ExtentEventArgs>(map_ExtentChanged);
    30.                     Map.SnapToLevels = true;
    31.                     ((ESRI.ArcGIS.ArcGISTiledMapServiceLayer)Map.Layers[0]).Initialized += new EventHandler<EventArgs>(layer0_initialized);
    32.                 }
    33.             }
    34.         }
    35.         private void layer0_initialized(object o,EventArgs e)
    36.         {
    37.             sliderLOD.Maximum = ((ESRI.ArcGIS.ArcGISTiledMapServiceLayer)Map.Layers[0]).TileInfo.Lods.Length - 1;
    38.         }
    39.         public mapslider()
    40.         {
    41.             InitializeComponent();
    42.         }
    43.         private void slider1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    44.         {
    45.             if (map.Map!=null)
    46.             {
    47.                 Map.ZoomToResolution(((ESRI.ArcGIS.ArcGISTiledMapServiceLayer)Map.Layers[0]).TileInfo.Lods[Convert.ToInt32(e.NewValue)].Resolution);
    48.             }
    49.         }
    50.         private void map_ExtentChanged(object o, ESRI.ArcGIS.ExtentEventArgs e)
    51.         {
    52.             ESRI.ArcGIS.ArcGISTiledMapServiceLayer layer = Map.Layers[0] as ESRI.ArcGIS.ArcGISTiledMapServiceLayer;
    53.             int i;
    54.             for (i = 0; i < layer.TileInfo.Lods.Length; i++)
    55.             {
    56.                 if (Map.Resolution == layer.TileInfo.Lods[i].Resolution)
    57.                     break;
    58.             }
    59.             sliderLOD.Value = i;
    60.         }
    61.         private void btnzoomin_Click(object sender, RoutedEventArgs e)
    62.         {
    63.             sliderLOD.Value += 1;
    64.         }
    65.         private void btnzoomout_Click(object sender, RoutedEventArgs e)
    66.         {
    67.             sliderLOD.Value -= 1;
    68.         }
    69.     }
    70.     //执行了这个接口后,当在主页面page.xaml.cs中给Map赋值的时候,就能返到set语句中,以便执行绑定事件的代码
    71.     public class mymap:INotifyPropertyChanged
    72.     {
    73.         private ESRI.ArcGIS.Map map;
    74.         public ESRI.ArcGIS.Map Map
    75.         {
    76.             get{return map;}
    77.             set
    78.             {
    79.                 map = value;
    80.                 if (PropertyChanged!=null)
    81.                 {
    82.                     PropertyChanged(this, new PropertyChangedEventArgs("Map"));
    83.                 }
    84.             }
    85.         }
    86.         public event PropertyChangedEventHandler PropertyChanged;
    87.     }
    88. }
    复制代码

    做完封装的工作,来看如何在page.xaml中使用这个控件。只需要三行代码:1、注册user control的命名空间(和对Silverlight API的引用是一样的,放在页面中的根元素UserControl里):
    xmlns:uc="clr-namespace:customcontrol"
            2、在页面中添加这个slider:
    <Grid x:Name="LayoutRoot" Background="White">
            <!--地图在这里-->
            </esri:Map>
            
            <uc:mapslider x:Name="mapslider1"/>
    </Grid>
            3、在初始化的时候对我们自定义控件的Map属性赋值(page.xaml.cs中):
    public Page()
          {
              InitializeComponent();
              mapslider1.Map = Map1;
          }
            到此应该有这个感觉,封装比较麻烦,但使用封装好的控件非常简便。这就是Widgets带给我们的好处。目前的beta版中,SilverlightAPI已经替我们完成5个Widgets的封装,它们分别是:Magnifier,ToolBar,BookMark,Navigation,MapTip,其中ToolBar内部使用了ToolBarItemCollection和ToolBarItem等类。还是通过一个例子,来看看这几个控件都长什么样吧(点击这里):

     



            MapTip需要使用到Query Task,以后的小节中再涉及到。现在分别熟悉一下这几个Widgets的用法。
    1、ToolBar和Magnifier:
            这个和ADF开发中的ToolBar(工具条)是一样的,里面可以添加ToolItem(工具),已实现各种功能,比如平移,缩放等。silverlight中当然要有一些比较好看的效果了,比如把鼠标放在工具条上选择工具的时候,会有放大效果,这个效果是默认的,不能设置;点击一个工具时,该工具会跳动一下,这个是ToolbarItemClickEffect中的Bounce效果(目前只有Bounce和None两个选择),也是默认的。此例中ToolBar里面有三个ToolBarItem,分别是Pan,FullExtent和Magnifier(本身也是一个Widget),下面是ToolBar的布局:

    1. <Grid Height="110" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,10,0" >
    2.             <Rectangle Fill="#22000000" RadiusX="10" RadiusY="10" Margin="0,4,0,0" />
    3.             <Rectangle Fill="#775C90B2" Stroke="Gray"  RadiusX="10" RadiusY="10" Margin="0,0,0,5" />
    4.             <Rectangle Fill="#66FFFFFF" Stroke="DarkGray" RadiusX="5" RadiusY="5" Margin="10,10,10,15" />
    5.             <StackPanel Orientation="Vertical">
    6.                 <esriWidgets:Toolbar x:Name="MyToolbar" MaxItemHeight="80" MaxItemWidth="80"
    7.                     VerticalAlignment="Top" HorizontalAlignment="Center"
    8.                     ToolbarItemClicked="MyToolbar_ToolbarItemClicked"
    9.                     ToolbarItemClickEffect="Bounce"
    10.                     Width="250" Height="80">
    11.                     <esriWidgets:Toolbar.Items>
    12.                         <esriWidgets:ToolbarItemCollection>
    13.                             <esriWidgets:ToolbarItem Text="Pan">
    14.                                 <esriWidgets:ToolbarItem.Content>
    15.                                     <Image Source="img/i_pan.png" Stretch="UniformToFill" Margin="5" />
    16.                                 </esriWidgets:ToolbarItem.Content>
    17.                             </esriWidgets:ToolbarItem>
    18.                             <esriWidgets:ToolbarItem Text="Full Screen">
    19.                                 <esriWidgets:ToolbarItem.Content>
    20.                                     <Image Source="img/i_globe.png" Stretch="UniformToFill" Margin="5" />
    21.                                 </esriWidgets:ToolbarItem.Content>
    22.                             </esriWidgets:ToolbarItem>
    23.                             <esriWidgets:ToolbarItem Text="Full Screen">
    24.                                 <esriWidgets:ToolbarItem.Content>
    25.                                     <Image Source="img/magglass.png" Stretch="UniformToFill" Margin="5"
    26.                                            MouseLeftButtonDown="Image_MouseLeftButtonDown"/>
    27.                                 </esriWidgets:ToolbarItem.Content>
    28.                             </esriWidgets:ToolbarItem>
    29.                         </esriWidgets:ToolbarItemCollection>
    30.                     </esriWidgets:Toolbar.Items>
    31.                 </esriWidgets:Toolbar>
    32.                 <TextBlock x:Name="StatusTextBlock" Text="" FontWeight="Bold" HorizontalAlignment="Center"/>
    33.             </StackPanel>
    34.         </Grid>
    复制代码

    然后是code-behind内容:
    private void MyToolbar_ToolbarItemClicked(object sender, ESRI.ArcGIS.Widgets.SelectedToolbarItemArgs e)
            {
                switch (e.Index)
                {
                    case 0:
                        //pan
                        break;
                    case 1:
                        Map1.ZoomTo(Map1.Layers.GetFullExtent());
                        break;
                    case 2:
                        break;
                }
            }

            private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                MyMagnifier.Enabled = !MyMagnifier.Enabled;
            }
            别忘了在page的构造函数中加一句:MyMagnifier.Initialize(Map1);。可以看出,Pan工具不需要任何代码,因为地图本身的默认动作就是Pan,而FullExtent也是利用了Map的ZoomTo()。放大镜的工具是在该图片被鼠标左键按住的过程中激活的(设置enabled属性),只要鼠标左键没有按住放大镜图片,该Widget就设置为不可用。比较有用的是我们可以单独设置放大镜自己的图层及放大倍数,这里放大镜使用的就是StreetMap,倍数为3。
    2、BookMark:
            这个功能和ArcMap(9.3版本)中的BookMark是一样的,可以像看书一样,为当前地图范围设置一个书签,便于其他时候快速定位到该范围。而查看API中的Bookmark.MapBookmark类(可以利用它对书签的内容进行单个添加或删除),可以发现其实每个书签存储的内容是一个Extent,然后再起一个名字就可以了。添加了bookmark widget后似乎会造成vs中的preview窗口出错。
    <!--bookmark-->
            <Canvas>
                <esriWidgets:Bookmark x:Name="MyBookmarks" Width="125" HorizontalAlignment="Left" VerticalAlignment="Top"
                 Margin="20" Background="#99257194" BorderBrush="#FF92a8b3" Foreground="Black"
                 Loaded="MyBookmarks_Loaded" />
            </Canvas>
    page.xaml.cs中:
    private void MyBookmarks_Loaded(object sender, RoutedEventArgs e)
            {
                MyBookmarks.Map = Map1;
            }
    3、Navigation:
            这个导航条工具是目前网络地图必备的一个控件,但silverlight的功能,可以轻易实现地图的旋转(其实也可以在代码中通过Map.Rotation属性来设置)。经试验这个widget只能放在StackPanel或Grid容器里,如果放在Canvas里的话地图中不会显示。
    <!--navigation bar.must be in a stackpanel-->
            <StackPanel HorizontalAlignment="Left" VerticalAlignment="Bottom">
                <esriWidgets:Navigation x:Name="MyNavigation" Margin="5"  />
            </StackPanel>
            同样在page的构造函数中添加一句:MyNavigation.Map = Map1;。
            API中的Widgets可以简化我们的工作,拿来即用。但明显的缺陷就是不灵活,如果想使自己的控件不那么千篇一律的话,就需要自己进行开发工作了。
            好了,下一节中来学习一个比较重要的概念:GraphicsLayer。

  • 相关阅读:
    关于用wubi安装Ubuntu,总是提示“没有定义根文件系统”的问题
    linux驱动---字符设备的注册register_chrdev说起
    面试汇总
    面试题(redis)
    面试题(restful)
    面试题(数据库)
    你常用的模块?
    falsk
    面试题
    浅谈virtualenv(虚拟环境)
  • 原文地址:https://www.cnblogs.com/xingchen/p/1969040.html
Copyright © 2011-2022 走看看