FeatureLayer featureLayer = new FeatureLayer(); featureLayer.ID = "blah"; featureLayer.OutFields.Add("*"); featureLayer.Url = arcGisLocalDynamicMapServiceLayer.Url + "/dynamicLayer"; featureLayer.Source = new LayerDataSource() { DataSource = dataSource }; featureLayer.Initialized += (s1, e1) => { MyDataGrid.Map = MyMap; MyDataGrid.GraphicsLayer = featureLayer as GraphicsLayer; }; // featureLayer.Initialize(); // You only need to call initialize if not adding layer to map. MyMap.Layers.Add(featureLayer);
dataSource = new TableDataSource { // Match the DataSourceName to the physical filename on disk (excluding extension). DataSourceName = fileName, // Provide the WorkspaceID (the unique workspace identifier created earlier). A LocalMapService may have multiple dynamic workspaces. WorkspaceID = workspaceInfo.Id };
featureLayer.Initialized += (s1, e1) => { featureLayer.UpdateCompleted += (s2, e2) => { // Assign Map and GraphicsLayer property in UpdateCompleted event (probbaly optional) MyDataGrid.Map = MyMap; MyDataGrid.GraphicsLayer = featureLayer as GraphicsLayer; }; featureLayer.Update(); // Call Update explicitly, that will populate the layer wiht features (and therefore populate the grid) }; featureLayer.Initialize(); //MyMap.Layers.Add(featureLayer);
private void AddFeatureLayerFromShapeFile(ArcGISLocalDynamicMapServiceLayer dynamicLayer) { var featureLayer = new FeatureLayer(); featureLayer.ID = "blah"; featureLayer.OutFields.Add("*"); featureLayer.Mode = FeatureLayer.QueryMode.OnDemand; featureLayer.OnDemandCacheSize = 500; //featureLayer.MaximumResolution = 25; featureLayer.Url = dynamicLayer.Url + "/" + dynamicLayer.DynamicLayerInfos[0].ID; featureLayer.Source = dynamicLayer.DynamicLayerInfos[0].Source; featureLayer.Initialized += (s1, e1) => { }; MyMap.Layers.Add(featureLayer); }
/// <summary> /// Interaction logic for DynamicLayersFeatureDataGrid.xaml /// </summary> public partial class DynamicLayersFeatureDataGrid : UserControl { // Get the path of the "empty" MPK from the application folder string _emptyMpkPath = @"..\Data\DynamicLayers\EmptyMPK_WGS84.mpk"; public DynamicLayersFeatureDataGrid() { InitializeComponent(); MyDataGrid.SelectionChanged += (s3, e3) => { foreach (Graphic graphic in e3.RemovedItems) { graphic.SetZIndex(0); } foreach (Graphic graphic in e3.AddedItems) { graphic.SetZIndex(1); } }; } /// <summary> /// Handles the Click event of the AddShapefileButton control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param> private void AddShapefileButton_Click(object sender, RoutedEventArgs e) { // Setup the OpenFiledialog. OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Shapefiles (*.shp)|*.shp"; openFileDialog.RestoreDirectory = true; openFileDialog.Multiselect = false; // This sample assumes a single file is selected if (openFileDialog.ShowDialog() == true) { try { // Remove any existing FeatureLayers in the Map List<FeatureLayer> featureLayers = MyMap.Layers.OfType<FeatureLayer>().ToList(); foreach (var fl in featureLayers) { MyMap.Layers.Remove(fl); } // Call the add dataset method with workspace type, parent directory path, file names (without extensions) and delegate. AddFileDatasetToDynamicMapServiceLayer(WorkspaceFactoryType.Shapefile, Path.GetDirectoryName(openFileDialog.FileName), Path.GetFileNameWithoutExtension(openFileDialog.SafeFileName)); } catch (Exception ex) { MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); } } } /// <summary> /// Adds a file dataset (Shapefile) to a new feature layer. /// </summary> /// <param name="workspaceType">The workspace type (FileGDB, Raster, SDE, Shapefile) <see cref="http://resources.arcgis.com/en/help/runtime-wpf/apiref/index.html?ESRI.ArcGIS.Client.Local~ESRI.ArcGIS.Client.Local.WorkspaceFactoryType.html"/>.</param> /// <param name="directoryPath">A <see cref="System.String"/> representing the directory path.</param> /// <param name="fileNames">A <see cref="System.Collections.Generic.List{System.String}"/> representing the name of the file.</param> public void AddFileDatasetToDynamicMapServiceLayer(WorkspaceFactoryType workspaceType, string directoryPath, string fileName) { try { // Generate a unique workspace ID (any unique string). string uniqueId = Guid.NewGuid().ToString(); // Create a new WorkspaceInfo object with a unique ID. WorkspaceInfo workspaceInfo = new WorkspaceInfo(uniqueId, workspaceType, "DATABASE=" + directoryPath); // Create a new LocalMapService instance. LocalMapService localMapService = new LocalMapService { Path = _emptyMpkPath, // Set the path property. EnableDynamicLayers = true, // Enable the dynamic layers capability. MaxRecords = 1000000, // Set the maximum number of records }; // Register the workspace to be used with this service. localMapService.DynamicWorkspaces.Add(workspaceInfo); // Asynchronously start the local map service. localMapService.StartAsync(x => { // Create a new ArcGISLocalDynamicMapServiceLayer passing in the newly started local service. FeatureLayer featureLayer = new FeatureLayer() { Url = localMapService.UrlMapService + "/dynamicLayer", // Construct the URL to include the /dynamicLayer resource. ID = fileName, // Assign ID OutFields = new ESRI.ArcGIS.Client.Tasks.OutFields() { "*" }, // Display all fields SelectionColor = new SolidColorBrush(Colors.Yellow), // Yellow is generally a nice selection color }; // The workspace is a feature class so create a new TableDataSource DataSource dataSource = new TableDataSource { DataSourceName = fileName, // Match the DataSourceName to the physical filename on disk (excluding extension). WorkspaceID = workspaceInfo.Id // Provide the WorkspaceID (the unique workspace identifier created earlier). }; // Set the Source property of the DynamicLayerInfo object. LayerDataSource layerDataSource = new LayerDataSource { DataSource = dataSource }; // Assign the LayerDataSource featureLayer.Source = layerDataSource; featureLayer.Initialized += (s, e) => { // Set the FeatureDataGrid's Map property MyDataGrid.Map = MyMap; // Set the new FeatureLayer as the FeatureDataGrid's GraphicsLayer property MyDataGrid.GraphicsLayer = featureLayer as GraphicsLayer; SimpleRenderer renderer = null; switch (featureLayer.LayerInfo.GeometryType) { case ESRI.ArcGIS.Client.Tasks.GeometryType.MultiPoint: renderer = new SimpleRenderer() { Symbol = new SimpleMarkerSymbol() { Color = new SolidColorBrush(GetRandomColor()), Size = 8 } }; break; case ESRI.ArcGIS.Client.Tasks.GeometryType.Point: renderer = new SimpleRenderer() { Symbol = new SimpleMarkerSymbol() { Color = new SolidColorBrush(GetRandomColor()), Size = 8 } }; break; case ESRI.ArcGIS.Client.Tasks.GeometryType.Polygon: renderer = new SimpleRenderer() { Symbol = new SimpleFillSymbol() { Fill = new SolidColorBrush(GetRandomColor()), BorderBrush = new SolidColorBrush(GetRandomColor()) } }; break; case ESRI.ArcGIS.Client.Tasks.GeometryType.Polyline: renderer = new SimpleRenderer() { Symbol = new SimpleLineSymbol() { Color = new SolidColorBrush(GetRandomColor()) } }; break; default: break; } featureLayer.Renderer = renderer; }; MyMap.Layers.Add(featureLayer); }); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } // Utility function: Generate a random System.Windows.Media.Color Random _random = new Random(); private Color GetRandomColor() { var colorBytes = new byte[3]; _random.NextBytes(colorBytes); Color randomColor = Color.FromRgb(colorBytes[0], colorBytes[1], colorBytes[2]); return randomColor; } private void Legend_Refreshed(object sender, Legend.RefreshedEventArgs e) { // Clear the sub items from the basemap layer. if (e.LayerItem.Layer == _worldTopographicBasemap) e.LayerItem.LayerItems.Clear(); } }
In OnDemand mode the FeatureLayer should be retrieving features for the map extent, which means you will have some duplication of content in the map. It would probabaly be better to set the FeatureLayer to SelectionOnly mode if you're using the dynamic map service layer for display purposes. In that case, only the features you select on the map will be displayed in the FeatureDataGrid. Here's an example in SL: http://resources.arcgis.com/en/help/silverlight-api/samples/start.htm#AttributeOnlyEditing (sorry - we haven't had time to port to WPF yet).
Regarding the selection issue - are you setting the Map property of the Editor in XAML? You'll need to set the Editor.Map after InitializeComponent() because WPF element-binding does not resolve when part of resource.
Hi,
I had a revelation that actually I'd probably confused the issue by keeping the ArcGISDynamicMapServiceLayer in my example whilst introducing a FeatureLayer as well. So I've simplified it to just use a FeatureLayer (below). So it now assumes that you actually want to add the FeatureLayer to the map and display that instead of the ArcGISDynamicMapServiceLayer. I'd recommend you definitely use the accelerated display mode if the feature layer may contain many thousands of graphics, or graphics with complex polygons.
Code:/// <summary> /// Interaction logic for DynamicLayersFeatureDataGrid.xaml /// </summary> public partial class DynamicLayersFeatureDataGrid : UserControl { // Get the path of the "empty" MPK from the application folder string _emptyMpkPath = @"..\Data\DynamicLayers\EmptyMPK_WGS84.mpk"; public DynamicLayersFeatureDataGrid() { InitializeComponent(); MyDataGrid.SelectionChanged += (s3, e3) => { foreach (Graphic graphic in e3.RemovedItems) { graphic.SetZIndex(0); } foreach (Graphic graphic in e3.AddedItems) { graphic.SetZIndex(1); } }; } /// <summary> /// Handles the Click event of the AddShapefileButton control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param> private void AddShapefileButton_Click(object sender, RoutedEventArgs e) { // Setup the OpenFiledialog. OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Shapefiles (*.shp)|*.shp"; openFileDialog.RestoreDirectory = true; openFileDialog.Multiselect = false; // This sample assumes a single file is selected if (openFileDialog.ShowDialog() == true) { try { // Remove any existing FeatureLayers in the Map List<FeatureLayer> featureLayers = MyMap.Layers.OfType<FeatureLayer>().ToList(); foreach (var fl in featureLayers) { MyMap.Layers.Remove(fl); } // Call the add dataset method with workspace type, parent directory path, file names (without extensions) and delegate. AddFileDatasetToDynamicMapServiceLayer(WorkspaceFactoryType.Shapefile, Path.GetDirectoryName(openFileDialog.FileName), Path.GetFileNameWithoutExtension(openFileDialog.SafeFileName)); } catch (Exception ex) { MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); } } } /// <summary> /// Adds a file dataset (Shapefile) to a new feature layer. /// </summary> /// <param name="workspaceType">The workspace type (FileGDB, Raster, SDE, Shapefile) <see cref="http://resources.arcgis.com/en/help/runtime-wpf/apiref/index.html?ESRI.ArcGIS.Client.Local~ESRI.ArcGIS.Client.Local.WorkspaceFactoryType.html"/>.</param> /// <param name="directoryPath">A <see cref="System.String"/> representing the directory path.</param> /// <param name="fileNames">A <see cref="System.Collections.Generic.List{System.String}"/> representing the name of the file.</param> public void AddFileDatasetToDynamicMapServiceLayer(WorkspaceFactoryType workspaceType, string directoryPath, string fileName) { try { // Generate a unique workspace ID (any unique string). string uniqueId = Guid.NewGuid().ToString(); // Create a new WorkspaceInfo object with a unique ID. WorkspaceInfo workspaceInfo = new WorkspaceInfo(uniqueId, workspaceType, "DATABASE=" + directoryPath); // Create a new LocalMapService instance. LocalMapService localMapService = new LocalMapService { Path = _emptyMpkPath, // Set the path property. EnableDynamicLayers = true, // Enable the dynamic layers capability. MaxRecords = 1000000, // Set the maximum number of records }; // Register the workspace to be used with this service. localMapService.DynamicWorkspaces.Add(workspaceInfo); // Asynchronously start the local map service. localMapService.StartAsync(x => { // Create a new ArcGISLocalDynamicMapServiceLayer passing in the newly started local service. FeatureLayer featureLayer = new FeatureLayer() { Url = localMapService.UrlMapService + "/dynamicLayer", // Construct the URL to include the /dynamicLayer resource. ID = fileName, // Assign ID OutFields = new ESRI.ArcGIS.Client.Tasks.OutFields() { "*" }, // Display all fields SelectionColor = new SolidColorBrush(Colors.Yellow), // Yellow is generally a nice selection color }; // The workspace is a feature class so create a new TableDataSource DataSource dataSource = new TableDataSource { DataSourceName = fileName, // Match the DataSourceName to the physical filename on disk (excluding extension). WorkspaceID = workspaceInfo.Id // Provide the WorkspaceID (the unique workspace identifier created earlier). }; // Set the Source property of the DynamicLayerInfo object. LayerDataSource layerDataSource = new LayerDataSource { DataSource = dataSource }; // Assign the LayerDataSource featureLayer.Source = layerDataSource; featureLayer.Initialized += (s, e) => { // Set the FeatureDataGrid's Map property MyDataGrid.Map = MyMap; // Set the new FeatureLayer as the FeatureDataGrid's GraphicsLayer property MyDataGrid.GraphicsLayer = featureLayer as GraphicsLayer; SimpleRenderer renderer = null; switch (featureLayer.LayerInfo.GeometryType) { case ESRI.ArcGIS.Client.Tasks.GeometryType.MultiPoint: renderer = new SimpleRenderer() { Symbol = new SimpleMarkerSymbol() { Color = new SolidColorBrush(GetRandomColor()), Size = 8 } }; break; case ESRI.ArcGIS.Client.Tasks.GeometryType.Point: renderer = new SimpleRenderer() { Symbol = new SimpleMarkerSymbol() { Color = new SolidColorBrush(GetRandomColor()), Size = 8 } }; break; case ESRI.ArcGIS.Client.Tasks.GeometryType.Polygon: renderer = new SimpleRenderer() { Symbol = new SimpleFillSymbol() { Fill = new SolidColorBrush(GetRandomColor()), BorderBrush = new SolidColorBrush(GetRandomColor()) } }; break; case ESRI.ArcGIS.Client.Tasks.GeometryType.Polyline: renderer = new SimpleRenderer() { Symbol = new SimpleLineSymbol() { Color = new SolidColorBrush(GetRandomColor()) } }; break; default: break; } featureLayer.Renderer = renderer; }; MyMap.Layers.Add(featureLayer); }); } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } // Utility function: Generate a random System.Windows.Media.Color Random _random = new Random(); private Color GetRandomColor() { var colorBytes = new byte[3]; _random.NextBytes(colorBytes); Color randomColor = Color.FromRgb(colorBytes[0], colorBytes[1], colorBytes[2]); return randomColor; } private void Legend_Refreshed(object sender, Legend.RefreshedEventArgs e) { // Clear the sub items from the basemap layer. if (e.LayerItem.Layer == _worldTopographicBasemap) e.LayerItem.LayerItems.Clear(); } }
Sorry - I haven't had time to look at the code in your previous yet... it's the end of the week here...
Cheers
Mike