WebGIS實現要素在線編輯之Silverlight調用FeatureService實現編輯功能


      在本文中,實現對污染源數據的管理主要是通過FeatureService,FeatureService支持在線的地理要素編輯,並且可以將要素編輯的結果更新至后台的數據庫中。在本文中,通過將之前新建的污染源數據庫點要素添加到MXD文檔中,然后將其發布成FeatureService(具體如何發布請看另一篇博文——http://www.cnblogs.com/potential/archive/2012/11/03/2752796.html)。

      在ArcGIS API for Silverlight中,提供了的EditorWidget工具,通過該工具即可實現對ArcSDE中地理要素的訪問並進行相關的編輯。

      ArcGIS API for Silverlight中提供的EditorWidget工具包含了要素屬性的編輯,要素形狀的編輯,要素選中要素,刪除要素等。下面就來看一下具體過程。

      新建一個項目:    

項目瀏覽:

之后我們在Expression Blend中編輯界面。大致設計如下:

基本控件列表:

這里我們聲明了一個EditorWidget以及一個FeatureDataForm。我們主要用EditorWidget來實現要素的添加和刪除,而用FeatureDataForm來實現要素屬性的編輯。注意:EditorWidget本身也具有編輯要素屬性的功能。FeatureDataForm同樣支持更新數據到數據庫,但是他只能修改已有的要素,不能執行添加要素的功能,一般用來編輯某一要素的屬性或者顯示某一要素的屬性信息。

在建立好基本的界面之后,下面開始正式的工作:

1. 我們需要添加一個供我們編輯的要素圖層:FeatureLayer.在上一篇中已經講了如何發布要素服務,這里我們引用上一篇發布的要素服務。示例代碼如下:

<esri:Map x:Name="MyMap" Background="White" WrapAround="True" Grid.RowSpan="2">
            <!--底圖圖層-->
            <esri:ArcGISTiledMapServiceLayer Url="http://www.arcgisonline.cn/ArcGIS/rest/services/ChinaOnlineStreetWarm/MapServer"/>
            <!--需要編輯的要素圖層-->
            <esri:FeatureLayer ID="SourceLayer" DisableClientCaching="True" 
                               AutoSave="False"
                               OutFields="*"
                               Mode="OnDemand"
                               Url="http://qzj-pc/ArcGIS/rest/services/RiverSourceMap/FeatureServer/0"/>
        </esri:Map>

以上我們添加了兩個圖層,一個是底圖圖層,一個是我們要編輯的要素圖層。同時我們這里對要素圖層進行了相關的設置。下面對FeatureLayer重要的屬性進行一下說明:

OutFields: OutFields類型是一個字符串數組,表示該圖層的要素暴露那些字段(屬性),也就是說用戶可見的屬性有哪些。比如上一篇我們定義了一個點要素,並添加了一系列的屬性,如排放量,負責人,運行狀態,經緯度等,而我現在並不想將這些信息展示給客戶端,不想這些信息都被用戶看見,那么我們通過設置這里的OutFields暴露的字段來實現。

AutoSave:表示是否自動保存圖層要素更改的信息。

Url:表示該要素圖層的地址,比如上一篇我們介紹了如何發布FeatureService,這里你就可以將地址修改為你自己發布的FeatureService地址。

2. 設置EditorWidget屬性。

示例代碼如下:

<esri:EditorWidget HorizontalAlignment="Left" 
                           Margin="20,20,0,0" 
                           Grid.Row="1" 
                           VerticalAlignment="Top" 
                           Background="{StaticResource Brush1}"
                           Map="{Binding ElementName=MyMap}"
                           AutoSelect="False"
                           AlwaysDisplayDefaultTemplates="True"
                           GeometryServiceUrl="http://qzj-pc/ArcGIS/rest/services/Geometry/GeometryServer"
                           ShowAttributesOnAdd="False"/>

EditorWidget重要屬性的說明:

Map:表示EditorWidget編輯對應的地圖是那個地圖,綁定之后我們只能編輯指定地圖中的要素圖層。

AutoSelect:表示是否自動選擇要素。

AlwaysDisplayDefaultTemplates:表示是否顯示默認的模版。

ShowAttributesOnAdd:表示在添加要素時是否顯示其屬性。

GeometryServiceUrl:表示幾何服務的地址,該幾何服務將用於要素的編輯,例如移動要素,編輯多變的形狀等。

LayerIDs:指定該編輯工具具體要編輯那幾個要素圖層,這些要素圖層必須位置Map綁定的地圖中,LayerIDs是一個字符串數組類型,不能在xaml中指定其屬性值,只能在后台代碼中指定。

3.設置FeatureDataForm的相關屬性

示例代碼如下:

<esri:FeatureDataForm HorizontalAlignment="Right" 
                              Grid.Row="1" 
                              VerticalAlignment="Bottom" 
                              Margin="0,0,20,20"
Visibility="Collapsed"
Background="{StaticResource Brush1}" x:Name="MyFeatureDataForm" FeatureLayer="{Binding Path=Layers[SourceLayer], ElementName=MyMap}" IsReadOnly="False" LabelPosition="Left"/>

FeatureDataForm重要屬性的說明:

FeatureLayer:指定該FeatureDataForm是要顯示那一個要素圖層的信息(也就是被顯示的要素位於那個FeatureLayer中)當被顯示的要素來自於不同的要素圖層時,不用在此綁定,可在后台代碼中動態的指定。這里我們默認設置初始時不可見。

完成了對基本控件的屬性設置后,我們開始在后台代碼中編寫相關的控制代碼。

最后的XAML中的代碼應該是這樣的:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:esri="http://schemas.esri.com/arcgis/client/2009" 
    x:Class="FeatureServiceTest.MainPage"
    mc:Ignorable="d"
    d:DesignHeight="357" d:DesignWidth="508">
    <UserControl.Resources>
        <LinearGradientBrush x:Key="Brush1" EndPoint="1.009,0.82" StartPoint="0.001,0.039">
            <GradientStop Color="#1970A14A" Offset="0"/>
            <GradientStop Color="#994795A9"/>
            <GradientStop Color="#7F859797"/>
            <GradientStop Color="#663EA4B8"/>
            <GradientStop Color="#CC296F81" Offset="0.59"/>
            <GradientStop Color="#B299A7A3" Offset="1"/>
            <GradientStop Color="#72B2D8CB"/>
            <GradientStop Color="#7F5FB4A7" Offset="0.262"/>
        </LinearGradientBrush>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="0.193*"/>
            <RowDefinition Height="0.807*"/>
        </Grid.RowDefinitions>
        <!--Map控件-->
        <esri:Map Background="White" WrapAround="True" Grid.RowSpan="2" x:Name="MyMap">
            <!--地圖圖層-->
            <esri:ArcGISTiledMapServiceLayer Url="http://www.arcgisonline.cn/ArcGIS/rest/services/ChinaOnlineStreetWarm/MapServer"/>
            <!--需要編輯的要素圖層-->
            <esri:FeatureLayer ID="SourceLayer" DisableClientCaching="True" 
                               AutoSave="False"
                               OutFields="*"
                               Mode="OnDemand"
                               Url="http://qzj-pc/ArcGIS/rest/services/RiverSourceMap/FeatureServer/0"/>
        </esri:Map>
        <!--標題的背景框-->
        <Rectangle Fill="{StaticResource Brush1}">
            <Rectangle.Effect>
                <DropShadowEffect/>
            </Rectangle.Effect>
        </Rectangle>
        <!--標題-->
        <TextBlock TextWrapping="Wrap" Text="要素在線編輯" FontSize="48" VerticalAlignment="Center" Foreground="#FF1A1717" Margin="50,0,0,0">
            <TextBlock.Effect>
                <DropShadowEffect/>
            </TextBlock.Effect>
        </TextBlock>
        <!--要素編輯的控件-->
        <esri:EditorWidget x:Name="MyEditorWidget"
HorizontalAlignment="Left" Margin="20,20,0,0" Grid.Row="1" VerticalAlignment="Top" Background="{StaticResource Brush1}" Map="{Binding ElementName=MyMap}" AutoSelect="False" AlwaysDisplayDefaultTemplates="True" GeometryServiceUrl="http://qzj-pc/ArcGIS/rest/services/Geometry/GeometryServer" ShowAttributesOnAdd="False"/> <!--顯示要素屬性以及編輯屬性的FeatureDataForm--> <esri:FeatureDataForm HorizontalAlignment="Right" Grid.Row="1" VerticalAlignment="Bottom" Margin="0,0,20,20"
Visibility="Collapsed"
Background="{StaticResource Brush1}" x:Name="MyFeatureDataForm" FeatureLayer="{Binding Path=Layers[SourceLayer], ElementName=MyMap}" IsReadOnly="False" LabelPosition="Left"/> </Grid> </UserControl>

4.Coding Behind

首先我們注冊以下幾個事件:

EditorWidget控件:Loaded事件(必選)

FeatureDataForm控件:EditEnded事件(可選,我們想在編輯完成時關閉FeatureDataForm)

FeatureLayer圖層:MouseLeftButtonDown事件(可選,這里我們想實現點擊某一要素時,顯示其具體信息)

注意:這里不建議在XAML代碼中注冊事件,最好將注冊事件和xaml代碼分離。

我們在MainPage.xaml.cs的MainPage()構造函數中注冊以上的事件:

這時我們的后台代碼如下所示,我們還沒有添加相關的事件操作。

using System;
using System.Windows;
using System.Windows.Controls;
using ESRI.ArcGIS.Client;
namespace FeatureServiceTest
{
    public partial class MainPage : UserControl
    {
        //聲明一個FeatureLayer變量,用來獲取編輯的要素圖層
        private FeatureLayer MyFeatureLayer;
        public MainPage()
        {
            InitializeComponent();
            //將Map中的SourceLayer要素圖層賦給MyFeatureLayer。
            MyFeatureLayer = MyMap.Layers["SourceLayer"] as FeatureLayer;
            //注冊要素圖層MouseLeftButtonDown事件
            MyFeatureLayer.MouseLeftButtonDown += FeatureLayer_MouseLeftButtonDown;
            //注冊EditorWidget的Loaded事件
            MyEditorWidget.Loaded += EditorWidget_Loaded;
            //注冊FeatureDataForm的EditEnded事件
            MyFeatureDataForm.EditEnded += MyFeatureDataForm_EditEnded; 
        }

        private void MyFeatureDataForm_EditEnded(object sender, EventArgs e)
        {

        }

        private void EditorWidget_Loaded(object sender, RoutedEventArgs e)
        {

        }

        private void FeatureLayer_MouseLeftButtonDown(object sender, ESRI.ArcGIS.Client.GraphicMouseButtonEventArgs e)
        {

        }
    }
}

接下來需要完成的工作是:

1.在EditorWidget_Loaded方法中指定EditorWidget編輯的要素圖層

  private void EditorWidget_Loaded(object sender, RoutedEventArgs e)
        {
            string[] layerIDs = {"SourceLayer"};
            MyEditorWidget.LayerIDs = layerIDs;
        }

2.在FeatureLayer_MouseLeftButtonDown方法中添加相應的處理代碼

這里需要實現的方法是:點擊不同的要素(點要素),則顯示其相應的屬性信息。這里我們只需要將FeatureDataForm的GraphicSource屬性綁定到我們點擊的Graphic即可。示例代碼如下:

 private void FeatureLayer_MouseLeftButtonDown(object sender, ESRI.ArcGIS.Client.GraphicMouseButtonEventArgs e)
        {
            FeatureLayer featureLayer = sender as FeatureLayer;

            foreach (Graphic g in featureLayer.Graphics)
                if (g.Selected)
                    g.UnSelect();

            e.Graphic.Select();
            MyFeatureDataForm.GraphicSource = e.Graphic;
            MyFeatureDataForm.Visibility = Visibility.Visible;
        }

在上一篇中我們建立的點要素包含了經緯度信息,這里我們想在添加點要素時根據其在地圖上的位置來自動設置其經緯度屬性。

現在我們聲明一個類級別的變量:

private static ESRI.ArcGIS.Client.Projection.WebMercator _mercator =
        new ESRI.ArcGIS.Client.Projection.WebMercator();

WebMercator變量的作用可用於坐標系之間的相互轉換,它具有兩個方法:


FromGeographic:將幾何要素的坐標系從4326坐標系轉換到102100坐標系

ToGeographic:將幾何要素的坐標系從102100坐標系轉換到4326坐標系

此外每一個點要素實際上也是一個MapPoint,MapPoint具有X,Y屬性,在102100坐標系中是以米為單位表示點的坐標。因此通過將點要素轉化為MapPoint,然后通過ToGeographic方法轉化成4326坐標系下的點,然后再獲得其X,Y,即可得相應的經緯度。最后賦給點要素的經緯度屬性。示例代碼如下:

//將120010坐標系,轉換為4326下的坐標系
            MapPoint mapPoint = _mercator.ToGeographic(e.Graphic.Geometry) as MapPoint;
            //自動的添加 經緯度
            e.Graphic.Attributes["Longitude"] = mapPoint.X;
           
e.Graphic.Attributes[
"Latitude"] = mapPoint.Y;

 

3.在MyFeatureDataForm_EditEnded中添加退出編輯代碼,即關閉FeatureDataForm,並清空其數據源。

  private void MyFeatureDataForm_EditEnded(object sender, EventArgs e)
        {
            MyFeatureDataForm.GraphicSource = null;
            MyFeatureDataForm.Visibility = Visibility.Collapsed;
        }


這樣所有的工作便已經完成,此時后台的代碼應該如下所示:

using System;
using System.Windows;
using System.Windows.Controls;
using ESRI.ArcGIS.Client;
using ESRI.ArcGIS.Client.Geometry;

namespace FeatureServiceTest
{
    public partial class MainPage : UserControl
    {
        ESRI.ArcGIS.Client.Projection.WebMercator _mercator =
       new ESRI.ArcGIS.Client.Projection.WebMercator();
        //聲明一個FeatureLayer變量,用來獲取編輯的要素圖層
        private FeatureLayer MyFeatureLayer;
        public MainPage()
        {
            InitializeComponent();
            //將Map中的SourceLayer要素圖層賦給MyFeatureLayer。
            MyFeatureLayer = MyMap.Layers["SourceLayer"] as FeatureLayer;
            //注冊要素圖層MouseLeftButtonDown事件
            MyFeatureLayer.MouseLeftButtonDown += FeatureLayer_MouseLeftButtonDown;
            //注冊EditorWidget的Loaded事件
            MyEditorWidget.Loaded += EditorWidget_Loaded;
            //注冊FeatureDataForm的EditEnded事件
            MyFeatureDataForm.EditEnded += MyFeatureDataForm_EditEnded; 
        }

        private void MyFeatureDataForm_EditEnded(object sender, EventArgs e)
        {
            MyFeatureDataForm.GraphicSource = null;
            MyFeatureDataForm.Visibility = Visibility.Collapsed;
        }

        private void EditorWidget_Loaded(object sender, RoutedEventArgs e)
        {
            string[] layerIDs = {"SourceLayer"};
            MyEditorWidget.LayerIDs = layerIDs;
        }

        private void FeatureLayer_MouseLeftButtonDown(object sender, ESRI.ArcGIS.Client.GraphicMouseButtonEventArgs e)
        {
            FeatureLayer featureLayer = sender as FeatureLayer;

            foreach (Graphic g in featureLayer.Graphics)
                if (g.Selected)
                    g.UnSelect();

            e.Graphic.Select();
         
            //將120010坐標系,轉換為4326下的坐標系
            MapPoint mapPoint = _mercator.ToGeographic(e.Graphic.Geometry) as MapPoint;
            //自動的添加 經緯度
              e.Graphic.Attributes["Longitude"] = mapPoint.X;
            e.Graphic.Attributes["Latitude"] = mapPoint.Y;

            MyFeatureDataForm.GraphicSource = e.Graphic;
            MyFeatureDataForm.Visibility = Visibility.Visible;
        }
    }
}

下面來看看運行的效果以及觀察是否能夠更新編輯到數據庫。

點擊要素,會自動根據點要素在地圖中的坐標為其經緯度屬性賦值

注意下圖:這里運行狀態屬性欄,我們發現是下拉框,只能選擇運行狀態和關閉狀態。這就是我們在上一篇說的設置屬性域起的作用。

 

 時間屬性只允許我們輸入時間。這也是由於我們之前設置對時間屬性應用了屬性域的原因。

 最后編輯完成之后點擊保存按鈕。

驗證是否保存成功,打開ArcCatalog,瀏覽到Feature Service使用的地理數據庫,打開我們在Feature Service使用的要素屬性表,就會發現所以的更改已保存到了數據庫。

至此,關於在線要素編輯的講解已經全部完成。

(版權所有,轉載請標明出處)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM