POST
|
I executed my sample and everything appears to be running fine on my end. I uploaded my sample to this discussion for everyone to be able to download it. Could you send me your email address so that I can forward it to you if you're still unable to download it from geonet?
... View more
04-07-2015
08:01 AM
|
0
|
2
|
213
|
POST
|
What are the geoprocessing messages you're getting from the local server?
... View more
04-07-2015
07:52 AM
|
0
|
3
|
835
|
POST
|
I'll just paste the code below for you to use in your project. You'll just need to create the gpk and reference it within the code, and update the parameters provided to it. I believe the last tool I used was the Copy Features tool. You should be able to use any tool that creates an output shapefile (i.e. Copy Features, Feature Class to Feature Class, Select, etc.). *** XAML *** <Window x:Class="CopyFeatures.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:esri="http://schemas.esri.com/arcgis/runtime/2013" Title="Copy Features GP" Height="700" Width="800"> <Grid x:Name="LayoutRoot"> <Grid.Resources> <esri:SimpleLineSymbol x:Key="ResultLineSymbol" Color="Red" Style="Solid" Width="3" /> <esri:SimpleFillSymbol x:Key="ResultFillSymbol" Color="LimeGreen" Outline="{StaticResource ResultLineSymbol}" /> <esri:SimpleRenderer x:Key="ResultRenderer" Symbol="{StaticResource ResultFillSymbol}" /> </Grid.Resources> <esri:MapView x:Name="MyMapView"> <esri:Map /> <esri:MapView.GraphicsOverlays> <esri:GraphicsOverlay x:Name="ResultsOverlay" Renderer="{StaticResource ResultRenderer}"/> </esri:MapView.GraphicsOverlays> </esri:MapView> <Border HorizontalAlignment="Right" VerticalAlignment="Top" Margin="30" Padding="20" Width="300" Background="White" BorderBrush="Black" BorderThickness="1"> <Border.Effect> <DropShadowEffect /> </Border.Effect> <StackPanel> <TextBlock Text="Click on the Copy Features button to execute the gp tool. This will create a new shapefile and add the results to the display." TextWrapping="Wrap" /> <Button x:Name="CopyFeaturesButton" Content="Copy Features" FontWeight="Bold" Margin="0,12,0,0" Padding="5" Click="CopyFeaturesButton_OnClick" IsEnabled="False" /> <TextBlock x:Name="TxtInfo" FontSize="12" Visibility="Collapsed" Margin="0,12,0,0"> <Run Text="Shapefile:" FontSize="14" FontWeight="Bold" /> <LineBreak /> <Run Text="Name: " FontWeight="Bold" /> <Run Text="{Binding ID, Mode=OneWay}" /> <LineBreak /> <Run Text="Path: " FontWeight="Bold" /> <Run Text="{Binding DisplayName, Mode=OneWay}" /> <LineBreak /> <Run Text="Spatial Reference: " FontWeight="Bold" /> <Run Text="{Binding FeatureTable.SpatialReference.Wkid, Mode=OneWay}" /> <LineBreak /> <Run Text="Geometry Type: " FontWeight="Bold" /> <Run Text="{Binding FeatureTable.GeometryType, Mode=OneWay}" /> <LineBreak /> <Run Text="Features: " FontWeight="Bold" /> <Run Text="{Binding FeatureTable.RowCount, Mode=OneWay}" /> </TextBlock> </StackPanel> </Border> </Grid> </Window> *** CODE BEHIND *** using Esri.ArcGISRuntime.Data; using Esri.ArcGISRuntime.Layers; using Esri.ArcGISRuntime.LocalServices; using Esri.ArcGISRuntime.Symbology; using Esri.ArcGISRuntime.Tasks.Geoprocessing; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; namespace CopyFeatures { public partial class MainWindow : Window { private const string ShpPath = @".\data\in_shp\States.shp"; private const string CopyFeaturesPath = @".\data\packages\CopyFeatures.gpk"; private const string ResultPath = @".\data\out_shp"; private const string ServiceName = "/Copy%20Features"; private Geoprocessor _gpTask; private static readonly Regex _pathRegex = new Regex(@"(([a-z]:|\\\\[a-z0-9_.$]+\\[a-z0-9_.$]+)?(\\?(?:[^\\/:*?""<>|\r\n]+\\)+)[^\\/:*?""<>|\r\n]+).shp", RegexOptions.IgnoreCase); private static readonly Random _random = new Random(); public MainWindow() { InitializeComponent(); MyMapView.Loaded += async (sender, args) => { await LoadShapefile(ShpPath); LocalGeoprocessingService copyFeaturesService = new LocalGeoprocessingService(CopyFeaturesPath, GeoprocessingServiceType.SubmitJob); await copyFeaturesService.StartAsync(); _gpTask = new Geoprocessor(new Uri(copyFeaturesService.UrlGeoprocessingService + ServiceName)); Debug.WriteLine(copyFeaturesService.UrlGeoprocessingService); CopyFeaturesButton.IsEnabled = true; }; } private async Task LoadShapefile(string path, bool useRenderer=false) { try { // open shapefile table var shapefile = await ShapefileTable.OpenAsync(path); // create feature layer based on the shapefile var flayer = new FeatureLayer(shapefile) { ID = shapefile.Name, DisplayName = path, }; if (useRenderer) flayer.Renderer = LayoutRoot.Resources["ResultRenderer"] as SimpleRenderer; await flayer.InitializeAsync(); // Add the feature layer to the map MyMapView.Map.Layers.Add(flayer); if (MyMapView.Map.Layers.Count == 1) MyMapView.SetView(flayer.FeatureTable.Extent.Expand(1.1)); else { TxtInfo.DataContext = flayer; TxtInfo.Visibility = Visibility.Visible; } } catch (Exception ex) { MessageBox.Show("Error creating feature layer: " + ex.Message, "Sample Error"); } } // Submit GP Job and Poll the server for results every 2 seconds. private static async Task<GPJobInfo> SubmitAndPollStatusAsync(GPInputParameter parameter, Geoprocessor gpTask) { // Submit gp service job var result = await gpTask.SubmitJobAsync(parameter); // Poll for the results async while (result.JobStatus != GPJobStatus.Cancelled && result.JobStatus != GPJobStatus.Deleted && result.JobStatus != GPJobStatus.Succeeded && result.JobStatus != GPJobStatus.TimedOut) { result = await gpTask.CheckJobStatusAsync(result.JobID); await Task.Delay(2000); } return result; } private async void CopyFeaturesButton_OnClick(object sender, RoutedEventArgs e) { try { // Disable the button while gp executes ((Button) sender).IsEnabled = false; // Get the Feature Layer from the map var layer = MyMapView.Map.Layers[0] as FeatureLayer; var filter = new QueryFilter {WhereClause = "1=1"}; // Get a list of the states in the loaded shapefile var features = await layer.FeatureTable.QueryAsync(filter); var states = features.Select(feature => feature.Attributes["STATE_NAME"].ToString()).ToArray(); // Select 9 random states from the list of states var randomStates = new List<string>(); while (randomStates.Count < 9) { var state = states[_random.Next(0, states.Length - 1)]; if (randomStates.Contains(state)) continue; randomStates.Add(state); } // Create a feature set with the selected states filter.WhereClause = string.Format("STATE_NAME IN ('{0}')", string.Join("', '", randomStates)); var featSet = new FeatureSet(await layer.FeatureTable.QueryAsync(filter)); // Use the geoprocessor to copy the shapefile with only the selected records var parameter = new GPInputParameter(); parameter.GPParameters.Add(new GPFeatureRecordSetLayer("in_features", featSet)); // Submit gp job and wait for status update var result = await SubmitAndPollStatusAsync(parameter, _gpTask); if (result.JobStatus != GPJobStatus.Succeeded) return; // Confirm that the output is a GPFeatureRecordSetLayer var resultData = await _gpTask.GetResultDataAsync(result.JobID, "out_feature_class"); if (!(resultData is GPFeatureRecordSetLayer)) return; // Parse the messages returned from the geoprocessor StringBuilder builder = new StringBuilder(); string copy = string.Empty; foreach (var message in result.Messages) { builder.AppendLine(message.Description); // Special Task: Search for shapefile path in output messages var match = _pathRegex.Match(message.Description); if (!match.Success) continue; string filePath = match.Value; if (!File.Exists(filePath)) continue; var files = Directory.GetFiles(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + ".*"); if (!(Directory.Exists(ResultPath))) Directory.CreateDirectory(ResultPath); // Special Task: If needed shapefile is found...copy all files related to it to a known location foreach (var file in files) { File.Copy(file, Path.Combine(ResultPath, Path.GetFileName(file)), true); if (file.EndsWith("Copy.shp")) copy = Path.Combine(ResultPath, Path.GetFileName(file)); } } // Display the results in the map if (copy != string.Empty) await LoadShapefile(copy, true); else { GPFeatureRecordSetLayer gpLayer = resultData as GPFeatureRecordSetLayer; ResultsOverlay.Graphics.Clear(); ResultsOverlay.Graphics.AddRange(gpLayer.FeatureSet.Features.OfType<Graphic>()); } Debug.WriteLine("**** GP Messages ****"); Debug.WriteLine(builder.ToString()); } catch (Exception ex) { MessageBox.Show(ex.Message, "EXCEPTION", MessageBoxButton.OK, MessageBoxImage.Error); } finally { // Enable the button now that geoprocessing has completed ((Button)sender).IsEnabled = true; } } } }
... View more
04-06-2015
12:23 PM
|
0
|
5
|
835
|
POST
|
I'm a little confused with your first question. I believe that what you want to ask is would what you're trying to accomplish require a COM component or an Add-In. For the most part these are the two technologies that you would host an Extension, Button, ComboBox, etc. One involves creating a dll that will need to be registered on the on client machine and the other creates an esriaddin file that can easily be installed on a client machine without any admin privileges or registry access. Also, COM components may require that you build them for each version you want to utilize them at, whereas AddIns are forwards compatible. The location you'll place the form will depend on what you need the form to do. If you're want the form to display automatically during a particular event in the ArcMap application you could use an Application or Editor extension. For example, if you wanted to show the form when someone starts a new map, opens an existing map, or open a particular item you could use an application extension. If you wanted to show the form when someone starts editing you'd use an Editor Extension. If you wanted the user to have more control over when the form shows you could launch it with a Button, ComboBox, MenuItem, or host it in a DockableWindow. The choice would just depend on the story of when the form should appear. In regards to your second question, if you're wanting to create something to work within ArcMap you wouldn't want to use the .NET Runtime. The Runtime products do not allow you direct access to ArcObjects. You could surely write a .NET Runtime application to work side by side with ArcMap, but the Runtime Application and ArcMap would have a hard time communicating with each other. Also, the ArcObjects API is not being deprecated. It is not included on the Developers site because this site is dedicated to the Runtime and Web APIs. The Desktop APIs, such as ArcMap (ArcObjects) and ArcGIS Pro SDK will be hosted in a separate environment.
... View more
04-02-2015
09:46 AM
|
1
|
0
|
503
|
POST
|
Hi Peter, I looked at the link you posted above and it appears to be doing what I was suggest. I currently have a .NET sample that does the exact same thing, but I feel that this workflow currently is a bit of a hack. I have a second way that I want to create this sample that may be closer to a best practice (i.e. zipping up the shapefile and providing a url that I can use to download it instead of hacking out the path to the local servers output directory). I will try to write it up by this weekend and upload it so that you can see both options.
... View more
04-02-2015
09:13 AM
|
0
|
3
|
835
|
POST
|
The short answer is no. The Runtime for WPF products doesn't support the creation of local data. This functionality may be coming in a future release of the Runtime for .NET API. If you want to do this currently in the Runtime for WPF API you'd need to leverage a GP Service (whether local or online) to convert the resulting GraphicsLayers to Shapefiles that can be downloaded or copied to a specific location on the client machine.
... View more
03-29-2015
06:51 PM
|
0
|
5
|
835
|
POST
|
You can do this workflow either way. You can either manually create these toolbars in ArcMap and share the map document as a template with your users or you can create a toolbar within any of your addins use the id of the addin as the references within the XAML that creates the toolbar. If you use the XAML approach you will need to ensure that all of the addins are installed prior to installing the one that references all of the id's for the various commands. Otherwise you could do this dynamically in the code by searching for each item and adding it to a single toolbar at runtime.
... View more
03-29-2015
06:42 PM
|
0
|
0
|
247
|
POST
|
Are you using ArcGIS Engine or ArcGIS for Runtime? Engine can consume ArcGIS for Desktop (Basic, Standard, Advanced), ArcGIS for Server (ArcServer), and ArcGIS Engine (Engine and EngineGeoDB). These license will need to be installed against your ArcGIS Administrator. Once you've sure it's installed you can either use a LicenseControl in the UI or the IAoInitialize class in the code to license the application. For our ArcGIS for Runtime products we have a different license structure. Runtime utilizes its own Basic and Standard License. These will included something simular to an RUD # that you embed in the application or host in AGOL.
... View more
03-29-2015
06:37 PM
|
0
|
0
|
184
|
POST
|
If you embed the data in the project you can get the path to it in C# starting with System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location). this will give you the path to where the addin data is extracted on the machine within the AssemblyCache folder.
... View more
03-29-2015
06:32 PM
|
1
|
0
|
294
|
POST
|
What is the problem? The problem is centered behind having a relate between a GlobalId column and Guid column. When you add a Guid to a table in a feature service using Runtime it appears that this Guid will not be returned as a related record when the data is hosted in Oracle. Why does this happen? So far it appears that you'll run into this problem when using data hosted in an Oracle database. Although both the GlobalId and Guid columns are stored as char(38), the methods behind how the values are assigned to these columns result in different cases for the Guid's string representation. GlobalId values are auto-generated when records are added to the table and it appears that we add them to the table using their upper case string representation. On the other hand, when supplying a Guid value to the feature service via Runtime we're required to provide a Guid object and these values are stored as lower case strings on the database end by default. This behavior leads to conflicts in ArcMap when relating the two columns because they are compared as strings. In ArcMap you would notice that the Guid value {EF2E0C18-638C-4C6D-AFA7-4D23581CCAA5} would not be equivalent to {ef2e0c18-638c-4c6d-afa7-4d23581ccaa5} (i.e. the relate would show that there are no related records). Can this issue be replicated without using runtime? Technically yes, but not in necessarily the same manner. In ArcMap you could copy the GlobalId from one column, paste it into a related column, and convert it to lowercase. Once the GlobalId is stored in upper case and the related Guid column is stored in lower case these records would not recognize their values as the same. The primary difference between using ArcMap instead of Runtime would be that ArcMap will only allow you to supply the string to the Guid field. As such, you would have full control over the case of the string when you supply it to Oracle. In Runtime the feature service would require that you provide it a Guid object and the case of the resulting string would be determined by the RDBMS. It would just be important to note that the Guid wouldn't be a problem in databases like SQL Server where the Guid would be stored in upper case regardless of what you provide. How to fix this issue? In my testing I found that changing the case of the Guid column in ArcMap fixed the issue with the relate. I would assume that you could fix this issue on your end by doing one of the following: 1. Adding a constraint to my Guid column to make it always uppercase 2. Creating a trigger to convert the newly added Guid to upper case 3. Using an edit session in ArcMap to manually or programmatically update the values to upper case
... View more
11-13-2014
11:17 AM
|
0
|
0
|
2288
|
POST
|
So I want to make sure I fully understand your situation. Let's say you have two fields, which we'll just say are A and B. A is just a standard field in the table, but B is tied to a relationship class with various triggers set on it. Are you saying that when you make changes to A you see that your relationship class is triggered in response to listening for changes to B?
... View more
09-15-2014
04:27 PM
|
0
|
1
|
1029
|
POST
|
Hi Richard, Quick question for ya. Why are you calling the updateRow method when nothing has been updated? Does this behavior you're reporting occur when you only call updateRow after you've verified that the row needs to be updated?
... View more
09-15-2014
02:37 PM
|
0
|
3
|
1029
|
POST
|
I'm going to assume that you're using ArcObjects .NET. If you're wanting to accomplish this task in C# you could do this using Geoprocessing. You could probably complete this entire process using the Summary Statistics tool. You would just need to get the SUM for the length field of the features and also utilize Count. This would create a table for each individual feature you need to process. You would then be able to aggregate all of the outputs into a single table. If you wanted more fine grain control you could try using cursors in ArcObjects as well. You would utilize a Search Cursor to aggregate the data about each feature and you could use an InsertCursor to push the results to an output table that you've created. On the other hand, the easiest way to accomplish this would be to use Python. The workflows would be the same as the ArcObjects workflow, but you'd see a decrease in development overhead. I don't believe you'd see too much of a performance difference between the two options.
... View more
07-29-2014
09:07 AM
|
0
|
0
|
685
|
Title | Kudos | Posted |
---|---|---|
1 | 11-16-2015 09:00 AM | |
1 | 09-15-2015 10:49 AM | |
1 | 10-05-2015 05:08 PM | |
1 | 10-01-2015 03:21 PM | |
1 | 11-25-2015 09:05 AM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|