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。

  • 相关阅读:
    洛谷 P1508 Likecloud-吃、吃、吃
    Codevs 1158 尼克的任务
    2017.10.6 国庆清北 D6T2 同余方程组
    2017.10.6 国庆清北 D6T1 排序
    2017.10.3 国庆清北 D3T3 解迷游戏
    2017.10.3 国庆清北 D3T2 公交车
    2017.10.3 国庆清北 D3T1 括号序列
    2017.10.4 国庆清北 D4T1 财富
    2017.10.7 国庆清北 D7T2 第k大区间
    2017.10.7 国庆清北 D7T1 计数
  • 原文地址:https://www.cnblogs.com/xingchen/p/1969040.html
Copyright © 2011-2022 走看看