Introduction To Programming Arcobjects U
Introduction To Programming Arcobjects U
Programming
TM
ArcObjects Using the
Microsoft .NET
Framework
Introduction
Exercise 1A: Install the course data
Record user information
Log on to Windows
Install the data
Modify a setting in ArcCatalog
(Optional) Create an ESRI Global Account
Exercise 1B: Verify the system requirements for the ArcGIS Engine Developer Kit
Verify Microsoft .NET Framework 3.5 installation
Import code snippets into Visual Studio
Authorize the software
Verify the license on your system
Identify the .NET ArcObjects API
Prepare the ESRI Object Browser for future use
1-1
1-1
1-1
1-1
1-2
1-3
1-5
1-5
1-6
1-7
1-8
1-9
1-11
2-1
2-1
2-3
2-5
2-7
2-7
2-8
2-9
3-1
3-1
3-2
3-3
3-7
3-8
3-9
3-15
3-15
3-16
3-16
ii
Contents
3-21
3-21
3-23
4-1
4-1
4-2
4-3
4-4
4-5
4-6
4-9
4-10
4-11
4-13
4-19
4-19
4-20
4-21
4-23
4-24
4-25
4-28
4-28
4-30
4-32
5-1
5-1
5-3
5-6
5-6
5-11
5-12
5-21
5-21
5-23
5-26
5-26
5-31
Contents
5-32
Accessing data
Exercise 6A: Access data with ArcObjects (VB.NET)
Open an existing workspace
Create a new project in Visual Studio
Explore classes and interfaces for working with data
Access feature classes
Create feature layers
Set the data sources for the feature layers
Set general layer properties
Add layers to your MapControl
Run your project
(Optional) Control MapTips for your layers dynamically
6-1
6-1
6-2
6-3
6-5
6-7
6-7
6-9
6-9
6-11
6-11
6-23
6-23
6-24
6-25
6-28
6-29
6-30
6-31
6-32
6-33
6-34
Rendering data
Exercise 7A: Display layers (VB.NET)
Open a Visual Studio project
Create a fill symbol for vector polygons
Render vector layers
Apply an RGB renderer to raster data
Save your symbology to a layer file
(Optional) Apply a scale-dependent renderer
(Optional) Apply a stretch renderer to raster data
7-1
7-1
7-2
7-4
7-6
7-9
7-11
7-15
7-35
7-35
7-36
7-38
7-41
7-43
7-45
iii
7-49
8-1
8-1
8-5
8-9
8-13
8-21
8-21
8-25
8-29
8-33
10
iv
Contents
9-1
9-2
9-3
9-4
9-5
9-6
9-7
9-8
9-10
9-12
9-12
9-21
9-22
9-23
9-24
9-25
9-26
9-27
9-28
9-30
9-32
9-32
10-1
10-1
Contents
11
12
Create a geodatabase
Create a new file geodatabase
Create a new table
Add rows and values to the table
Calculate field values using an update cursor
(Optional) Compare methods for editing
10-2
10-4
10-6
10-9
10-11
10-12
10-23
10-23
10-24
10-26
10-28
10-30
10-31
10-33
Geoprocessing
Exercise 11A: Access the GeoProcessor (VB.NET)
Start ArcCatalog and view your data
Create a new project in Visual Studio
Create and work with a GeoProcessor object
Buffer a feature class
Work with messaging and overwriting output
Run multiple tools in the same process
(Optional) Perform a batch process using a "List" method
Challenge: List environments
11-1
11-2
11-3
11-4
11-6
11-9
11-12
11-14
11-19
11-27
11-28
11-29
11-30
11-33
11-35
11-38
11-40
11-44
12-1
12-2
12-4
12-5
12-6
12-7
Contents
12-8
12-10
12-12
12-15
12-17
12-17
12-25
12-26
12-28
12-29
12-29
12-31
12-32
12-34
12-35
12-38
12-40
12-40
vi
1
Introduction
Exercise 1A
1-1
Click Next.
Click Finish when the data installation is complete.
Remove the training data CD from your CD drive and return it to its sleeve in your
exercise book.
1-2
Exercise 1A
Creating an account is free and takes only a few moments. If you don't already have an
ESRI Global Account and want to create one, this step will guide you the process.
Open Internet Explorer and type support.esri.com in the Address bar.
The ESRI Support Center Web site displays.
Locate the Support Center Login section on the page, as shown in the graphic below.
1-3
In the form that displays, provide a user name and password of your choice and fill out
the remaining fields displayed in bold (required).
When you have filled out the required fields, click "create my ESRI Global Account."
Note: If the user name you chose is already taken, you will be prompted to choose
another one.
Your account will be created and activated upon confirmation of your e-mail address.
Conclusion
You have now installed the data that you will work with in the upcoming exercises in this
course. If you have any problems accessing this data, please ask your instructor for
assistance.
1-4
Exercise 1B
1-5
Verify that Microsoft .NET Framework 3.5 appears in the list of installed programs. If
it is not, ask your instructor for help.
If prompted, choose the settings for the language you will use for this course:
1-6
Exercise 1B
Click Next.
1-7
Choose the option indicating you received the authorization file by e-mail and
saved it to disk.
Click Browse.
Navigate to the location of the authorization file (provided by your instructor).
Select the .ecp file and click Open.
Click Next.
The final panel lists the features that you are now authorized to use.
Click Finish to complete the authorization process.
Note: Outside of this course, you can obtain authorization files and ArcGIS Desktop
license files by registering your software with ESRI at http://service.esri.com.
1-8
Exercise 1B
If you run your application within a few days of the expiration date, a warning message
will remind you that it is time to renew your license.
Click Close.
Notice the period-delimited (.) naming convention of the files in this folder. You will
learn about this naming convention in a later lesson.
Question 3: In the DotNet directory, which .DLL's name indicates that it allows you to
work with raster data sources on machines that do not have ArcGIS Desktop installed?
______________________________________________________________________
You will also work with the COM libraries, even though you are developing in .NET.
1-9
The com directory houses type information in a series of object library (.olb) files. Data
sources (i.e., geodatabases, shapefiles, text files, and even folders) are managed by some
of these COM libraries.
Question 4: In the com directory, which file's name indicates that it allows you to work
with geodatabase data sources?
______________________________________________________________________
To support .NET developers, libraries called ArcObjects Primary Interop Assemblies
(PIAs) are installed in the Microsoft Global Assembly Cache (GAC). You will work with
these libraries later. For now, you will explore the contents of the GAC.
1-10
Exercise 1B
Navigate to C:\WINDOWS, click the assembly folder, then scroll down to view the
ESRI assemblies.
Notice that the assemblies display in a special view that shows the assembly name,
version, public key token, etc.
Close Windows Explorer.
1-11
In the Select Type Library dialog box, leave the default option (Select by file name)
and click Browse.
In the dialog box that appears, do the following:
1-12
Click Search.
Exercise 1B
On the right, double-click the result. (If necessary, expand Map in the lower pane.
Your search yields a list of interfaces, which are very important in writing ArcObjects
code. You will learn about these and other interfaces in this course.
Close the ESRI Object Browser.
Conclusion
In this exercise, you confirmed that your machine is correctly configured for working
with ArcGIS Engine Developer Kit and ArcObjects.
1-13
1-14
2
Exploring ArcGIS
Engine controls
Exercise 2: Create your first mapping
application
Estimated time: 45 minutes
Exercise 2
Exercise shortcut
1. In Visual Studio, create a new Windows Forms Application.
2. Add a MapControl, TOCControl, and ToolbarControl to your form. Buddy the
TOCControl and ToolbarControl with the MapControl. Modify some of the
properties of your controls in the property pages.
3. Add a LicenseControl to the form and test your project.
4. To your ToolbarControl, add a Button control that will open a map document. Be
sure to remove the current map document from your MapControl's property pages.
** (Optional) Add a Button control to programmatically determine the number of
layers in your map.
2-1
The high-level topics display in an expandable tree and vary depending on the software
development kits (SDKs) installed on your computer. During this class, you will use the
libraries for ArcGIS Desktop and ArcGIS Engine.
In the table of contents, expand Building solutions with ArcGIS Engine using .NET.
Navigate to:
The topic that you selected displays on the right. Notice that the topic title correlates with
the name of the tab.
Also notice a URL that displays. With this URL, you can view the help topic in a Web
browser on any computer that has the ArcGIS Developer Help installed.
2-2
Exercise 2
In the table of links on the page, click the Controls library link (
).
In the tree on the left, select Projects and Solutions (you don't need to expand it).
For Visual Studio projects location, click the ellipsis button , browse to your
\Student\IPAN folder, and click OK.
Verify that the Save new projects when created box is checked.
Click OK.
2-3
In the tree under Project types, select either Visual Basic or Visual C#.
On the right under Templates, click Windows Forms Application to select it.
Note: While the Windows Forms Application is selected by default, it may difficult to
see.
At the bottom of the dialog box, notice that the Location field displays the default path
that you previously specified in this step.
Assign or verify the following:
Name: FirstMap (By default, the Solution Name matches the name you input
here.)
Location: \Student\IPAN\Exercise02
Create directory for solution: Checked
Click OK.
Your FirstMap project opens in Design view as a Visual Studio form control named
Form1. In the Solution Explorer on the right, notice that the project contains one folder
and one file.
2-4
Exercise 2
Note: If the Form1 form control does not display, right-click the Form1 file in the
Solution Explorer and choose View Designer.
2-5
Modify some properties for the other controls to change their appearance.
Question 2: On which controls can you assign a buddy control? What can you set it to?
______________________________________________________________________
Using your answer, set the Buddy Control property for the two controls that have it.
Open the Properties dialog box for the ToolbarControl.
On the Items tab, click Add.
In the Controls Commands dialog box, on the Commands tab, click Map Navigation in
the list of categories.
In the list of commands, double-click each of the following to add them to your
ToolbarControl:
Full Extent
Pan
Zoom In
Zoom Out
Find
Identify
Measure
If you would like, add additional commands from these or other categories.
Click Close on the Controls Commands dialog box, then click OK on the Properties
dialog box.
2-6
Exercise 2
An error message appears, indicating that the application has not been initialized with an
ESRI license. Even though you have created a small application without any code, the
controls still need a license.
Click OK to close the error message, then close your application.
Question 3: Which control can you add to your form to eliminate the error?
______________________________________________________________________
Drag the necessary control from the Toolbox window onto your form.
Open the Properties dialog box for the control.
Check the box to shut down the application if the selected licenses are not available.
Question 4: Which license is in effect? How many product licenses can you choose from?
______________________________________________________________________
Click OK to close the Properties dialog box.
Click the Start Debugging button
2-7
Open the Properties dialog box for your MapControl and do the following:
On the Map tab, click Reset and then click Yes on the prompt that appears.
Click OK.
2-8
Exercise 2
Step 3 shows you how to add a button that programmatically determines the
number of layers in your map.
If you want to complete the optional step, do so now. Otherwise, save your project and
close Visual Studio.
2-9
Open SouthAmerica.mxd.
Click your new button to display the message box.
Question 10: How many layers are in your map?
______________________________________________________________________
Close the message box, then close your application.
Save your project and close Visual Studio.
Conclusion
In this exercise, you learned how to easily introduce lots of GIS functionality into an
ArcGIS Engine project by merely working with some of the controls. You created a
simple Windows application with four ArcGIS Engine Controls (MapControl,
ToolbarControl, TOCControl, and LicenseControl) and modified some of their
properties. If you completed the optional step, you also saw an example of how you can
programmatically customize your projects.
2-10
Exercise 2
2-11
2-12
Exercise 2
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Linq;
System.Text;
System.Windows.Forms;
namespace FirstMap
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Optional step: Determine the number of layers in the map
MessageBox.Show(String.Format("{0:#} layers in map", axMapControl1.LayerCount));
2-13
3
Programming with
COM and .NET
Exercise 3A: Program with COM
(VB.NET)
Estimated time: 45 minutes
Exercise 3B: Program with COM (C#)
Estimated time: 45 minutes
Exercise 3A
Exercise shortcut
1. In Visual Studio, create a new Windows Forms Application.
2. Add a Button control to your form.
3. Write code to the Button control's Click event to create a map document object.
4. Output the first map in your map document and write its name to the Output
window.
5. Output the name of the active view's focus map, minimum and maximum X and Y
properties of the active view's extent to the Output window.
** (Optional) Add an ArcGIS Engine MapControl to your form, then
programmatically call a method on it to load your map document.
Property
Value
Language
Visual Basic
Template
Name
MapDocInfo
Location
\Student\IPAN\Exercise03
Solution name
MapDocInfo
3-1
Make sure the Create directory for solution check box is checked.
Your project opens in Design view as a Visual Studio form control. In the Solution
Explorer, notice that your project contains one folder and one file.
Before continuing, you will verify that any output will be directed to the Output window.
From the Tools menu, choose Options.
In the Options dialog box, do the following:
As you work through this exercise, it will be helpful to know when implicit casting
occurs.
In the Solution Explorer, right-click the My Project folder and choose Open.
A new tab called MapDocInfo displays in Visual Studio.
On the left-pane of the tab, click Compile.
Change the Notification level for Implicit conversion to Warning.
Close the MapDocInfo tab by clicking the X on the upper right corner.
3-2
Exercise 3A
In the Toolbox window, drag a Button control from the Common Controls group onto
your form.
In the Properties window, specify the following:
(Name): btnInfo
Text: Info
3-3
Enter IMapDocument, then check the Report Search and Copy results for use in .NET
check box.
Click Search.
Question 1: Which library do you need to add to your project?
______________________________________________________________________
Click Copy.
In Visual Studio, from the Project menu, choose Add ArcGIS Reference.
Because you will not be adding any ArcGIS Engine controls to your application, you can
use ArcGIS Desktop references and libraries.
In the Add ArcGIS Reference dialog box, do the following:
Near the top of your code (above your class) type Imports, right-click, and choose
Paste to add the assembly reference to your project.
From your Build menu, build your project.
Click inside your btnInfo_Click method.
3-4
Exercise 3A
Notice that MapDocument now displays an error. To understand its cause, you need to
know that many assemblies have the System namespace as a dependency. The following
graphic depicts the MapDocument coclass and its two interfaces.
Although you are only working with IMapDocument, IDocumentVersion is found in the
System assembly. Your project, therefore, needs a reference to the System assembly.
Add an ArcGIS reference to ESRI.ArcGIS.System the same way you added a
reference to ESRI.ArcGIS.Carto. (Hint: You do not need to import it.)
Recall from the lecture that there are different types of map documents, one of which is
an .mxd file. Next, you will access an .mxd file that installed with your data.
3-5
Write the code to open a map document, adding the appropriate drive letter to the
following path:
mapDoc.Open("\Student\IPAN\Exercise03\SouthAmerica.mxd")
Note: If prompted, for Online Help Settings, choose Use local help as primary source,
and then click OK.
Question 3: What parameter does the property return? How many types of documents
does it include?
______________________________________________________________________
After the code that opens the map document, complete the following code to write the
value of the property to the Output window:
Debug.WriteLine(mapDoc.________________________)
For the remainder of this exercise, you are responsible for building
your project as needed. It is especially important to build your project
after you correct syntax errors.
).
3-6
Exercise 3A
In your button's Click event, skip several lines after Debug.WriteLine and then use
the following syntax to close your application as soon as the process finishes:
Me.Close()
Using the developer resource of your choice, find additional properties for your map.
Find the property that will indicate the value for the map's distance units.
Write the value for this property to the Output window.
Note: Remember to use ToString() on the property to output the map's distance units.
If you would like, write the value of any other properties to the Output window.
3-7
3-8
Exercise 3A
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.____________
Public Class Form1
Modify your code to write the minimum X value of the extent. Include a descriptive
label in the argument for Debug.WriteLine.
Test your code.
Question 7: What is the minimum X value (rounded to the nearest integer)?
______________________________________________________________________
Revise your code to write the minimum X and Y and the maximum X and Y. (Tip: Use
the Round function in the Math library to round to zero decimal places.)
Test your code.
Question 8: What is the maximum Y?
______________________________________________________________________
You have finished this exercise; however, you may wish to complete the optional step:
Step 5 shows you how to load a map document into the application using a
MapControl.
If you want to complete the optional step, do so now. Otherwise, save your project and
close Visual Studio.
at the top of
In the Toolbox window, drag a MapControl from the ArcGIS Windows Forms group
onto your form.
Resize your form, if necessary.
Run your project.
3-9
A license error appears. Recall that ArcMap and ArcCatalog use ArcObjects to perform
GIS tasks. When you start ArcMap, for example, some processing behind the scenes
checks for a license. Your custom application also uses ArcObjects to perform a GIS
task; therefore, when you run your custom application, you are responsible for checking
for a license.
In order to use the MapControl, you need to include license handling in your project. In
the previous exercise, you added the LicenseControl. This time, you will add code that
has already been written.
Close the error message and close your application.
From the Project menu, choose Add ArcGIS License Checking.
In the ArcGIS License Initializer dialog box, do the following:
Two code modules are added to your project. They contain code that will manage the
license for you.
Question 9: Which module initializes the license with the application and shuts down the
license?
______________________________________________________________________
Now you will load your map document into the MapControl.
View the Form1 code.
In your button's Click event, just before the line Me.Close(), complete the following
code to load the same map document that you have been exploring, by file name:
AxMapControl1.LoadMxFile(mapDoc.________________________________)
3-10
Exercise 3A
Conclusion
In this exercise, you accessed the properties of an existing map without viewing it. In
your code, you moved between two interfaces on the same object by casting, the .NET
technique for the process known as QueryInterface (QI) in the world of COM.
3-11
3-12
Exercise 3A
AxMapControl1.LoadMxFile(mapDoc.DocumentFilename)
'Me.Close()
End Sub
End Class
3-13
Exercise 3B
Exercise shortcut
1. In Visual Studio, create a new Windows Forms Application.
2. Add a Button control to your form.
3. Write code to the Button control's Click event to create a map document object.
4. Output the first map in your map document and write its name to the Output
window.
5. Output the name of the active view's focus map, minimum and maximum X and Y
properties of the active view's extent to the Output window.
** (Optional) Add an ArcGIS Engine MapControl to your form, then
programmatically call a method on it to load your map document.
Property
Value
Language
Visual C#
Template
Name
MapDocInfo
Location
\Student\IPAN\Exercise03
Solution name
MapDocInfo
3-15
Make sure the Create directory for solution check box is checked.
Your project opens in Design view as a Visual Studio form control. In the Solution
Explorer, notice that your project contains one folder, two files, and project references.
Before continuing, you will verify that any output will be directed to the Output window.
From the Tools menu, choose Options.
In the Options dialog box, do the following:
In the Toolbox window, drag a Button control from the Common Controls group onto
your form.
In the Properties window, specify the following:
(Name): btnInfo
Text: Info
3-16
Exercise 3B
Click Search.
Question 1: Which library do you need to add to your project?
______________________________________________________________________
Click Copy.
In Visual Studio, from the Project menu, choose Add ArcGIS Reference.
Because you will not be adding any ArcGIS Engine controls to your application, you can
use ArcGIS Desktop references and libraries.
3-17
Near the top of your code (above your namespace) type using, right-click, and choose
Paste to add the assembly reference to your project.
Build your project (Hint:
).
3-18
Exercise 3B
Although you are only working with IMapDocument, IDocumentVersion is found in the
System assembly. Your project, therefore, needs a reference to the System assembly.
Add an ArcGIS reference to ESRI.ArcGIS.System the same way you added a
reference to ESRI.ArcGIS.Carto. (Hint: You do not need a using statement.)
For the remainder of this exercise, you are responsible for building
your project (or solution) as needed. It is especially important to build
your project after you correct syntax errors.
Recall from the lecture that there are different types of map documents, one of which is
an .mxd file. Next, you will access an .mxd file that installed with your data.
Write the code to open a map document, adding the appropriate drive letter to the
following path:
mapDoc.Open("\\Student\\IPAN\\Exercise03\\SouthAmerica.mxd", "");
Note: If prompted, for Online Help Settings, choose Use local help as primary source,
and then click OK.
3-19
Locate the property that will tell you the type of map document currently loaded in the
object, then explore its links.
Question 3: What parameter does the property return? How many types of documents
does it include?
______________________________________________________________________
After the code that opens the map document, complete the following code to write the
value of the property to the Output window:
System.Diagnostics.Debug.WriteLine(mapDoc.________________________);
3-20
Exercise 3B
Using the developer resource of your choice, find additional properties for your map.
Find the property for the map's distance units.
Write the value for this property to the Output window.
If you would like, write the value of any other properties to the Output window.
3-21
Continuing with your code, declare the variable actView to hold a reference to
IActiveView.
Write code to cast (perform a COM QueryInterface) from IMap to IActiveView.
(Hint: For help with the syntax, refer to your lecture book.)
Write the name of the focus map to the Output window.
Test your code.
Notice that the name of the active view's focus map is the same as the name of the map
you are accessing from your map document. The variables inMap and actView are
pointing to the same map.
Write the Extent property of the active view to the Output window.
Build your project.
Notice the error on the Extent property of the active view.
Hover your mouse pointer over the error.
Question 6: Which assembly is required?
______________________________________________________________________
Add an ArcGIS reference to the required assembly.
At the top of your code, import the assembly to your project with the following code:
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.____________;
namespace MapDocInfo
{
public partial class Form1 : Form
Modify your code to write the minimum X value of the extent. Include a descriptive
label in the argument for System.Diagnostics.Debug.WriteLine.
Test your code.
Question 7: What is the minimum X value (rounded to the nearest integer)?
______________________________________________________________________
3-22
Exercise 3B
Revise your code to write the minimum X and Y and the maximum X and Y. (Tip: Use
the Round function in the Math library to round to zero decimal places.)
Test your code.
Question 8: What is the maximum Y?
______________________________________________________________________
You have finished this exercise; however, you may wish to complete the optional step:
Step 5 shows you how to load a map document into the application using a
MapControl.
If you want to complete the optional step, do so now. Otherwise, save your project and
close Visual Studio.
at the top of
In the Toolbox window, drag a MapControl from the ArcGIS Windows Forms group
onto your form.
Resize your form, if necessary.
Run your project.
A license error appears. Recall that ArcMap and ArcCatalog use ArcObjects to perform
GIS tasks. When you start ArcMap, for example, some processing behind the scenes
checks for a license. Your custom application also uses ArcObjects to perform a GIS
task; therefore, when you run your custom application, you are responsible for checking
for a license.
In order to use the MapControl, you need to include license handling in your project. In
the previous exercise, you added the LicenseControl. This time, you will add code that
has already been written.
Close the error message and close your application.
3-23
Now you will load your map document into the MapControl.
In your button's Click event, just before the line this.Close(), complete the
following code to load the same map document that you have been exploring, by file
name:
axMapControl1.LoadMxFile(mapDoc.________________________________);
3-24
Exercise 3B
Conclusion
In this exercise, you accessed the properties of an existing map without viewing it. In
your code, you moved between two interfaces on the same object by casting, the .NET
technique for the process known as QueryInterface (QI) in the world of COM.
3-25
3-26
Exercise 3B
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
namespace MapDocInfo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnInfo_Click(object sender, EventArgs e)
{
IMapDocument mapDoc = new MapDocument();
mapDoc.Open("\\Student\\IPAN\\Exercise03\\SouthAmerica.mxd", "");
System.Diagnostics.Debug.WriteLine(mapDoc.DocumentType);
IMap inMap;
inMap = mapDoc.get_Map(0);
System.Diagnostics.Debug.WriteLine("Map name: " + inMap.Name);
System.Diagnostics.Debug.WriteLine(
"Distance units: " + inMap.DistanceUnits);
IActiveView actView;
actView = inMap as IActiveView;
System.Diagnostics.Debug.WriteLine(
"Focus map name: " + actView.FocusMap.Name);
// System.Diagnostics.Debug.WriteLine("MinX: " + actView.Extent.XMin);
System.Diagnostics.Debug.WriteLine(
"MinX: " + Math.Round(actView.Extent.XMin,
"MinY: " + Math.Round(actView.Extent.YMin,
"MaxX: " + Math.Round(actView.Extent.XMax,
"MaxY: " + Math.Round(actView.Extent.YMax,
0) + " " +
0) + " " +
0) + " " +
0));
System.Diagnostics.Debug.WriteLine(mapDoc.DocumentFilename);
axMapControl1.LoadMxFile(mapDoc.DocumentFilename);
//this.Close();
3-27
4
Understanding object
model diagrams
Exercise 4A: Create an ArcObjects
application (VB.NET)
Estimated time: 45 minutes
Exercise 4B: Create an ArcObjects
application (C#)
Estimated time: 45 minutes
Exercise 4A
Exercise shortcut
1. In Visual Studio, create a Windows Form Application.
2. Add a Button control and a TextBox to your form.
3. In the Button control's Click event, insert a snippet that counts features in a
shapefile.
4. Browse appropriate developer resources to help you understand the snippet.
5. Add code to the snippet to count the records in a shapefile's attribute table.
6. Run your project and check your results.
Property
Value
Language
Visual Basic
Template
Name
CountFeatures
Location
\Student\IPAN\Exercise04
Solution name
CountFeatures
4-1
Make sure the Create directory for solution check box is checked.
(Name): frmCount
Text: Count Features in a Shapefile
In the Toolbox window, expand the Common Controls group and drag a Button
control onto your form.
In the Properties window, change the following properties for your button:
(Name): btnCount
Text: Count Features
If necessary, resize the button on your form so that all of the text displays.
Drag a TextBox control onto your form, then change its (Name) property to txtCount.
Verify that your form resembles the following graphic:
4-2
Exercise 4A
In the ArcGIS Snippet Finder dialog box, from the Tools menu, choose Options.
In the Preferences dialog box, do the following:
4-3
4-4
Exercise 4A
In Design view, double-click Count Features button on the form to open its Click
event.
Place your cursor inside the btnCount_Click method, right-click, and choose Insert
Snippet.
Navigate to and double-click IPAN_CodeSnippets > Visual Basic >
IPAN_Ex04_CountFeatures.
Notice the syntax errors indicated by the blue squiggly underscores. You will resolve
those errors and provide the path to your data later in the exercise.
Take a moment to examine the snippet you just added.
Notice that the code contains several variables that hold references to interfaces. One
object is created as a new instance of a coclass. In addition, the code contains two
methods that open data.
Question 1: How many interfaces does the sample use? What is the name of the coclass?
______________________________________________________________________
Question 2: What are the two methods?
______________________________________________________________________
You will use the available help resources to learn more about the ArcObjects in the
sample and how to correct the errors to make your code work.
On the right, scroll down and read the description for the Geodatabase library.
4-5
This library provides the programming API (application programming interface) for the
geodatabasethe objects, methods, and properties that you need to work with.
Click the Geodatabase link.
Additional documentation displays, including the software that can access the library.
Scroll down to the Core geodatabase model diagram.
Notice that the Dataset abstract class appears at the top of the diagram. A dataset is the
highest-level container for data.
Note: Abstract classes are not shown in the help system or in the ESRI Object Browser;
however, they are viewable in the OMDs.
4-6
Exercise 4A
4-7
to pan, follow the solid line that extends from the top of the
4-8
Exercise 4A
In the previous step, you found two methods, OpenFromFile and OpenTable, in your
code.
Find the two methods in the OMD.
Question 9: What does OpenFromFile return, and what does OpenTable return?
______________________________________________________________________
Once you know the return type for a method, you know how to declare the variable that
will store the result.
Read through your snippet code again and locate the lines of code that use these two
methods.
Question 10: What are the variables returned by OpenFromFile and OpenTable? Are the
variables declared to the correct return data types?
______________________________________________________________________
Browsing developer resources as you have just done helps you understand the snippet
that you added to your code.
Close the Desktop Help for .NET (VS2008).
4-9
Centers. In this step, you will explore the ArcGIS Resource Centers that provide online
access to various developer communities.
From your desktop, open Internet Explorer.
In the URL box, type resources.esri.com, then press Enter.
The ArcGIS Resource Centers Web site displays.
Under Products, click ArcGIS Desktop.
Click the For Developers tab.
Click the .NET link, then click the Concept and Samples tab.
In the tree on the left, click Working with ArcGIS Components and examine the
contents.
Take a few minutes to explore the help. You will quickly realize how valuable this
resource is to an ArcObjects developer.
4-10
Click Add.
For Title, type ESRI Library Locator.
For Command, click the ellipses button , browse to C:\Program
Files\ArcGIS\DeveloperKit\Tools and open LibraryLocator.exe.
Click OK.
Exercise 4A
Now you can open the Library Locator directly from Visual Studio.
From the Tools menu, choose ESRI Library Locator.
In the ESRI Library Locator, do the following:
Type IWorkspaceFactory.
Check the check box for Report Search and Copy results for use in .NET.
Click Search.
filePath: \Student\IPAN\Database
tableName: Cities.shp
Note: Remember to enter the values for filePath and tableName within quotes.
4-11
Question 13: Which of the objects seems to have the most potential for giving you the
number of features in your shapefile? (Hint: It contains the attributes.)
______________________________________________________________________
Your code declares this object as the interface that you will examine.
On Visual Studio's Standard toolbar, click the Object Browser button
The members (properties and methods) of ITable display on the right. You may need to
scroll to view the complete contents.
Question 14: Which method will return the number of features in a shapefile (or the rows
in a table), and what is the data type that is returned?
______________________________________________________________________
4-12
Exercise 4A
You now know that you can determine the number of features, or rows, in your table.
What should you do next? You need to create a selection, or query, of the desired
features. In this case, you want to know the count of all features.
Question 15: Which method lets you select features, and what does this method accept as
its first argument?
______________________________________________________________________
In ArcObjects, the QueryFilter object lets you write the WHERE clause portion of a
SQL statement. Because you want to return all of the rows, or records, in a table, you do
not need to write the WHERE clause. Instead, you can just pass Nothing as the
argument. This is just a preview of QueryFilteryou will learn more in a later lesson.
Click the X on the Object Browser tab to close it.
Your goal is to count the number of records in a shapefile's attribute table.
Complete the following code to declare the variable numRows as the appropriate data
type (Tip: Place the code immediately after the comment):
Dim numRows As _______
Return the number of rows (or features) in your shapefile and store the result in
numRows.
numRows = pTable.________________(Nothing)
Make an additional modification to place your results in the text box on your form.
txtCount.________ = ________.ToString
The code will populate your text box with the number of rows (or records or features) in
your shapefile. In addition, the code will convert the numeric value to a string.
Save and build your project.
4-13
Question 16: Based on the license you have chosen, if you wanted to share your
application with another person, what software would need to be installed on that
person's computer?
______________________________________________________________________
Now you are ready to run your project.
Return to your code and run your project.
Click your Count Features button to test your code.
Question 17: How many features are in your shapefile?
______________________________________________________________________
Close your application.
Save your project and close Visual Studio.
Now you will preview the Cities shapefile in ArcCatalog to confirm your results.
Start ArcCatalog.
In the Catalog tree, browse to the \Student\IPAN\Database folder.
Click the Cities shapefile.
In the display area, click the Preview tab.
At the bottom of the tab, choose Table from the Preview drop-down list.
Question 18: How many records are in the table? Did your code return the correct
number?
______________________________________________________________________
Close ArcCatalog.
4-14
Exercise 4A
Conclusion
In this exercise, you created a small application to count the number of features in a
shapefile. To save time, you inserted a snippet into your application and then used the
developer resources to understand the code it contained. You learned how useful the
developer help is for searching classes, interfaces, methods, and properties to see what is
available and which library they are located in, while OMDs allow you to easily view
relationships between objects. You also explored the ArcGIS Resource Centers.
In future lessons, you will use the skills you developed here for searching the help system
and OMDs for casting between interfaces.
4-15
4-16
Exercise 4A
Question 10: What are the variables returned by OpenFromFile and OpenTable? Are the
variables declared to the correct return data types?
Answer: pWorkspace and pTable; yes
Question 11: What is the error that displays?
Answer: Type 'IWorkspaceFactory' is not defined
Question 12: Which library contains the IWorkspaceFactory interface?
Answer: ESRI.ArcGIS.GeoDatabase
Question 13: Which of the objects seems to have the most potential for giving you the
number of features in your shapefile? (Hint: It contains the attributes.)
Answer: pTable
Question 14: Which method will return the number of features in a shapefile (or the rows
in a table), and what is the data type that is returned?
Answer: RowCount, Integer
Question 15: Which method lets you select features, and what does this method accept as
its first argument?
Answer: Select, IQueryFilter
Question 16: Based on the license you have chosen, if you wanted to share your
application with another person, what software would need to be installed on that
person's computer?
Answer: ArcGIS Desktop
Question 17: How many features are in your shapefile?
Answer: 606
Question 18: How many records are in the table? Did your code return the correct
number?
Answer: 606; yes
4-17
4-18
Exercise 4B
Exercise shortcut
1. In Visual Studio, create a Windows Form Application.
2. Add a Button control and a TextBox to your form.
3. In the Button control's Click event, insert a snippet that counts features in a
shapefile.
4. Browse appropriate developer resources to help you understand the snippet.
5. Add code to the snippet to count the records in a shapefile's attribute table.
6. Run your project and check your results.
Property
Value
Language
Visual C#
Template
Name
CountFeatures
Location
\Student\IPAN\Exercise04
Solution name
CountFeatures
4-19
Make sure the Create directory for solution check box is checked.
(Name): frmCount
Text: Count Features in a Shapefile
In the Toolbox window, expand the Common Controls group and drag a Button
control onto your form.
In the Properties window, change the following properties for your button:
(Name): btnCount
Text: Count Features
If necessary, resize the button on your form so that all of the text displays.
Drag a TextBox control onto your form, then change its (Name) property to txtCount.
Verify that your form resembles the following graphic:
4-20
Exercise 4B
In the ArcGIS Snippet Finder, from the Tools menu, choose Options.
In the Preferences dialog box, do the following:
4-21
4-22
Exercise 4B
With the snippet finder, you can see exactly what the snippet will do before you insert it
into your project.
When you are finished, close the ArcGIS Snippet Finder dialog box.
A description of each snippet included with ArcGIS SDK is available in the developer
help topic, Visual Studio Integration Tools > Snippet Index.
4-23
On the right, scroll down and read the description for the Geodatabase library.
This library provides the programming API (application programming interface) for the
geodatabasethe objects, methods, and properties that you need to work with.
Click the Geodatabase link.
Additional documentation displays, including the software that can access the library.
Scroll down to the Core geodatabase model diagram.
Notice that the Dataset abstract class appears at the top of the diagram. A dataset is the
highest-level container for data.
Note: Abstract classes are not shown in the help system or in the ESRI Object Browser;
however, they are viewable in the OMDs.
4-24
Exercise 4B
Question 5: Based on the symbology for the WorkspaceFactory objects, what is the
relationship between a ShapefileWorkspaceFactory and a WorkspaceFactory?
______________________________________________________________________
Leave the help open as you will continue using it in the next step.
Note: In the interest of completing the exercise, if you want to review more of the
documentation in this topic, you may wish to do so after you finish.
4-25
Scroll to the right until you see the Class Diagram Key.
This key serves as a quick reference to the symbols and terms that you learned in the
lecture. Every diagram has such a key.
Use the PDF tools to search for the Table class.
to pan, follow the solid line that extends from the top of the
4-26
Exercise 4B
Remember, a dataset is the highest-level container for data. It is logical that a table,
which is also a container for data, is a type of dataset.
Pan along the line that extends from the top of the Dataset class.
Question 7: Can a Workspace contain more than one Dataset?
______________________________________________________________________
Pan and zoom to find the dashed arrow that points to the Workspace class.
In the lecture, you learned that this is a "creates a" relationship.
Question 8: Which class can instantiate (or create) a Workspace?
______________________________________________________________________
is a generic class containing methods that will allow you to create an object
for data that resides in a file (such as a shapefile) on disk.
Workspace
In the previous step, you found two methods, OpenFromFile and OpenTable, in your
code.
Find the two methods in the OMD.
Question 9: What does OpenFromFile return, and what does OpenTable return?
______________________________________________________________________
Once you know the return type for a method, you know how to declare the variable that
will store the result.
Read through your sample code again and locate the lines of code that use these two
methods.
Question 10: What are the variables returned by OpenFromFile and OpenTable? Are the
variables declared to the correct return data types?
______________________________________________________________________
Browsing developer resources as you have just done helps you understand the snippet
that you added to your code.
Close the Desktop Help for .NET (VS2008).
4-27
4-28
Exercise 4B
Click Add.
For Title, type ESRI Library Locator.
For Command, click the ellipses button , browse to C:\Program
Files\ArcGIS\DeveloperKit\Tools and open LibraryLocator.exe.
Click OK.
Now you can open the Library Locator directly from Visual Studio.
From the Tools menu, choose ESRI Library Locator.
In the ESRI Library Locator, do the following:
Type IWorkspaceFactory.
Check the check box for Report Search and Copy results for use in .NET.
Click Search.
4-29
Modify the values for the two string variables in your code as follows (remember to
include the drive letter in the path):
filePath:
\\Student\\IPAN\\Database
tableName: Cities.shp
Note: Remember to enter the values for filePath and tableName within quotes.
4-30
Exercise 4B
The members (properties and methods) of ITable display on the right. You may need to
scroll to view the complete contents.
Question 14: Which method will return the number of features in a shapefile (or the rows
in a table), and what is the data type that is returned?
______________________________________________________________________
You now know that you can determine the number of features, or rows, in your table.
What should you do next? You need to create a selection, or query, of the desired
features. In this case, you want to know the count of all features.
Question 15: Which method lets you select features, and what does this method accept as
its first argument?
______________________________________________________________________
In ArcObjects, the QueryFilter object lets you write the WHERE clause portion of a
SQL statement. Because you want to return all of the rows, or records, in a table, you do
not need to write the WHERE clause. Instead, you can just pass null as the argument.
This is just a preview of QueryFilteryou will learn more in a later lesson.
Click the X on the Object Browser tab to close it.
4-31
Return the number of rows (or features) in your shapefile and store the result in
numRows.
numRows = tab.________________(null);
Make an additional modification to place your results in the text box on your form.
txtCount.________ = ________.ToString();
The code will populate your text box with the number of rows (or records or features) in
your shapefile. In addition, the code will convert the numeric value to a string.
Build your project.
Question 16: Based on the license you have chosen, if you wanted to share your
application with another person, what software would need to be installed on that
person's computer?
______________________________________________________________________
Now you are ready to run your project.
Return to your code and run your project.
Click your Count Features button to test your code.
4-32
Exercise 4B
Conclusion
In this exercise, you created a small application to count the number of features in a
shapefile. To save time, you inserted a snippet into your application and then used the
developer resources to understand the code it contained. You learned how useful the
developer help is for searching classes, interfaces, methods, and properties to see what is
available and which library they are located in, while OMDs allow you to easily view
relationships between objects. You also explored the ArcGIS Resource Centers.
In future lessons, you will use the skills you developed here for searching the help system
and OMDs for casting between interfaces.
4-33
4-34
Exercise 4B
Question 10: What are the variables returned by OpenFromFile and OpenTable? Are the
variables declared to the correct return data types?
Answer: ws and tab; yes
Question 11: What is the error that displays?
Answer: Type 'IWorkspaceFactory' could not be found
Question 12: Which library contains the IWorkspaceFactory interface?
Answer: ESRI.ArcGIS.GeoDatabase
Question 13: Which of the objects seems to have the most potential for giving you the
number of features in your shapefile? (Hint: It contains the attributes.)
Answer: tab (or ITable)
Question 14: Which method will return the number of features in a shapefile (or the rows
in a table), and what is the data type that is returned?
Answer: RowCount, int
Question 15: Which method lets you select features, and what does this method accept as
its first argument?
Answer: Select, IQueryFilter
Question 16: Based on the license you have chosen, if you wanted to share your
application with another person, what software would need to be installed on that
person's computer?
Answer: ArcGIS Desktop
Question 17: How many features are in your shapefile?
Answer: 606
Question 18: How many records are in the table? Did your code return the correct
number?
Answer: 606; yes
4-35
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
namespace CountFeatures
{
public partial class frmCount : Form
{
public frmCount()
{
InitializeComponent();
}
private void btnCount_Click(object sender, System.EventArgs e)
{
// ArcGIS Snippet Title:
// Count Features
//
// Long Description:
// Count the number of features in a shapefile
//
// Intended ArcGIS Products for this snippet:
// ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
// ArcGIS Engine
//
// Applicable ArcGIS Product Versions:
// 9.2
// 9.3
//
// Required ArcGIS Extensions:
// (NONE)
//
// Notes:
// This snippet is intended to be inserted inside a Method.
// It is not intended to be added to the base level of the Class.
string filePath = "\\Student\\IPAN\\Database";
string tableName = "Cities.shp";
IWorkspaceFactory wsfactory = new ShapefileWorkspaceFactoryClass();
IWorkspace ws = wsfactory.OpenFromFile(filePath, 0);
IFeatureWorkspace fws = ws as IFeatureWorkspace;
ITable tab = fws.OpenTable(tableName);
// do something with the table
4-36
Exercise 4B
long numRows;
numRows = tab.RowCount(null);
txtCount.Text = numRows.ToString();
4-37
5
Working with maps
and layers
Exercise 5A: Work with maps and layers
(VB.NET)
Estimated time: 45 minutes
Exercise 5B: Work with maps and layers
(C#)
Estimated time: 45 minutes
Exercise 5A
Exercise shortcut
1. In Visual Studio, open the MapsAndLayers.sln solution from the
\Student\IPAN\Exercise05\VisualBasic folder.
2. Load a map document programmatically and access the collection of maps found
in the map document.
3. Programmatically allow the user to browse to the desired map and add each map's
name to the list box.
4. Access the layers in your map and add each layer's name to the list box.
** (Optional) Respond to MapControl events to copy the map to a
PageLayoutControl.
** (Optional) Distinguish between feature layers and raster layers in your map
document.
5-1
The form contains a MapControl, plus several Visual Studio buttons and other controls.
This form will display information about the current map document, such as the names of
the maps and layers and their fields.
Click the form to view its properties in the Properties window.
Question 1: What is the name of the form?
______________________________________________________________________
5-2
Exercise 5A
At the top of the form, click the combo box and view its (Name) property in the
Properties window.
You will use this combo box, cboMaps, to display a list of the names of the data frames
(maps) contained in a map document.
Question 2: What type of control are lboMapLayers and lboFields? What type of items
can be stored in them?
______________________________________________________________________
You will use the lboMapLayers control to display a list of layers contained in the data
frame that are selected in the combo box.
5-3
Place your cursor inside the method, right-click, and choose Insert Snippet.
Navigate to and double-click IPAN_CodeSnippets > Visual Basic >
IPAN_Ex05_OpenFileDialog.
Build your project.
Question 4: Which reference do you need to add?
______________________________________________________________________
From the Project menu, click Add ArcGIS reference.
Expand Desktop ArcMap.
Notice the COM interface icon with the checkmark. This indicates that a reference to
ESRI.ArcGIS.Carto has already been added to your project. This Visual Studio project
was created from an ArcGIS Desktop Windows template, so some references have
automatically been added for you. All you need to do is import the namespaces for those
libraries.
Close the dialog box.
Above the class declaration, import the namespace.
Note: Remember, if an ArcGIS reference had not been added automatically, you would
need to add it or use the fully-qualified namespace path.
The IMapDocument interface on the MapDocument coclass contains a Map property. You
will use this property to access the collection of maps in the document. You will also
need to use the MapDocument variable in other sub procedures. You will begin by
creating a module-level variable.
In the btnLoadMxd_Click method, copy the line Dim mapDocument As
IMapDocument and then comment it.
5-4
Exercise 5A
The "m_" prefix to the variable name indicates that it is a module-level variable.
Add the "m_" prefix to the variable name throughout the snippet.
Rather than browse to all folders on your C drive, you will narrow down the options to
your Student folder.
Modify the InitialDirectory property to point to the \Student\IPAN folder.
Now you are ready to add the name of each map to your combo box.
After the Open method, loop through the maps in the map document by completing the
following code. Inside the For loop, write the name of each map to the combo box
cboMaps on your form, based on the number of maps in the map document.
Dim i As ______________
For i = ____ To ________________________._________________ - 1
cboMaps.Items.______(m_mapDocument.______(__).Name)
Next
Lastly, you will populate your combo box with a default map name.
Set cboMaps.Text equal to the name of the first map in the map document.
Complete the following code to write the name of the map document's active data
frame to a label on the form:
lblDataFrame.Text = "Active Data Frame: " & m_mapDocument.ActiveView.FocusMap.________
The code you have written populates a combo box, which will allow you to choose the
map you want to display.
5-5
5-6
Exercise 5A
Using the developer resource of your choice, answer the following questions:
Question 6: Which property on the IMaps interface returns a pointer to an object that
supports IMap?
______________________________________________________________________
Question 7: Which property on the IMap interface returns a reference to an object that
supports IEnumLayer?
______________________________________________________________________
Question 8: Which method on the IEnumLayer interface returns a reference to an object
that supports ILayer?
______________________________________________________________________
On the Visual Studio navigation bar, use the drop-down lists to navigate to the
SelectedValueChanged method for cboMaps (cboMaps_SelectedValueChanged).
When the value in this combo box changes, the names of the selected map's layers will be
updated in the list box.
Next, you will return a count of the maps in the map document and assign the result to a
variable.
Declare the variable i as Integer.
Begin a For Next loop that is controlled by the number of maps in the collection.
5-7
You will loop through all the maps in the map document until you find the one whose
name matches the one selected in the combo box.
Inside the loop, write the following code to provide the logic for finding the chosen
map and adding it to your MapControl:
m_map = m_mapDocument.______(i) ' Pull a map from the collection
If m_map.____ = cboMaps.SelectedItem() Then ' Is this the chosen map?
axMapControl1.______ = m_map
Exit For ' Exits the loop once the map is found
End If
Note: From this point forward, the code may contain comments to help you understand
it. Although it is not required, if you want to type them, remember to begin comments
with a quotation mark and surround text strings with double quotation marks.
Now that you have found the specified map, you will write another loop to add the name
of each layer in the map to a list box.
After the For Next loop, initialize m_enumLayers with all the layers in the chosen
map by completing the following code:
m_enumLayers = m_map.____________ ' Not just one layer!
Complete the following code to initialize the layer variable by pulling the first layer
out of the enumLayers enumeration:
m_layer = m_enumLayers.________()
A For Next loop (like you just wrote) is useful if you know how many times to
loop.
The loop you need to write now uses syntax to loop based on a condition.
Complete the following loop to write the name of each layer to the lboMapLayers list
box:
Do __________ m_layer Is Nothing
lboMapLayers.Items.Add(m_layer.________)
m_layer = m_enumLayers.Next()
Loop
5-8
Exercise 5A
Note: If you have errors, compare your code with the following:
Dim i As Integer
For i = 0 To m_mapDocument.MapCount - 1
m_map = m_mapDocument.Map(i) ' Pull a map from the collection
If m_map.Name = cboMaps.SelectedItem() Then ' Is this the chosen map?
axMapControl1.Map = m_map
Exit For ' Exits the loop once the map is found
End If
Next
m_enumLayers = m_map.Layers ' Not just one layer!
m_layer = m_enumLayers.Next()
Do Until m_layer Is Nothing
lboMapLayers.Items.Add(m_layer.Name)
m_layer = m_enumLayers.Next()
Loop
Click the Load Mxd button and load MapsAndLayers.mxd from your
\Student\IPAN\Exercise05 folder.
The Kauai, HI data frame appears as the default in your combo box. The layers of the
Kauai, HI map display in the list box.
Choose each of the other maps.
5-9
In the list box, notice that the layers for each map that you choose are added to the end of
the list of layers for the previously chosen map. You will take care of this next.
Close your application.
Add the following code to the top of the cboMaps_SelectedValueChanged method to
remove any existing text items from the lboMapLayers list box before new items are
added:
lboMapLayers.Items.Clear()
Next, write the following single line of code to enable the Frame Info button when a
map name is chosen in the combo box:
btnFrameInfo.Enabled = cboMaps.Text <> ""
Note: The button will be disabled until a map name is chosen.
Write a line of code to enable the Layer Info button once a map name is chosen.
Navigate to the Click event of the btnFrameInfo and expand it, if necessary.
Uncomment the code.
Navigate to the Click event of the btnLayerInfo and uncomment the code.
Run your project.
In your application, load MapsAndLayers.mxd.
Choose a data frame, then click your Frame Info button to test it.
Click OK on the message box.
From the Data Frames combo box, choose each of the maps to make sure that the list
box is cleared properly and that the buttons are enabled when the corresponding list
box has been populated.
You now know how to loop through each map in the document, as well as through each
layer in a map.
Close your application.
5-10
Exercise 5A
You have finished this exercise, however, you may wish to complete the optional steps:
Step 5 shows you how to create a layout whenever you choose a new map.
Step 6 shows you how to distinguish feature layers from raster layers.
If you want to complete the optional steps, do so now. Otherwise, close Visual Studio.
You see a long list of the events on the MapControl. You can customize your project by
writing code to respond to any of these events.
Choose the OnMapReplaced event in the list.
Insert the IPAN_Ex05_CopyMapToLayout code snippet. (Hint: Right-click > Insert
Snippet.)
Review the code and add any necessary references to your project.
Note that the code responds to an event that occurs automatically whenever a new map is
added.
Before the code that copies the map, clear the active view of the page layout.
Run your project.
5-11
On the Visual Studio navigation bar, use the drop-down lists to navigate to the
SelectedValueChanged method for the lboMapLayers list box
(lboMapLayers_SelectedValueChanged).
In the same way that you previously cleared the contents of lboMapLayers, clear the
items from the lboFields list box.
Now you will write a looping routine to find the layer chosen in the lboMapLayers list
box.
Complete the following loop to locate the selected layer. (Tip: Because most variables
used earlier were declared as module-level, you can use them here.)
m_enumLayers.__________ ' Move the enum pointer above the first layer
m_layer = m_enumLayers.________ ' Return the first layer from the enumeration
____ __________ m_layer ____ Nothing ' Begin the conditional loop
If m_layer.Name = lboMapLayers.Text Then ' Check whether this is the layer
Exit ____ ' If the layer is found, exit the loop (but not the Sub)
End If
m_layer = ____________________.________ ' Return another layer
Loop ' End the loop
5-12
Exercise 5A
After the loop finishes, m_layer will be set to the layer selected in the list box.
Next, you will test the type of layer that is selected. You will use the TypeOf structure to
determine which interfaces an object variable supports.
Complete the following code to determine whether the selected layer (m_layer) is a
type of feature layer. If it is not, write "Not a feature layer" in the lboFields list
box.
If Not ____________ m_layer Is IFeatureLayer2 ________
'Does it support this interface?
lboFields.__________.______("Not a feature layer")
Exit Sub ' Stop executing the procedure
End If
Because the loop exits the sub procedure if the chosen layer does not support the
IFeatureLayer interface, the remainder of your code can assume that a feature layer was
chosen in the list box.
Below the If statement, enter the following code to enable the Field Info button:
btnFieldInfo.Enabled = lboMapLayers.Text <> ""
5-13
Conclusion
In this exercise, you programmatically loaded an existing map document into an ArcGIS
Engine MapControl. You created your own "table of contents" by using properties on the
map document to access the maps, or data frames, that it contained, as well as the layers
in each map.
If you completed the optional steps, you responded to the associated map event by
populating a page layout whenever the map changed, and distinguished feature layers
from raster layers. You also learned how to access GIS data programmaticallyeven
without a visual table of contents.
5-14
Exercise 5A
5-15
5-16
Exercise 5A
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
OpenFileDialog1.Title = "Browse"
OpenFileDialog1.Filter = "Map Documents (*.mxd) | *.mxd"
OpenFileDialog1.InitialDirectory = "\Student\IPAN"
OpenFileDialog1.ShowDialog()
Dim sFilePath As String
sFilePath = OpenFileDialog1.FileName
'Dim mapDocument As IMapDocument
m_mapDocument = New MapDocument
If (Not m_mapDocument.IsMapDocument(sFilePath)) Then Exit Sub
m_mapDocument.Open(sFilePath)
Dim i As Integer
For i = 0 To m_mapDocument.MapCount - 1
cboMaps.Items.Add(m_mapDocument.Map(i).Name)
Next
cboMaps.Text = m_mapDocument.Map(0).Name
lblDataFrame.Text = _
"Active Data Frame: " & m_mapDocument.ActiveView.FocusMap.Name
End Sub
Private Sub cboMaps_SelectedValueChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles cboMaps.SelectedValueChanged
lboMapLayers.Items.Clear()
btnFrameInfo.Enabled = cboMaps.Text <> ""
btnLayerInfo.Enabled = cboMaps.Text <> ""
5-17
Dim i As Integer
For i = 0 To m_mapDocument.MapCount - 1
m_map = m_mapDocument.Map(i) ' Pull a map from the collection
If m_map.Name = cboMaps.SelectedItem() Then ' Is this the chosen map?
AxMapControl1.Map = m_map
Exit For ' Exits the loop once the map is found
End If
Next
m_enumLayers = m_map.Layers ' Not just one layer!
m_layer = m_enumLayers.Next()
Do Until m_layer Is Nothing
lboMapLayers.Items.Add(m_layer.Name)
m_layer = m_enumLayers.Next()
Loop
End Sub
Private Sub axMapControl1_OnMapReplaced(ByVal sender As Object, _
ByVal e As ESRI.ArcGIS.Controls.IMapControlEvents2_OnMapReplacedEvent) _
Handles axMapControl1.OnMapReplaced
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
AxPageLayoutControl1.ActiveView.Clear()
'Get IObjectCopy interface
Dim objectCopy As IObjectCopy
objectCopy = New ObjectCopy
'Get IUnknown interface (map to copy)
Dim toCopyMap As Object
'toCopyMap = AxPageLayoutControl1.ActiveView.FocusMap
toCopyMap = axMapControl1.ActiveView.FocusMap
'Get IUnknown interface (copied map)
Dim copiedMap As Object
copiedMap = pObjectCopy.Copy(toCopyMap)
'Get IUnknown interface (map to overwrite)
Dim toOverwriteMap As Object
'toOverwriteMap = AxMapControl1.Map
toOverwriteMap = AxPageLayoutControl1.ActiveView.FocusMap
5-18
Exercise 5A
5-19
Exercise 5B
Exercise shortcut
1. In Visual Studio, open the MapsAndLayers.sln solution from the
\Student\IPAN\Exercise05\CSharp folder.
2. Load a map document programmatically and access the collection of maps found
in the map document.
3. Programmatically allow the user to browse to the desired map and add each map's
name to the list box.
4. Access the layers in your map and add each layer's name to the list box.
** (Optional) Respond to MapControl events to copy the map to a
PageLayoutControl.
** (Optional) Distinguish between feature layers and raster layers in your map
document.
5-21
The form contains a MapControl, plus several Visual Studio buttons and other controls.
This form will display information about the current map document, such as the names of
the maps and layers and their fields.
Click the form to view its properties in the Properties window.
Question 1: What is the name of the form?
______________________________________________________________________
5-22
Exercise 5B
At the top of the form, click the combo box and view its (Name) property in the
Properties window.
You will use this combo box, cboMaps, to display a list of the names of the data frames
(maps) contained in a map document.
Question 2: What type of control are lboMapLayers and lboFields? What type of items
can be stored in them?
______________________________________________________________________
You will use the lboMapLayers control to display a list of layers contained in the data
frame that are selected in the combo box.
5-23
Place your cursor inside the method, right-click, and choose Insert Snippet.
Navigate to and double-click IPAN_CodeSnippets > CSharp >
IPAN_Ex05_OpenFileDialog.
Build your project.
Question 4: Which reference do you need to add?
______________________________________________________________________
From the Project menu, click Add ArcGIS reference.
Expand Desktop ArcMap.
Notice the COM interface icon with the checkmark. This indicates that a reference to
ESRI.ArcGIS.Carto has already been added to your project. This Visual Studio project
was created from an ArcGIS Desktop Windows template, so some references have
automatically been added for you. All you need to do is import the namespaces for those
libraries.
Close the dialog box.
Above the class declaration, import the namespace.
Note: Remember, if an ArcGIS reference had not been added automatically, you would
need to add it or use the fully-qualified namespace path.
The IMapDocument interface on the MapDocument coclass contains a Map property. You
will use this property to access the collection of maps in the document. You will also
need to use the MapDocument variable in other methods. You will begin by creating a
module-level variable.
In the btnLoadMxd_Click method, copy the line IMapDocument mapDocument; and
then comment it.
5-24
Exercise 5B
The "m_" prefix to the variable name indicates that it is a module-level variable.
Add the "m_" prefix to the variable name throughout the snippet.
Rather than browse to all folders on your C drive, you will narrow down the options to
your Student folder.
Modify the InitialDirectory property to point to the \\Student\\IPAN folder.
Now you are ready to add the name of each map to your combo box.
After the Open method, loop through the maps in the map document by completing the
following code. Inside the For loop, write the name of each map to the combo box
cboMaps on your form, based on the number of maps in the map document.
for (int i = 0; i < m_mapDocument.MapCount; i++) {
cboMaps.Items.______(m_mapDocument.________________(__).Name);
}
Lastly, you will populate your combo box with a default map name.
Set cboMaps.Text equal to the name of the first map in the map document.
Complete the following code to write the name of the map document's active data
frame to a label on the form:
lblDataFrame.Text = "Active Data Frame: " + m_mapDocument.ActiveView.FocusMap.________;
5-25
The code you have written populates a combo box, which will allow you to choose the
map you want to display.
5-26
Exercise 5B
When you want to find a particular map according to its name, you can use an if
statement inside a looping structure. You will begin that process by declaring some
module-level variables.
View the code for Form1.
At the beginning of your class, below the declaration for IMapDocument, declare the
following variables:
private IEnumLayer m_enumLayers;
private IMap m_map;
private ILayer2 m_layer;
Using the developer resource of your choice, answer the following questions:
Question 6: Which property on the IMaps interface returns a pointer to an object that
supports IMap?
______________________________________________________________________
Question 7: Which property on the IMap interface returns a reference to an object that
supports IEnumLayer?
______________________________________________________________________
Question 8: Which method on the IEnumLayer interface returns a reference to an object
that supports ILayer?
______________________________________________________________________
In Design view, click the cboMaps combo box to display its properties in the
Properties window.
In the Properties window, click the Events
button.
You see a list of the events on the combo box. You can customize your project by writing
code to respond to any of these events.
In the list of events, find SelectedValueChanged and double-click it to open the code
for this event.
When the value in this combo box changes, the names of the selected map's layers will be
updated in the list box.
5-27
Next, you will return a count of the maps in the map document and assign the result to a
variable.
Begin a For loop that is controlled by the number of maps in the collection.
You will loop through all the maps in the map document until you find the one whose
name matches the one selected in the combo box.
Inside the loop, write the following code to provide the logic for finding the chosen
map and adding it to your MapControl:
{
Now that you have found the specified map, you will write another loop to add the name
of each layer in the map to a list box.
After the For loop, initialize m_enumLayers with all the layers in the chosen map by
completing the following code:
m_enumLayers = m_map.____________(null, true); //Not just one layer!
Complete the following code to initialize the layer variable by pulling the first layer
out of the enumLayers enumeration:
m_layer = m_enumLayers.________() as ______________;
A For loop (like you just wrote) is useful if you know how many times to loop.
The loop you need to write now uses syntax to loop based on a condition.
Add the following code to write the name of each layer to the lboMapLayers list box:
5-28
Exercise 5B
do
{
lboMapLayers.Items.Add(m_layer.Name);
m_layer = m_enumLayers.Next() as ILayer2;
} while (m_layer != null);
lboMapLayers.Items.Add(m_layer.Name);
m_layer = m_enumLayers.Next() as ILayer2;
} while (m_layer != null);
5-29
Click the Load Mxd button and load MapsAndLayers.mxd from your
\Student\IPAN\Exercise05 folder.
The Kauai, HI data frame appears as the default in your combo box. The layers of the
Kauai, HI map display in the list box.
Choose each of the other maps.
In the list box, notice that the layers for each map that you choose are added to the end of
the list of layers for the previously chosen map. You will take care of this next.
Close your application.
Add the following code to the top of the cboMaps_SelectedValueChanged method to
remove any existing text items from the lboMapLayers list box before new items are
added:
lboMapLayers.Items.Clear();
After the do-while loop, write the following line of code to enable the Frame Info
button when a map name is chosen in the combo box:
btnFrameInfo.Enabled = cboMaps.Text != "";
5-30
Exercise 5B
Write a line of code to enable the Layer Info button when a map name is chosen.
Navigate to the Click event of the btnFrameInfo and expand it, if necessary.
Uncomment the code.
Navigate to the Click event of the btnLayerInfo and uncomment the code.
Run your project.
In your application, load MapsAndLayers.mxd.
Choose a data frame, then click your Frame Info button to test it.
Click OK on the message box.
From the Data Frames combo box, choose each of the maps to make sure that the list
box is cleared properly and that the buttons are enabled when the corresponding list
box has been populated.
You now know how to loop through each map in the document, as well as through each
layer in a map.
Close your application.
You have finished this exercise, however, you may wish to complete the optional steps:
Step 5 shows you how to create a layout whenever you choose a new map.
Step 6 shows you how to distinguish feature layers from raster layers.
If you want to complete the optional steps, do so now. Otherwise, close Visual Studio.
5-31
5-32
Exercise 5B
In Design view, click the lboMapLayers list box to display its properties in the
Properties window.
Click the Events button
After the loop finishes, m_layer will be set to the layer selected in the list box.
Next, you will test the type of layer that is selected. You will use the is structure to
determine which interfaces an object variable supports.
After the //Determine comment, complete the following code to determine whether
the selected layer (m_layer) is a type of feature layer. If it is not, write "Not a
feature layer" in the lboFields list box.
if (!(m_layer is IFeatureLayer2))
{
lboFields.Items.______("Not a feature layer");
}
break; //If the layer is found, exit the loop
5-33
Because the loop exits the method if the chosen layer does not support the
IFeatureLayer interface, the remainder of your code can assume that a feature layer was
chosen in the list box.
Below the while loop, enter the following code to enable the Field Info button:
btnFieldInfo.Enabled = (lboMapLayers.Text != "");
Conclusion
In this exercise, you programmatically loaded an existing map document into an ArcGIS
Engine MapControl. You created your own "table of contents" by using properties on the
map document to access the maps, or data frames, that it contained, as well as the layers
in each map.
If you completed the optional steps, you responded to the associated map event by
populating a page layout whenever the map changed, and distinguished feature layers
from raster layers. You also learned how to access GIS data programmaticallyeven
without a visual table of contents.
5-34
Exercise 5B
5-35
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
namespace MapsAndLayers
{
public partial class frmDocInfo : Form
{
private
private
private
private
IMapDocument m_mapDocument;
IEnumLayer m_enumLayers;
IMap m_map;
ILayer2 m_layer;
public frmDocInfo()
{
InitializeComponent();
}
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
private void btnLayerInfo_Click(object sender, EventArgs e)
{
MessageBox.Show(String.Format("{0:#} layers in the active map", m_map.LayerCount));
}
private void btnFieldInfo_Click(object sender, EventArgs e)
{
MessageBox.Show("You will learn how to access fields in a later lesson");
}
private void btnLoadMxd_Click(object sender, EventArgs e)
{
5-36
Exercise 5B
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
openFileDialog1.Title = "Browse";
openFileDialog1.Filter = "Map Documents (*.mxd) | *.mxd";
openFileDialog1.InitialDirectory = "\\Student\\IPAN";
openFileDialog1.ShowDialog();
string sFilePath;
sFilePath = openFileDialog1.FileName;
//IMapDocument mapDocument;
m_mapDocument = new MapDocument();
if (!m_mapDocument.get_IsMapDocument(sFilePath))
{
return;
}
m_mapDocument.Open(sFilePath, "");
for (int i = 0; i < m_mapDocument.MapCount; i++)
{
cboMaps.Items.Add(m_mapDocument.get_Map(i).Name);
}
cboMaps.Text = m_mapDocument.get_Map(0).Name;
5-37
do
{
lboMapLayers.Items.Add(m_layer.Name);
m_layer = m_enumLayers.Next() as ILayer2;
} while (m_layer != null);
axPageLayoutControl1.ActiveView.Clear();
IObjectCopy objectCopy;
objectCopy = new ObjectCopy();
object toCopyMap;
toCopyMap = axMapControl1.ActiveView.FocusMap;
object copiedMap;
copiedMap = objectCopy.Copy(toCopyMap);
object toOverwriteMap;
toOverwriteMap = axPageLayoutControl1.ActiveView.FocusMap;
5-38
Exercise 5B
5-39
6
Accessing data
Exercise 6A
Access a workspace
Access feature classes
Add feature layers to a MapControl
Exercise shortcut
1. In ArcCatalog, open an existing workspace, the World.gdb file geodatabase from
\Student\IPAN\Database folder.
2. In Visual Studio, create a new Visual Basic ArcGIS Engine MapControl
Application.
3. Programmatically open the Countries feature class from the World feature dataset
and then open the Lakes stand-alone feature class.
4. Create new FeatureLayer object variables to store layers for your two feature
classes.
5. Set the data sources for your feature layers to reference the data.
6. Set the Name and some other general properties for your new feature layers.
7. Add your feature layers to the MapControl.
** (Optional) Conditionally show MapTips for a selected layer.
6-1
You will be accessing data stored in this geodatabase throughout this exercise.
Question 1: How many feature datasets are in this geodatabase?
______________________________________________________________________
Question 2: How many feature classes are there? How many stand-alone feature classes?
______________________________________________________________________
Close ArcCatalog.
!
6-2
Property
Value
Language
Visual Basic
Project type
Template
MapControl Application
Name
DataAccess
Location
\Student\IPAN\Exercise06
Solution name
DataAccess
Make sure the Create directory for solution check box is checked.
Exercise 6A
Notice that this template provides you with ArcGIS Engine controls, including a
LicenseControl.
Review the MainForm code.
Collapse the existing sub procedures, but do not collapse the class.
6-3
This wormhole points you to additional OMDs where you will find other classes and
interfaces.
Question 5: What is the relationship between all of the various workspace factories and
the WorkspaceFactory class?
______________________________________________________________________
Open the DataSourcesGDB OMD.
Zoom in on the area shown in the following graphic:
These are the various types of geodatabase workspace factories. You will be opening a
file geodatabase, so you need to create a new FileGDBWorkspaceFactory object.
Note: Notice the wormhole leading back to the WorkspaceFactory class in the
Geodatabase OMD.
6-4
Exercise 6A
In Visual Studio, just before the end of the class, add a new private sub procedure
named AddData with no arguments.
In your sub procedure, declare a variable named wsFactory as a new
FileGDBWorkspaceFactory object.
Add the necessary reference and namespace to your project.
Now that you have had some practice adding references, importing
namespaces, and resolving implicit conversions, it is your
responsibility for the remainder of the course to address these issues in
your code as necessary.
Declare a variable named workspace to return the interface based on what is returned
by the OpenFromFile method.
Verify that your code looks like the following:
Dim wsFactory As IWorkspaceFactory
wsFactory = New FileGDBWorkspaceFactory
Dim workspace As IWorkspace
6-5
Hover your mouse pointer over workspace and notice the reference to implicit casting.
Use the CType structure to change the code from an implicit cast to an explicit cast.
Declare a variable named fcCountries to the interface that is returned by the
OpenFeatureClass method.
Instantiate the new variable with the following code:
fcCountries = fWS.OpenFeatureClass("Countries")
The fcCountries variable now references the Countries feature class. Recall that the
World feature dataset contains two feature classes that you want to add to the map:
Countries and Lakes. You will now access the Lakes feature class.
Declare a variable named fcLakes to the IFeatureClass interface.
Instantiate fcLakes with the following code:
fcLakes = fWS.OpenFeatureClass("Lakes")
You now have two variables, each referencing a feature class within the World feature
dataset. You do not need to open the feature dataset to access the feature classes because
each feature class in the workspace has a unique name; thus, there are no conflicts
between stand-alone feature classes and feature classes that reside in a feature dataset.
6-6
Exercise 6A
Verify that the code for your two new feature layers matches the following:
Dim countriesLayer As IFeatureLayer
countriesLayer = New FeatureLayer
Dim lakesLayer As IFeatureLayer
lakesLayer = New FeatureLayer
In the Interfaces area, verify that you are searching for an interface name.
6-7
The FeatureClass property on IFeatureLayer will point your new layer to a data
source. Notice that the return type of the FeatureClass property is IFeatureClass.
Both variables that you have pointing to a feature class support IFeatureClass, as seen
in the code you wrote earlier:
Question 9: What does the symbol used for FeatureClass property mean ?
______________________________________________________________________
Complete the following code to set the FeatureClass property for your two layer
variables:
countriesLayer.________________________ = fcCountries
lakesLayer.________________________ = ______________
Now that the data source has been set, you will set some general properties.
6-8
Exercise 6A
Layer
Property
Value
countriesLayer
Name
World Countries
countriesLayer
ShowTips
True
------------------------
------------------------
------------------------
lakesLayer
Name
World Lakes
lakesLayer
ShowTips
False
lakesLayer
Visible
False
Why did you set the Lakes layer to invisible? There are times when you do not want all
the layers that you add to a map to draw by default for example, when the layers
contain lots of data coming from a multiuser geodatabase. In cases like these, making a
layer invisible is more efficient.
6-9
6-10
Exercise 6A
The layers are displayed with default symbology. In a later lesson, you will learn how to
modify layer symbology.
Close your application.
You have finished this exercise, however, you may wish to complete the optional step:
If you want to complete the optional step, do so now. Otherwise, close Visual Studio.
6-11
In code view, use the Class Name and Method Name drop-down lists to navigate to
your TOCControl's OnMouseDown event.
Place your mouse pointer inside the event code, then right-click and insert the snippet
IPAN_Ex06_TOC_HitTest.
Review the code.
6-12
Exercise 6A
In the event, find the line of code that contains the HitTest method.
Right-click the HitTest method and choose Go To Definition.
Question 12: What data type do the x and y properties of e return?
______________________________________________________________________
The x,y coordinates represent the pixels of items clicked in the table of contents.
Now that you have entered the code that will tell you whether a layer has been selected,
you need to know whether to show MapTips.
In code view, navigate to the chkShowTips check box's CheckStateChanged event.
Insert the snippet IPAN_Ex06_ShowTips.
Question 13: Which types of layers will display MapTips?
______________________________________________________________________
Navigate to the MainForm_Load event.
Immediately before AddData(), enter the following code to initialize MapTips to the
off state:
axMapControl1.ShowMapTips = False
chkShowTips.CheckState = CheckState.Unchecked
6-13
Conclusion
In this exercise, you learned how to add feature layers to your map using ArcObjects
code. You accessed a workspace to open feature classes, created new feature layers
referencing the feature classes, and set properties for the feature layers. Finally, you
added the feature layers to ArcMap.
6-14
Exercise 6A
6-15
6-16
Exercise 6A
System.IO
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Controls
ESRI.ArcGIS.ADF
ESRI.ArcGIS.SystemUI
ESRI.ArcGIS.Geodatabase
ESRI.ArcGIS.DataSourcesGDB
6-17
6-18
Exercise 6A
6-19
6-20
Exercise 6A
6-21
Exercise 6B
Access a workspace
Access feature classes
Add feature layers to a MapControl
Exercise shortcut
1. In ArcCatalog, open an existing workspace, the World.gdb file geodatabase from
\Student\IPAN\Database folder.
2. In Visual Studio, create a new Visual C# ArcGIS Engine MapControl Application.
3. Programmatically open the Countries feature class from the World feature dataset
and then open the Lakes stand-alone feature class.
4. Create new FeatureLayer object variables to store layers for your two feature
classes.
5. Set the data sources for your feature layers to reference the data.
6. Set the Name and some other general properties for your new feature layers.
7. Add your feature layers to the MapControl.
** (Optional) Conditionally show MapTips for a selected layer.
6-23
You will be accessing data stored in this geodatabase throughout this exercise.
Question 1: How many feature datasets are in this geodatabase?
______________________________________________________________________
Question 2: How many feature classes are there?
______________________________________________________________________
Question 3: How many stand-alone feature classes are there?
______________________________________________________________________
Close ArcCatalog.
6-24
Property
Value
Language:
Visual C#
Project type:
Template:
MapControl Application
Name:
DataAccess
Location:
\Student\IPAN\Exercise06
Solution name:
DataAccess
Exercise 6B
Make sure the Create directory for solution check box is checked.
Notice that this template gives you ArcGIS Engine controls, including a LicenseControl.
Review the MainForm code.
Collapse the existing methods, but do not collapse the class.
6-25
Locate the WorkspaceFactory class in the upper left and the wormhole below it.
This wormhole points you to additional OMDs where you will find other classes and
interfaces.
Question 6: What is the relationship between all of the various workspace factories and
the WorkspaceFactory class?
______________________________________________________________________
Open the DataSourcesGDB OMD.
6-26
Exercise 6B
These are the various types of geodatabase workspace factories. You will be opening a
file geodatabase, so you need to create a new FileGDBWorkspaceFactory object.
Note: Notice the wormhole leading back to the WorkspaceFactory class in the
Geodatabase OMD.
In Visual Studio, just before the end of the class, add a new private method named
AddData with no arguments.
In your method, declare a variable named wsFactory as a new
FileGDBWorkspaceFactory object.
Add the necessary reference and namespace to your project.
6-27
Now that you have had some practice adding references, importing
namespaces, and resolving implicit conversions, it is your
responsibility for the remainder of the course to address these issues in
your code as necessary.
Declare a variable named workspace to return the interface based on what is returned
by theOpenFromFile method.
Verify that your code looks like the following:
IWorkspaceFactory wsFactory = new FileGDBWorkspaceFactoryClass();
IWorkspace workspace;
6-28
Exercise 6B
The fcCountries variable now references the Countries feature class. Recall that the
World feature dataset contains two feature classes that you want to add to the map:
Countries and Lakes. You will now access the Lakes feature class.
Declare a variable named fcLakes to the IFeatureClass interface.
Instantiate fcLakes with the following code:
fcLakes = fWS.OpenFeatureClass("Lakes");
You now have two variables, each referencing a feature class within the World feature
dataset. You do not need to open the feature dataset to access the feature classes because
each feature class in the workspace has a unique name; thus, there are no conflicts
between stand-alone feature classes and feature classes that reside in a feature dataset.
6-29
Verify that your code for the two new feature layers matches the following:
IFeatureLayer countriesLayer;
countriesLayer = new FeatureLayer();
IFeatureLayer lakesLayer;
lakesLayer = new FeatureLayer();
In the Interfaces area, verify that you are searching for an interface name.
The FeatureClass property on IFeatureLayer will point your new layer to a data
source. Notice that the return type of the FeatureClass property is IFeatureClass.
Both variables that you have pointing to a feature class support IFeatureClass, as seen
in the code you wrote earlier:
6-30
Exercise 6B
Question 10: What does the symbol used for FeatureClass property mean ?
______________________________________________________________________
Complete the following code to set the FeatureClass property for your two layer
variables:
countriesLayer.________________________ = fcCountries;
lakesLayer.________________________ = ______________;
Now that the data source has been set, you will set some general properties.
Layer
Property
Value
countriesLayer
Name
World Countries
countriesLayer
ShowTips
true
------------------------
------------------------
------------------------
lakesLayer
Name
World Lakes
lakesLayer
ShowTips
false
lakesLayer
Visible
false
Why did you set the Lakes layer to invisible? There are times when you do not want all
the layers that you add to a map to draw by default for example, for example when the
6-31
layers contain lots of data coming from a multiuser geodatabase. In cases like these,
making a layer invisible is more efficient.
6-32
Exercise 6B
The layers are displayed with default symbology. In a later lesson, you will learn how to
modify layer symbology.
Close your application.
You have finished this exercise, however, you may wish to complete the optional step:
6-33
If you want to complete the optional step, do so now. Otherwise, close Visual Studio.
6-34
Exercise 6B
6-35
6-36
Exercise 6B
Hover your mouse pointer over lake features in the map to view the MapTips.
Uncheck the Show MapTips box.
Select the World Countries layer, turn MapTips on again, and view them in the map.
When you are finished, close your application and close Visual Studio.
Conclusion
In this exercise, you learned how to add feature layers to your map using ArcObjects
code. You accessed a workspace to open feature classes, created new feature layers
referencing the feature classes, and set properties for the feature layers. Finally, you
added the feature layers to ArcMap.
6-37
6-38
Exercise 6B
6-39
System;
System.Drawing;
System.Collections;
System.ComponentModel;
System.Windows.Forms;
System.Data;
System.IO;
System.Runtime.InteropServices;
using
using
using
using
using
ESRI.ArcGIS.esriSystem;
ESRI.ArcGIS.Carto;
ESRI.ArcGIS.Controls;
ESRI.ArcGIS.ADF;
ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
namespace DataAccess
{
public sealed partial class MainForm : Form
{
#region class private members
private IMapControl3 m_mapControl = null;
private string m_mapDocumentName = string.Empty;
private ILayer m_layer;
#endregion
#region class constructor
public MainForm()
{
InitializeComponent();
}
#endregion
private void MainForm_Load(object sender, EventArgs e)
{
//get the MapControl
m_mapControl = (IMapControl3)axMapControl1.Object;
//disable the Save menu (since there is no document yet)
menuSaveDoc.Enabled = false;
axMapControl1.ShowMapTips = false;
chkShowTips.CheckState = CheckState.Unchecked;
AddData();
}
6-40
Exercise 6B
6-41
//if there is no MapDocument, disable the Save menu and clear the statusbar
if (m_mapDocumentName == string.Empty)
{
menuSaveDoc.Enabled = false;
statusBarXY.Text = string.Empty;
}
else
{
//enable the Save menu and write the doc name to the statusbar
menuSaveDoc.Enabled = true;
statusBarXY.Text = Path.GetFileName(m_mapDocumentName);
}
6-42
Exercise 6B
axMapControl1.AddLayer(countriesLayer);
axMapControl1.AddLayer(lakesLayer);
if ((item == esriTOCControlItem.esriTOCControlItemLayer))
{
m_layer = layer as ILayer;
}
6-43
6-44
ILayer layer;
// Loop through the layers in the map
for (int i = 0; (i < (axMapControl1.LayerCount)); i++)
{
layer = axMapControl1.get_Layer(i);
if (layer is IFeatureLayer)
{
// Show MapTips based for selected layer,
// depending on status of CheckBox
if (layer == m_layer)
{
if (chkShowTips.CheckState == CheckState.Checked)
{
layer.ShowTips = true;
}
else
{
layer.ShowTips = false;
}
}
else
{
layer.ShowTips = false;
}
}
}
Exercise 6B
6-45
7
Rendering data
Exercise 7A
Exercise shortcut
1. In Visual Studio, open the DisplayingData.sln solution from the
\Student\IPAN\Exercise07\VisualBasic\DisplayingData folder.
2. Programmatically create a new simple fill symbol and set properties (e.g., style,
color). Apply the new symbol to a polygon layer with a simple renderer. Use the
same techniques to apply class breaks and unique value.
OR
7-1
Option 1: Complete steps 2 and 3 to work with symbology for vector data.
OR
Option 2: Complete step 4 (skip 2 and 3) to work with symbology for raster data.
After completing either option, you will save your symbology to a layer file in step 5.
7-2
Exercise 7A
You can use this technique to quickly jump to any procedure in your project.
Read through the code in the GetLayerByName function.
This code uses a unique identifier (UID) to return layers of a specified type. In this case,
the UID is associated with IGeoFeatureLayer.
Note: There are UIDs for all types of layers. For a description and listing of additional
UIDs, read about IMap::Layers in the developer help.
Now set the style to a solid fill for your symbol by completing the following code:
sym.__________
= esriSimpleFillStyle.________________________
7-3
Click OK.
In code view, navigate to the AddLayersToComboBox sub procedure and uncomment it.
7-4
Exercise 7A
Question 2: What types of layers are added to the cboLayer combo box?
______________________________________________________________________
Build and run your project.
From your application's Feature Layer drop-down list, choose States to render this
layer.
First, you will apply a simple renderer.
Below the Feature Layer drop-down list, choose the Simple option to apply a simple
renderer.
Notice that the R, G, and B drop-down lists are now enabled.
Choose values for R, G, and B, then click Render.
Your single color, simple renderer is applied to the States layer.
Close your application.
Now you will experiment with two other renderers for feature layers: unique value and
class breaks.
In code view, navigate to MainForm_Load.
Review the code where the three color combo boxes are enabled and populated.
Note that the values in the drop-down lists will range from 0 to 255.
Navigate to the following MainForm sub procedures and functions, and uncomment the
code in each:
ApplyUniqueValue
ApplyClassBreaks
GetColors
FillFieldsComboBox
7-5
Note: This course hasn't covered all of the objects in these renderers, so you might not
understand all of the code. For example, you may have noticed references to cursors and
fields. You will learn more about these objects in later lessons. For now, use the renderers
and observe how your layers display in the map.
Choose a different field and vary the number of breaks, then run your class breaks
renderer again.
To test the unique values renderer, choose the Unique Value option, then run it on a
field of your choice.
When you are finished, close your application.
Skip to step 5, where you will save your symbology to a layer file.
7-6
Exercise 7A
Because you will not be working with feature layers, comment the code in the
following sub procedures and then collapse them:
ApplySimple
AddLayersToComboBox
btnRender_Click
cboLayer_SelectedValueChanged
You will use the IRasterBandCollection interface to verify that this raster has at least
three bands. If it doesn't, you will exit the sub procedure.
Complete the following code to return the bands and check if there are at least three:
Dim bandCol As ________________________________________
bandCol = raster ' QI
If bandCol.__________ < 3 Then Exit Sub
Complete the following code to create a new raster RGB renderer and a raster
renderer:
Dim rgbRen As IRasterRGBRenderer = New __________________________________
Dim rasRen As ______________________________
7-7
Update the renderer to reflect the new properties and tie it to the layer:
rasRen.____________()
rLayer.________________ = CType(rgbRen, IRasterRenderer)
Refresh the MapControl's active view, then update your table of contents.
Build your project, then run it.
7-8
Exercise 7A
Verify that the band numbers now display as you coded them, with red as band 3
(RedBandIndex = 2).
Close your application.
In the next step, you will save your symbology to a layer file.
7-9
Create a message box to notify the user of the layer file's name and location on disk.
Run your project.
When your form displays, if you are using vector layers, symbolize one of the layers.
(If you are using raster layers, you do not need to symbolize the layer.)
Click the same layer in the table of contents to select it, then click your Save Layer
button.
Clicking the Save Layer button without first selecting a layer in the
table of contents may result in an error.
7-10
Exercise 7A
If you want to complete the optional steps, do so now. Otherwise, close Visual Studio.
7-11
Notice that the renderer displayed is that of the first layer in the data frame, COUNTY1.
This renderer shows the counties with a single symbol and no outline.
Turn off the COUNTY1 layer. (If necessary, zoom in or out so that you can see several
states at once, as shown below.)
Now the counties are displayed based on states names (in the STATE_NAME field)
using a unique values renderer and a pastel color ramp.
7-12
Exercise 7A
Now the counties are displayed based on county names (in the NAME field) using a
unique values renderer and a blue color ramp.
Turn on the COUNTY1 and COUNTY2 layers.
Right-click the COUNTY1 layer and choose Properties.
Click the General tab and select the Don't show layer when zoomed option.
In this dialog box, you can add a display scale range to each individual layer. As you
zoom in and out of your map display, you will notice that layers will either draw or not
draw based on their scale range.
For In beyond, type 50000000 (7 zeros) and click OK.
You are specifying that you do not want this layer to draw when the display scale is
within 1:50,000,000.
7-13
Use the zoom tools to zoom out past 50,000,000 and in less than 50,000,000 to see
what happens in the display.
Question 6: What happens in the display when you zoom?
______________________________________________________________________
______________________________________________________________________
Open the layer properties for COUNTY1, select the Show layer at all scales option,
and click OK.
You want to mimic this type of functionality all within one layer in ArcMap, as opposed
to multiple layers.
To save time, the code to create the new renderer has been written for you. You will run
the code and examine how it works. You will begin by setting your MapControl to open
the map document that you currently see in ArcMap.
Close ArcMap. Do not save changes.
In Visual Studio, open the Properties dialog box for your MapControl.
For Map Document, browse to \Student\IPAN\Exercise07 and open
Scale_Renderer.mxd.
Click OK.
In code view, navigate to the following sub procedures and uncomment the code:
AddLayersToComboBox
btnScale_Click
In the btnScale_Click sub procedure, explore the code that uses IGeoFeatureLayer.
Use the developer resource of your choice to search for IGeoFeatureLayer. (Tip:
Remember, you can use the Visual Studio Object Browser.)
Question 7: What is returned when you use the Renderer property?
______________________________________________________________________
7-14
Exercise 7A
It may take a little time for the new layer to display in the table of
contents.
7-15
Navigate to the Click event for your Stretch Raster button (btnStretch) and
uncomment the code.
Take a moment to explore the code.
This code gets into the active data frame, accesses the first layer, creates a new renderer,
defines two new colors, creates a color ramp, and then uses the color ramp in the
renderer.
If the code in the AddLayersToComboBox sub procedure is not already commented,
comment it now since it applies only to feature layers.
In Design view, open the Properties dialog box for your MapControl and do the
following:
The ramp now stretches between green and red, as specified in the code.
Close your application, then close Visual Studio.
Conclusion
In this exercise, you worked with renderers to create symbology for your layers. You then
saved the symbology a layer file. Remember, layer files give you the ability to add the
layer file to future maps, allowing you to take advantage of the symbology and other
layer properties stored in the file. If you completed the optional steps, you learned how to
7-16
Exercise 7A
apply a scale-dependent renderer to vector data and a stretch color ramp renderer to raster
data for more sophisticated data display.
7-17
7-18
Exercise 7A
System.IO
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Controls
ESRI.ArcGIS.ADF
ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.Geometry
Imports
Imports
Imports
Imports
ESRI.ArcGIS.CartoUI
ESRI.ArcGIS.DataSourcesRaster
ESRI.ArcGIS.Display
ESRI.ArcGIS.Geodatabase
7-19
7-20
Exercise 7A
'if there is no MapDocument, disable the Save menu and clear the statusbar
If m_mapDocumentName = String.Empty Then
menuSaveDoc.Enabled = False
statusBarXY.Text = String.Empty
Else
'enable the Save manu and write the doc name to the statusbar
menuSaveDoc.Enabled = True
statusBarXY.Text = System.IO.Path.GetFileName(m_mapDocumentName)
End If
End Sub
Private Sub axMapControl1_OnMouseMove(ByVal sender As Object, _
ByVal e As IMapControlEvents2_OnMouseMoveEvent) _
Handles axMapControl1.OnMouseMove
statusBarXY.Text = String.Format("{0}, {1} {2}", _
e.mapX.ToString("#######.##"), e.mapY.ToString("#######.##"), _
axMapControl1.MapUnits.ToString().Substring(4))
End Sub
Private Sub btnChangeRGBRenderer_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnChangeRGBRenderer.Click
''RGB Raster rendering
Dim map As IMap
map = AxMapControl1.ActiveView.FocusMap
Dim rLayer As IRasterLayer
rLayer = CType(map.Layer(0), IRasterLayer)
Dim raster As IRaster
raster = rLayer.Raster
Dim bandCol As IRasterBandCollection
bandCol = CType(raster, IRasterBandCollection)
If bandCol.Count < 3 Then Exit Sub
Dim rgbRen As IRasterRGBRenderer = New RasterRGBRenderer
Dim rasRen As IRasterRenderer
rasRen = CType(rgbRen, IRasterRenderer)
rasRen.Raster = raster
rasRen.Update()
rgbRen.RedBandIndex = 2
rgbRen.GreenBandIndex = 1
rgbRen.BlueBandIndex = 0
rasRen.Update()
rLayer.Renderer = CType(rgbRen, IRasterRenderer)
AxMapControl1.ActiveView.Refresh()
AxTOCControl1.Update()
End Sub
Private Sub AxTOCControl1_OnMouseDown(ByVal sender As Object, _
ByVal e As ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent) _
Handles AxTOCControl1.OnMouseDown
7-21
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
Dim
Dim
Dim
Dim
Dim
7-22
Exercise 7A
7-23
7-24
Exercise 7A
7-25
Case "Unique"
'call the ApplyUniqueValue
ApplyUniqueValue(geoLayer,
Case "Breaks"
'call the ApplyClassBreaks
ApplyClassBreaks(geoLayer,
Case Else
Exit Sub
End Select
End Sub
method
cboUniqueVals.Text)
method
cboNumericVals.Text, CLng(cboBreaks.Text))
7-26
Exercise 7A
7-27
7-28
Exercise 7A
7-29
rgbRen.RedBandIndex = 2
rgbRen.GreenBandIndex = 1
rgbRen.BlueBandIndex = 0
'Update renderer and refresh layer
rasRen.Update()
rLayer.Renderer = CType(rgbRen, IRasterRenderer)
AxMapControl1.ActiveView.Refresh()
AxTOCControl1.Update()
End Sub
Private Sub btnSaveLayer_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnSaveLayer.Click
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
7-30
Exercise 7A
End Sub
Private Sub optBreaks_Click1(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles optBreaks.Click
m_strOption = "Breaks"
Call OptionEnabler()
End Sub
Private Sub optSimple_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles optSimple.Click
m_strOption = "Simple"
Call OptionEnabler()
End Sub
Private Sub optUnique_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles optUnique.Click
m_strOption = "Unique"
Call OptionEnabler()
End Sub
Private Sub btnStretch_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnStretch.Click
Dim map As IMap
map = AxMapControl1.ActiveView.FocusMap
'Get raster input from layer
Dim rLayer As IRasterLayer
rLayer = CType(map.Layer(0), IRasterLayer)
Dim raster As IRaster
raster = rLayer.Raster
'Create renderer and QI for RasterRenderer
Dim stretchRen As IRasterStretchColorRampRenderer
stretchRen = New RasterStretchColorRampRenderer
Dim rasRen As IRasterRenderer
rasRen = CType(stretchRen, IRasterRenderer)
'Set raster for the renderer and update
rasRen.Raster = raster
rasRen.Update()
'Define two colors
Dim fromColor As IColor
Dim toColor As IColor
fromColor = New RgbColor
fromColor.RGB = RGB(255, 0, 0)
toColor = New RgbColor
toColor.RGB = RGB(0, 255, 0)
'Create color ramp
Dim ramp As IAlgorithmicColorRamp
ramp = New AlgorithmicColorRamp
ramp.Size = 255
ramp.FromColor = fromColor
ramp.ToColor = toColor
ramp.CreateRamp(True)
7-31
7-32
Exercise 7A
7-33
Exercise 7B
Exercise shortcut
1. In Visual Studio, open the DisplayingData.sln solution from the
\Student\IPAN\Exercise07\CSharp\DisplayingData folder.
2. Programmatically create a new simple fill symbol and set properties (e.g., style,
color). Apply the new symbol to a polygon layer with a simple renderer. Use the
same techniques to apply class breaks and unique value.
OR
7-35
Option 1: Complete steps 2 and 3 to work with symbology for vector data.
OR
Option 2: Complete step 4 (skip 2 and 3) to work with symbology for raster data.
After completing either option, you will save your symbology to a layer file in step 5.
7-36
Exercise 7B
You can use this technique to quickly jump to any function or method in your project.
Read through the code in the GetLayerByName function.
This code uses a unique identifier (UID) to return layers of a specified type. In this case,
the UID is associated with IGeoFeatureLayer.
Note: There are UIDs for all types of layers. For a description and listing of additional
UIDs, read about IMap::Layers in the developer help.
Now set the style to a solid fill for your symbol by completing the following code:
sym.__________
= esriSimpleFillStyle.________________________;
7-37
7-38
Exercise 7B
Click OK.
7-39
Navigate to the following MainForm methods and functions, and uncomment the code
in each:
ApplyUniqueValue
ApplyClassBreaks
GetColors
FillFieldsComboBox
Choose a different field and vary the number of breaks, then run your class breaks
renderer again.
To test the unique values renderer, choose the Unique Value option, then run it on a
field of your choice.
When you are finished, close your application.
Skip to step 5, where you will save your symbology to a layer file.
7-40
Exercise 7B
Because you will not be working with feature layers, comment the code in the
AddLayersToComboBox method and then collapse it.
Open the Desktop Help for .NET (VS2008), if necessary.
Search for IRasterLayer and review its properties.
You will use this interface to access properties such as Raster and Renderer. Before you
can do so, you will need to return a reference to a map, or data frame.
Navigate to the btnChangeRGBRenderer_Click method.
Complete the following code to access the map (data frame) and the first raster layer in
the active map:
IMap map;
map = axMapControl1.ActiveView.________________;
_______________________ rLayer;
rLayer = map.get_Layer(__) as IRasterLayer;
You will use the IRasterBandCollection interface to verify that this raster has at least
three bands. If it doesn't, you will exit the click event.
7-41
Complete the following code to return the bands and check whether there are at least
three:
__________________________________________ bandCol;
bandCol = raster as IRasterBandCollection; //Cast
if (bandCol.Count < 3)
{
return;
}
Complete the following code to create a new raster RGB renderer and a raster
renderer:
IRasterRGBRenderer rgbRen = new ________________________________();
______________________________ rasRen;
Update the renderer to reflect the new properties and tie it to the layer:
7-42
Exercise 7B
rasRen.____________();
rLayer.________________ = rgbRen as IRasterRenderer;
Refresh the MapControl's active view, then update your table of contents.
Build your project, then run it.
Click the Change RGB Raster button.
Verify that the band numbers now display as you coded them, with red as band 3
(RedBandIndex = 2).
Close your application.
In the next step, you will save your symbology to a layer file.
7-43
You want to code this button so that when it is clicked, the layer that is selected in the
table of contents is saved to a layer file. You will begin by inserting code to
programmatically open the Visual Studio SaveFileDialog control.
Insert the snippet IPAN_Ex07_SaveLyrFile.
Read through the code.
The code uses the layer name selected by the user at run time as the output file name. The
.lyr extension is added to the file so that ArcGIS can recognize it as a layer file.
Now that you know the output name, you will create the new layer file object.
After the line of code that assigns a value to the path variable, use the LayerFile
class to create a new instance of a layer file with the layerFile variable.
Create the new layer file by calling ILayerFile::New, passing the file name selected
in the dialog box as the argument.
At the bottom of the method, after the code that assigns the variable, complete the
following code to load m_layer into the layer file:
layerFile.ReplaceContents(______________);
Create a message box to notify the user of the layer file's name and location on disk.
Run your project.
When your form displays, if you are using vector layers, symbolize one of the layers.
(If you are using raster layers, you do not need to symbolize the layer.)
Click the same layer in the table of contents to select it, then click your Save Layer
button.
Clicking the Save Layer button without first selecting a layer in the
table of contents may result in an error.
7-44
Exercise 7B
If you want to complete the optional steps, do so now. Otherwise, close Visual Studio.
7-45
Notice that the renderer displayed is that of the first layer in the data frame, COUNTY1.
This renderer shows the counties with a single symbol and no outline.
Turn off the COUNTY1 layer. (If necessary, zoom in or out so that you can see several
states at once, as shown below.)
Now the counties are displayed based on states names (in the STATE_NAME field)
using a unique values renderer and a pastel color ramp.
7-46
Exercise 7B
Now the counties are displayed based on county names (in the NAME field) using a
unique values renderer and a blue color ramp.
Turn on the COUNTY1 and COUNTY2 layers.
Right-click the COUNTY1 layer and choose Properties.
Click the General tab and select the Don't show layer when zoomed option.
In this dialog box, you can add a display scale range to each individual layer. As you
zoom in and out of your map display, you will notice that layers will either draw or not
draw based on their scale range.
For In beyond, type 50000000 (7 zeros) and click OK.
You are specifying that you do not want this layer to draw when the display scale is
within 1:50,000,000.
7-47
Use the zoom tools to zoom out past 50,000,000 and in less than 50,000,000 to see
what happens in the display.
Question 6: What happens in the display when you zoom?
______________________________________________________________________
______________________________________________________________________
Open the layer properties for COUNTY1, select the Show layer at all scales option,
and click OK.
You want to mimic this type of functionality all within one layer in ArcMap, as opposed
to multiple layers.
To save time, the code to create the new renderer has been written for you. You will run
the code and examine how it works. You will begin by setting your MapControl to open
the map document that you currently see in ArcMap.
Close ArcMap. Do not save changes.
In Visual Studio, open the property pages for your MapControl.
For Map Document, browse to \Student\IPAN\Exercise07 and open
Scale_Renderer.mxd.
Click OK.
Navigate to the following methods and uncomment them:
AddLayersToComboBox
btnScale_Click
7-48
Exercise 7B
It may take a little time for the new layer to display in the table of
contents.
7-49
Navigate to the Click event for your Stretch Raster button (btnStretch) and
uncomment the code.
Take a moment to explore the code.
This code gets into the active data frame, accesses the first layer, creates a new renderer,
defines two new colors, creates a color ramp, and then uses the color ramp in the
renderer.
If the code in the AddLayersToComboBox method is not already commented, comment
it now since it applies only to feature layers.
In Design view, open the Properties dialog box for your MapControl and do the
following:
The ramp now stretches between green and red, as specified in the code.
Close your application, then close Visual Studio.
Conclusion
In this exercise, you worked with renderers to create symbology for your layers. You then
saved the symbology a layer file. Remember, layer files give you the ability to add the
layer file to future maps, allowing you to take advantage of the symbology and other
layer properties stored in the file. If you completed the optional steps, you learned how to
7-50
Exercise 7B
apply a scale-dependent renderer to vector data and a stretch color ramp renderer to raster
data for more sophisticated data display.
7-51
7-52
Exercise 7B
System;
System.Drawing;
System.Collections;
System.ComponentModel;
System.Windows.Forms;
System.Data;
System.IO;
System.Runtime.InteropServices;
using Microsoft.VisualBasic;
using
using
using
using
using
ESRI.ArcGIS.esriSystem;
ESRI.ArcGIS.Carto;
ESRI.ArcGIS.Controls;
ESRI.ArcGIS.ADF;
ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Display;
using
using
using
using
ESRI.ArcGIS.CartoUI;
ESRI.ArcGIS.DataSourcesRaster;
ESRI.ArcGIS.Geometry;
ESRI.ArcGIS.Geodatabase;
namespace DisplayingData
{
public sealed partial class MainForm : Form
{
#region class private members
private IMapControl3 m_mapControl = null;
private string m_mapDocumentName = string.Empty;
private string m_strOption = string.Empty;
private ILayer m_layer = null;
#endregion
#region class constructor
public MainForm()
{
InitializeComponent();
}
#endregion
private void MainForm_Load(object sender, EventArgs e)
{
//get the MapControl
m_mapControl = (IMapControl3)axMapControl1.Object;
//disable the Save menu (since there is no document yet)
AddLayersToComboBox();
7-53
7-54
Exercise 7B
//if there is no MapDocument, disable the Save menu and clear the statusbar
if (m_mapDocumentName == string.Empty)
{
menuSaveDoc.Enabled = false;
statusBarXY.Text = string.Empty;
}
else
{
//enable the Save menu and write the doc name to the statusbar
menuSaveDoc.Enabled = true;
statusBarXY.Text = System.IO.Path.GetFileName(m_mapDocumentName);
}
7-55
7-56
Exercise 7B
7-57
IAlgorithmicColorRamp ramp;
ramp = new AlgorithmicColorRamp();
ramp.Algorithm = esriColorRampAlgorithm.esriHSVAlgorithm;
ramp.FromColor = startColor;
ramp.ToColor = endColor;
ramp.Size = Convert.ToInt32(Colors);
bool blnIsRampOK;
ramp.CreateRamp(out blnIsRampOK);
if (!blnIsRampOK)
{
return null;
}
else
{
return ramp.Colors;
}
7-58
Exercise 7B
// user-written code
ISimpleFillSymbol sym;
sym = new SimpleFillSymbol();
sym.Style = esriSimpleFillStyle.esriSFSSolid;
IRgbColor color = new RgbColor();
color.Red = Convert.ToInt32(cboRed.Text);
color.Green = Convert.ToInt32(cboGreen.Text);
color.Blue = Convert.ToInt32(cboBlue.Text);
sym.Color = color;
// pass the layer and symbol to the ApplySimple method
ApplySimple(geoLayer, sym as ISymbol);
break;
// end user-written code
case "Unique":
ApplyUniqueValue(geoLayer, cboUniqueVals.Text);
break;
case "Breaks":
ApplyClassBreaks(geoLayer, cboNumericVals.Text,
long.Parse(cboBreaks.Text));
break;
default:
//return;
break;
7-59
7-60
Exercise 7B
//IEnumLayer allFLayers;
//allFLayers = map.get_Layers(uidLayer, true);
//IFeatureLayer fLayer;
//fLayer = allFLayers.Next() as IFeatureLayer;
//while (fLayer != null)
//{
//
if ((fLayer.FeatureClass.ShapeType ==
esriGeometryType.esriGeometryPolygon))
//
{
//
cboLayer.Items.Add(fLayer.Name);
//
}
//
else if ((fLayer.FeatureClass.ShapeType ==
esriGeometryType.esriGeometryPolyline))
//
{
//
cboLayer.Items.Add(fLayer.Name);
//
}
//
else if ((fLayer.FeatureClass.ShapeType ==
esriGeometryType.esriGeometryPoint))
//
{
//
cboLayer.Items.Add(fLayer.Name);
//
}
//
fLayer = allFLayers.Next() as IFeatureLayer;
//}
7-61
}
private void FillFieldsComboBox(IFeatureLayer geoLayer)
{
IFeatureClass fClass;
fClass = geoLayer.FeatureClass;
IFields fields;
fields = fClass.Fields;
cboNumericVals.Items.Clear();
cboUniqueVals.Items.Clear();
IField fld;
7-62
Exercise 7B
for (int i = 0; (i
< (fields.FieldCount - 1)); i++)
{
fld = fields.get_Field(i);
//int fldType;
//fldType = Convert.ToInt32(fld.Type);
if (Convert.ToInt32(fld.Type) <= 3) //if ((fld.Type <= 3))
{
cboNumericVals.Items.Add(fld.Name);
}
// numeric
if (Convert.ToInt32(fld.Type) <= 5) //if ((fld.Type <= 5))
{
cboUniqueVals.Items.Add(fld.Name);
}
// not shape, OID, or BLOBshape, OID, or BLOB
7-63
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
7-64
Exercise 7B
7-65
7-66
Exercise 7B
IFeatureLayer newFLayer;
newFLayer = new FeatureLayer();
newFLayer.Name = "USA";
IFeatureClass featureClass;
featureClass = fLayer1.FeatureClass;
newFLayer.FeatureClass = featureClass;
IGeoFeatureLayer geoFLayer0;
IGeoFeatureLayer geoFLayer1;
IGeoFeatureLayer geoFLayer2;
IGeoFeatureLayer newGeoFLayer;
geoFLayer0 = ((IGeoFeatureLayer)(fLayer0));
geoFLayer1 = ((IGeoFeatureLayer)(fLayer1));
geoFLayer2 = ((IGeoFeatureLayer)(fLayer2));
newGeoFLayer = ((IGeoFeatureLayer)(newFLayer));
IScaleDependentRenderer scaleDependentRenderer;
scaleDependentRenderer = new ScaleDependentRenderer();
IFeatureRenderer renderer0;
IFeatureRenderer renderer1;
IFeatureRenderer renderer2;
renderer0 = geoFLayer0.Renderer;
renderer1 = geoFLayer1.Renderer;
renderer2 = geoFLayer2.Renderer;
// Build the new scale dependent renderer from the existing renderers.
scaleDependentRenderer.AddRenderer(renderer0);
scaleDependentRenderer.AddRenderer(renderer1);
scaleDependentRenderer.AddRenderer(renderer2);
// Set the scale thresholds for the renderers
// within the scale dependent renderer.
scaleDependentRenderer.Break(0) = 10000000
scaleDependentRenderer.Break(1) = 50000000
scaleDependentRenderer.Break(2) = 500000000
7-67
7-68
8
Querying and
selecting data
Exercise 8A: Queries and selections
(VB.NET)
Estimated time: 45 minutes
Challenge: Open a feature class from a
feature workspace
Estimated time: 10 minutes
Exercise 8B: Queries and selections (C#)
Estimated time: 45 minutes
Challenge: Open a feature class from a
feature workspace
Estimated time: 10 minutes
Exercise 8A
Exercise shortcut
1. In Visual Studio, open the QueryFilters.sln solution from your
\Student\IPAN\Exercise08\VisualBasic\QueryFilters folder.
2. Apply a query filter to highlight landlocked countries in the Country feature class
of QueryFilters.mxd.
3. Use a query filter and a spatial filter to select cities with a population greater than
2 million that fall within the country that the user has selected in the table of
contents.
** (Optional) Display a query filter as a selection to report the number of selected
cities.
** (Challenge) Open a feature class from a feature workspace.
8-1
When the map document opens, notice that the Country layer is the third layer in the
table of contents.
Right-click the Country layer and choose Open Attribute Table.
In the attribute table, scroll to the right to the LANDLOCKED field.
Question 1: What two values does this field contain?
______________________________________________________________________
You will use this information to return the number of landlocked countries in the feature
class.
Close the attribute table and ArcMap.
Start Visual Studio.
From the File menu, choose Open Project.
Browse to the \Student\IPAN\Exercise08\VisualBasic\QueryFilters folder and open the
QueryFilters solution.
In the ArcGIS Engine MapControl Application that opens, view MainForm in Design
view.
Notice that the form contains a MapControl, ToolbarControl, TOCControl, and three
Visual Studio buttons.
Double-click the Landlocked button (btnLandLocked) for its Click event.
This is where you will write code to find landlocked countries. You will be working with
feature layers and their corresponding feature classes, so you need to reference the
appropriate interfaces.
Within the event, declare the variable fLayer as an IFeatureLayer object.
Complete the following code to set fLayer equal to the Country layer, the third layer
in your active data frame (FocusMap). (Hint: The third layer is index #2.)
fLayer = axMapControl1.____________.FocusMap._______(2)
In order to access the underlying table for a feature, you will need a FeatureClass
object.
8-2
Exercise 8A
You discovered earlier that the LANDLOCKED attribute has two values (Y and N).
Landlocked countries (without a coastline) have a values of Y, while countries that are
not landlocked (with a coastline) have a value of N.
Complete the following code to search the Country feature class for all records with a
value of Y for the LANDLOCKED attribute:
fCursor = fClass.____________(qFilter, ________)
The records matching this criterion will be stored in fCursor. In other words, the feature
cursor (fCursor) will store a subset of landlocked country features.
Question 3: How did you set memory recycling?
______________________________________________________________________
Next, you need to write a looping structure to access each of the records in the cursor and
to calculate basic statistics.
Declare the following variables to reference an individual feature in the cursor, the
population value, the area, and the number of countries, respectively:
8-3
Next, you want to loop until all the records have been pulled from the cursor.
Begin a Do Until loop by completing the following code:
Do Until feat Is _________________
Inside the loop, write the following code to sum the area of all the countries in the
cursor:
dblarea = dblarea + dblarea + feat.Value(10)
Note: You will learn more about accessing fields in a later lesson.
End the loop with the following code to return the next feature from the cursor:
feat = fCursor.______________________
If you do not include this line of code inside the Do Until loop, your
code will loop endlessly.
After the loop, display information about the total number and average area of the
landlocked countries in a message box, for example:
MessageBox.Show("Number of landlocked countries: " _
& lngCountries & vbCrLf & _
"Average area: " & Math.Round(dblarea / lngCountries, 0))
Note: Remember, Math is a class in the System namespace.
8-4
Exercise 8A
Complete the following code to set the required object variables (Hint: Country is the
third layer):
8-5
cntryLyr = axMapControl1.ActiveView.__________________.Layer(2)
cntrySel = cntryLyr.SelectionSet
Because cntryLyr was declared with the IFeatureSelection interface, you can access
selected features by using the SelectionSet property.
Next, you will transfer the selection set (cntrySel) to a feature cursor (cntryCursor) so
you can easily retrieve the selected country.
Note: The syntax for the Search method works slightly differently on the
ISelectionSet interface. Instead of storing the returned cursor using an assignment
statement, such as myCursor = myTable.Search, the cursor variable is passed in
as one of the required parameters.
Complete the following code to search your selection set and populate your feature
cursor (Tip: Use Nothing as a query filter parameter to return all features):
cntrySel.____________(______________, True, ______________________)
Complete the following code to declare the variable country so that it can contain the
selected feature (or the first feature, if more than one is selected):
Dim country As ________________
Complete the following code to make sure a country was selected. If no country was
selected, report an error to the user, then stop execution of the procedure.
If country Is ___________ Then
MessageBox.Show("Please select a country")
_______ Sub
End If
Now that you have referenced the selected country, you will create a new spatial filter by
passing the feature's shape to the Geometry property of your cursor. You will declare two
variables to work with the same SpatialFilter object:
8-6
Exercise 8A
Complete the following code to set all of the filter's selection criteria using the two
variables that point to it:
Note: Because you want to locate cities inside the selected country, the spatial
relationship will be contains.
______________.WhereClause = "Population > 2000000"
______________.Geometry = country.Shape
spatFilt.______________ = esriSpatialRelEnum._______________________________________
Now that you have produced the filter and defined the spatial and attribute criteria, you
will apply the filter to the Cities feature class.
Declare the following variables:
Dim cityLyr As IFeatureLayer
Dim cityFClass As IFeatureClass
Next, you will display a message box to report the number of cities that meet the search
criteria.
Declare the variable intCities as an Integer.
Complete the following code to return the number of features in your cityFClass
feature class.
intCities = cityFClass.________________________(________________)
8-7
If you want to complete one or both of these, do so now. Otherwise, close Visual
Studio.
8-8
Exercise 8A
You will use the SelectionColor property to set the color of the selection, and the
SelectFeatures method to select features on the map that satisfy a query filter.
Query filter
Selection method, as an enumeration
Boolean
8-9
A list of enumeration methods displays. These are the methods used for the second
argument of SelectFeatures. They are similar to the ArcMap interactive selection
methods that you can access from the Selection menu, as shown in the following graphic:
The third and final argument of the SelectFeatures method, justOne, is a Boolean:
A value of True will select the first feature in the cursor that meets the query filter
criteria.
A value of False will select all features that meet the criteria.
8-10
Exercise 8A
Question 7: Which variable holds the map's selected layer? (Hint: The variable is
populated in the OnMouseDown event of your TOCControl.)
______________________________________________________________________
Set your new variable to your map's selected layer.
This will allow you to make a selection within the selected layer in the map. Next, you
will create a query filter as you did earlier.
Create a new instance of a QueryFilter object and store it in the variable qFilt.
Complete the following code to set its WhereClause property (Hint: Be sure to type
seven zeroes):
qFilt.______________________ = "Population > 10000000"
Make sure there are no selected features by clearing the feature selection:
featSel.Clear()
Complete the following code to call the SelectFeatures method on featSel while
supplying the query filter, creating a new selection, and allowing more than one feature
to be selected:
featSel.______________________________(qFilt, _
esriSelectionResultEnum.__________________________________________, __________)
8-11
Notice that the default selection color is cyan. You can change it through code using the
SelectionColor property on IFeatureSelection.
The return type for this property is IColor. The color you create must support this
interface.
Close your application.
In the ESRI Object Browser, search for RgbColor by coclass name.
Double-click the result and view its members.
Notice that RgbColor supports the IColor interface. You will create a new RgbColor
object and use it to change the selection color to green.
In Visual Studio, find the code for the message box in the btnSelectCities_Click
method.
Under this line of code, create a new RgbColor object and store it in the variable grn.
The IRgbColor interface allows you to set red, green, and blue values for your color.
Because you are creating a green color, you will only set the Green property.
Set the Green property on grn to 255.
Complete the following code to assign the new color as the selection color:
featSel.___________________________ = grn
8-12
Exercise 8A
Test your changes. (Hint: Open QueryFilters.mxd, click the Cities layer, and click the
Select Cities button.)
Verify that the cities selected by your query filter now display in green.
Zoom to some of the selected cities and Identify
them.
When you are finished, close the Identify window and your application.
If you want to complete the Challenge, do so now. Otherwise, close Visual Studio.
Conclusion
In this exercise, you worked with objects for creating selections and working with feature
cursors. These objects are used for data analysis and display.
8-13
8-14
Exercise 8A
System.IO
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Controls
ESRI.ArcGIS.ADF
ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.Display
Public Class MainForm
Private m_mapControl As IMapControl3 = Nothing
Private m_mapDocumentName As String = String.Empty
Private m_layer As ILayer
Private Sub MainForm_Load(ByVal sender As System.Object, _
ByVal e As EventArgs) Handles MyBase.Load
'get the MapControl
m_mapControl = CType(axMapControl1.Object, IMapControl3)
'disable the Save menu (since there is no document yet)
menuSaveDoc.Enabled = False
End Sub
#Region "Main Menu event handlers"
Private Sub menuNewDoc_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles menuNewDoc.Click
'execute New Document command
Dim command As ICommand = New CreateNewDocument()
command.OnCreate(m_mapControl.Object)
command.OnClick()
End Sub
Private Sub menuOpenDoc_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles menuOpenDoc.Click
'execute Open Document command
Dim command As ICommand = New ControlsOpenDocCommandClass()
command.OnCreate(m_mapControl.Object)
command.OnClick()
End Sub
Private Sub menuSaveDoc_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles menuSaveDoc.Click
'execute Save Document command
If m_mapControl.CheckMxFile(m_mapDocumentName) Then
'create a new instance of a MapDocument
Dim mapDoc As IMapDocument = New MapDocumentClass()
mapDoc.Open(m_mapDocumentName, String.Empty)
8-15
8-16
Exercise 8A
8-17
8-18
Exercise 8A
featSel.Clear()
featSel.SelectFeatures(qFilt, _
esriSelectionResultEnum.esriSelectionResultNew, False)
MessageBox.Show(featSel.SelectionSet.Count & " features selected")
Dim grn As IRgbColor
grn = New RgbColor
grn.Green = 255
featSel.SelectionColor = grn
axMapControl1.ActiveView.Refresh()
End Sub
End Class
8-19
8-20
Exercise 8B
Exercise shortcut
1. In Visual Studio, open the QueryFilters.sln solution from your
\Student\IPAN\Exercise08\CSharp\QueryFilters folder.
2. Apply a query filter to highlight landlocked countries in the Country feature class
of QueryFilters.mxd.
3. Use a query filter and a spatial filter to select cities with a population greater than
2 million that fall within the country that the user has selected in the table of
contents.
** (Optional) Display a query filter as a selection to report the number of selected
cities.
** (Challenge) Open a feature class from a feature workspace.
8-21
When the map document opens, notice that the Country layer is the third layer in the
table of contents.
Right-click the Country layer and choose Open Attribute Table.
In the attribute table, scroll to the right to the LANDLOCKED field.
Question 1: What two values does this field contain?
______________________________________________________________________
You will use this information to return the number of landlocked countries in the feature
class.
Close the attribute table and ArcMap.
Start Visual Studio.
From the File menu, choose Open Project.
Browse to the \Student\IPAN\Exercise08\CSharp\QueryFilters folder and open the
QueryFilters solution.
In the ArcGIS Engine MapControl Application that opens, view MainForm in Design
view.
Notice that the form contains a MapControl, ToolbarControl, TOCControl, and three
Visual Studio buttons.
Double-click the Landlocked button (btnLandLocked) for its Click event.
This is where you will write code to find landlocked countries. You will be working with
feature layers and their corresponding feature classes, so you need to reference the
appropriate interfaces.
Within the event, declare the variable fLayer as an IFeatureLayer object.
Complete the following code to set fLayer equal to the Country layer, the third layer
in your map (get_Layer). (Hint: The third layer is index #2.)
fLayer = axMapControl1.__________________(__) as IFeatureLayer;
In order to access the underlying table for a feature, you will need a FeatureClass
object.
8-22
Exercise 8B
You discovered earlier that the LANDLOCKED attribute has two values (Y and N).
Landlocked countries (without a coastline) have a values of Y, while countries that are
not landlocked (with a coastline) have a value of N.
Complete the following code to search the Country feature class for all records with a
value of Y for the LANDLOCKED attribute:
fCursor = fClass.____________(qFilter, ________);
The records matching this criterion will be stored in fCursor. In other words, the feature
cursor (fCursor) will store a subset of landlocked country features.
Question 3: How did you set memory recycling?
______________________________________________________________________
Next, you need to write a looping structure to access each of the records in the cursor and
to calculate basic statistics.
Declare and initialize the following variables for the area and the number of countries:
8-23
double dblArea = 0;
long lngCountries = 0;
Next, you want to loop until all the records have been pulled from the cursor.
Begin a while loop by completing the following code:
while (feat != ________)
Inside the loop. write the following code to sum the area of all the countries in the
cursor:
dblArea += Convert.ToDouble(feat.get_Value(10)); //Area in square km is the 11th field
Note: You will learn more about accessing fields in a later lesson.
End the loop with the following code by returning the next feature from the cursor:
feat = fCursor.NextFeature();
If you do not include this line of code inside the loop, your code will
loop endlessly.
After the loop, display information about the total number and average area of the
landlocked countries in a message box.
Build and run your project.
Click the Open button
QueryFilters.mxd.
8-24
Exercise 8B
Complete the following code to return the layer (Hint: Country is the third layer):
cntryLyr = axMapControl1.get_Layer(2) as __________________________________;
8-25
Next, you will transfer the selection set (cntrySel) to a feature cursor (cntryCursor) so
you can easily retrieve the selected country.
Note: The syntax for the Search method works slightly differently on the
ISelectionSet interface. Instead of storing the returned cursor using an assignment
statement, such as myCursor = myTable.Search;, the cursor variable is passed in
as one of the required parameters.
Complete the following code to search your selection set and populate your feature
cursor: (Tip: Use null as the query filter parameter to return all features):
cntrySel.____________(________, true, out _______________________);
The Search method on ISelectionSet returns an ICursor object. Since you want to
work with features, you will need to cast from ICursor to IFeatureCursor.
Declare the variable featCursor as IFeatureCursor.
Complete the following code to cast from ICursor:
featCursor = cntryCursor as _____________________________;
Now you are ready to begin working with the individual features in your feature cursor.
Complete the following code to declare the country so that it can contain the selected
feature (or the first feature, if there was more than one selected):
IFeature country;
Complete the following code to make sure a country was selected. If no country was
selected, report an error to the user, then stop execution of the method.
if (country == null)
{
MessageBox.Show("Please select a country");
return;
}
8-26
Exercise 8B
Now that you have referenced the selected country, you will create a new spatial filter by
passing the feature's shape to the Geometry property of your cursor. You will declare two
variables to work with the same SpatialFilter object:
Complete the following code to set all of the filter's selection criteria using the two
variables that point to it:
Note: Because you want to locate cities inside the selected country, the spatial
relationship will be contains.
______________.WhereClause = "Population > 2000000";
______________.Geometry = country.Shape;
spatFilt.______________ =
esriSpatialRelEnum.____________________________________________;
Now that you have produced the filter and defined the spatial and attribute criteria, you
will apply the filter to the Cities feature class.
Declare the following variables:
IFeatureLayer cityLyr;
IFeatureClass cityFClass;
8-27
IFeatureCursor cityCursor;
Complete the following code to apply the spatial filter to the Cities feature class using
the Search method and store the returned feature cursor in cityCursor:
cityCursor = cityFClass.Search(___________, _______);
Complete the following code to return the number of cities selected by your spatial
filter:
long lngCities = 0;
lngCities = cityFClass.FeatureCount(____________________);
Display a message box to report the number of cities that meet the search criteria and
their total population.
Build and run your project.
Open QueryFilters.mxd and turn on the Country layer, if necessary.
Zoom to South America.
Select Brazil with the Select Features tool
8-28
Exercise 8B
Question 7: How many cities in Brazil have a population greater than 2 million?
______________________________________________________________________
Close the message box, then close your application.
You have finished this exercise; however, you may wish to complete the optional step
and the Challenge:
If you want to complete one or both of these, do so now. Otherwise, close Visual
Studio.
8-29
You will use the SelectionColor property to set the color of the selection, and the
SelectFeatures method to select features on the map that satisfy a query filter.
Query filter
Selection method, as an enumeration
Boolean
A list of enumeration methods displays. These are the methods used for the second
argument of SelectFeatures. They are similar to the ArcMap interactive selection
methods that you can access from the Selection menu, as shown in the following graphic:
The third and final argument of the SelectFeatures method, justOne, is a Boolean:
8-30
A value of true will select the first feature in the cursor that meets the query filter
criteria.
A value of false will select all features that meet the criteria.
Exercise 8B
Question 8: Which variable holds the map's selected layer? (Hint: The variable is
populated in the OnMouseDown event of your TOCControl.)
______________________________________________________________________
Set your new variable to your map's selected layer.
This will allow you to make a selection within the selected layer in the map. Next, you
will create a query filter as you did earlier.
Create a new instance of a QueryFilter object and store it in the variable qFilt.
Complete the following code to set its WhereClause property (Hint: Be sure to type
seven zeroes):
qFilt.______________________ = "Population > 10000000";
Make sure there are no selected features by clearing the feature selection:
featSel.Clear();
Note: You can also call the Clear method conditionally when featSel is not null.
Complete the following code to call the SelectFeatures method on featSel while
supplying the query filter, creating a new selection, and allowing more than one feature
to be selected:
featSel.______________________________(qFilt,
esriSelectionResultEnum.__________________________________________, __________);
8-31
The return type for this property is IColor. The color you create must support this
interface.
Close your application.
In the ESRI Object Browser, search for RgbColor by coclass name.
Double-click the result and view its members.
Notice that RgbColor supports the IColor interface. You will create a new RgbColor
object and use it to change the selection color to green.
8-32
Exercise 8B
In Visual Studio, find the code for the message box in the btnSelectCities method.
Under this line of code, create a new RgbColor object and store it in the variable grn.
The IRgbColor interface allows you to set red, green, and blue values for your color.
Because you are creating a green color, you will only set the Green property.
Set the Green property on grn to 255.
Complete the following code to assign the new color as the selection color:
featSel.___________________________ = grn;
Save your project, then run it and test your changes. (Hint: Open QueryFilters.mxd,
click the Cities layer, and click the Select Cities button.)
Verify that the cities selected by your query filter now display in green.
Zoom to some of the selected cities and Identify
them.
When you are finished, close the Identify window and your application.
If you want to complete the Challenge, do so now. Otherwise, close Visual Studio.
Conclusion
In this exercise, you worked with objects for creating selections and working with feature
cursors. These objects are used for data analysis and display.
8-33
8-34
Exercise 8B
System;
System.Drawing;
System.Collections;
System.ComponentModel;
System.Windows.Forms;
System.Data;
System.IO;
System.Runtime.InteropServices;
using
using
using
using
using
ESRI.ArcGIS.esriSystem;
ESRI.ArcGIS.Carto;
ESRI.ArcGIS.Controls;
ESRI.ArcGIS.ADF;
ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Display;
namespace QueryFilters
{
public sealed partial class MainForm : Form
{
#region class private members
private IMapControl3 m_mapControl = null;
private string m_mapDocumentName = string.Empty;
#endregion
#region class constructor
public MainForm()
{
InitializeComponent();
}
#endregion
private void MainForm_Load(object sender, EventArgs e)
{
//get the MapControl
m_mapControl = (IMapControl3)axMapControl1.Object;
8-35
8-36
Exercise 8B
//if there is no MapDocument, disable the Save menu and clear the statusbar
if (m_mapDocumentName == string.Empty)
{
menuSaveDoc.Enabled = false;
statusBarXY.Text = string.Empty;
}
else
{
//enable the Save menu and write the doc name to the statusbar
menuSaveDoc.Enabled = true;
statusBarXY.Text = Path.GetFileName(m_mapDocumentName);
}
8-37
8-38
Exercise 8B
axTOCControl1.HitTest(
e.x, e.y, ref item, ref map, ref layer, ref other, ref index);
if ((item == esriTOCControlItem.esriTOCControlItemLayer))
{
m_layer = layer;
}
}
}
8-39
8-40
9
Working with
geometry
Exercise 9A: Create a parcel proximity
tool (VB.NET)
Estimated time: 45 minutes
Challenge: Draw the polygon buffer
Estimated time: 10 minutes
Challenge: Use DisplayTransformation
Estimated time: 2 minutes
Exercise 9B: Create a parcel proximity
tool (C#)
Estimated time: 45 minutes
Challenge: Draw the polygon buffer
Estimated time: 10 minutes
Challenge: Use DisplayTransformation
Estimated time: 2 minutes
Exercise 9A
Create a buffer based on the location clicked in the map and select nearby features
Work with spatial filters, feature cursors, and spatial reference objects
Exercise shortcut
1. Create a new Visual Basic ArcGIS Engine MapControl Application.
2. Add the Select Features command to your ToolbarControl.
3. Create a point to represent a new gas station based on a location the user clicks.
4. Create a spatial filter to select the parcel intersecting the new point in
\Student\IPAN\Exercise09\ParcelProximity.mxd.
5. Using your spatial filter, create a cursor that contains the parcel on which the new
gas station will be located. Fetch a single feature from the cursor. Report the land
use of the parcel that was clicked in a text box.
6. Test your project to confirm that the land use displays in the text box.
7. Determine the buffer distance in the parcel layer's native map units.
8. Create a buffer around the polygon clicked with your new tool, then select the
parcels that are within the buffer distance.
9. If the gas station parcel is selected with the neighboring parcels, create a new
selection environment to remove it from the selection.
** (Challenge) Draw the polygon buffer on your map.
** (Challenge) Create the point object and Use DisplayTransformation.
9-1
Property
Value
Language
Visual Basic
Project type
Template
MapControl Application
Name
ParcelBuffer
Location
\Student\IPAN\Exercise09
Solution name
ParcelBuffer
Make sure the Create directory for solution check box is checked.
The code that you write will select features based on a location clicked by the user. To
make it easy to deselect features, you will use a built-in tool.
View the form in Design view.
You will to add a new item to the toolbar.
Open the Properties dialog box for your ToolbarControl.
From the Feature Selection category, add the Select Features tool just to the left of the
map scale.
Open the Properties dialog box for your MapControl.
For Map Document, assign ParcelProximity.mxd from your \Student\IPAN\Exercise09
folder.
Drag two TextBox controls and two Label controls onto your form and position each
text box with a label next to it. (Tip: Place these controls in the upper-right corner of
your map or in another location of your choice. Also, make the TextBox controls wider
to accommodate longer text.)
You will use one set of controls to display projection information and the other set to
display land use.
9-2
Exercise 9A
Control
(Name)
Text
Label
lblProj
Projection:
TextBox
txtProj
Label
lblLU
TextBox
txtLU
Land Use:
9-3
Now you are ready to begin writing the code that will select a parcel and buffer it. You
will start by accessing the active view.
Inside your If statement, complete the following code to instantiate the active view:
Dim activeView As _____________________ = axMapControl1.______________
Next, you will add code to the OnMouseDown event to capture the point where your user
clicks in the map display. Your code will eventually use this point to identify the
neighboring parcels.
To capture the point clicked by your user, you need a variable to hold a point object.
Because you are working with an event on the MapControl, there are two options for
instantiating a point object and assigning its x,y coordinates:
1. Populate x and y on your point object with coordinates already in map units
2. Populate x and y on your point object with coordinates that have been
transformed from display units
In this exercise, you will use the first option.
Instantiate a new instance of a point object in the variable aPoint.
Complete the following code to assign the x coordinate from one of the properties of e:
aPoint.X = e.________
9-4
Exercise 9A
9-5
You will now report the land use for the chosen parcel in the other text box.
Complete the following code to find the attribute Landuse and display its value:
txtLU.Text = feat.__________(fCursor.FindField("______________")).ToString()
9-6
Exercise 9A
When you right-click a parcel, its land use value (COMM, OFF, PI, VAC, etc.) displays
in one of your text boxes.
One by one, right-click two or three more parcels.
Text displays indicating that you clicked a parcel.
Right-click outside the parcels to test your code.
Text displays indicating that you did not click a parcel.
Close your application.
Because the feature class now has a projection, the name of the projection appears in the
text box.
Close the application.
9-7
When the user types a number, it will be converted to the native units of the data.
Next, you will get an interface for the Parcels geometry (polygon) that has the Buffer
method. Your goal is to create a buffer around the polygon you click with your new tool.
To do this, you will use ITopologicalOperator::Buffer.
In the Visual Studio Object Browser, search for ITopologicalOperator, then click its
Buffer method.
Notice that the Buffer method returns a reference to IGeometry and requires a distance
as Double.
Declare the following variables to work with the buffer:
Dim topoOp As ITopologicalOperator
Dim buffPoly As IPolygon
ITopologicalOperator
9-8
Exercise 9A
9-9
Notice that each time you click a parcel to place a new gas station and buffer it, the
parcels neighboring it are highlighted. However, the clicked parcel itself is also
highlighted. You will remove that parcel from the selection in the next step.
Close your application.
Modify the selection environment to subtract features from the current selection.
Subtract the gas station parcel.
Set the selection environment to the default and create a new selection.
Place your cursor in the empty space before the line of code that calls the
PartialRefresh method.
Complete the following code to assign the proper enumeration to the
CombinationMethod property of selEnv to subtract features from the selection:
____________.CombinationMethod = esriSelectionResultEnum._______________________
Next, you will call the SelectByShape method on the IMap interface to subtract the gas
station parcel from the selection set.
Write the following code to select only the gas station polygon:
axMapControl1.ActiveView.FocusMap.SelectByShape(aPoint, selEnv, ________)
9-10
Exercise 9A
Below the code you just wrote, complete the following the code to programmatically
restore a new selection:
selEnv.CombinationMethod = esriSelectionResultEnum._____________________________
Now the selection method will remove the parcel you clicked from the selection, then
restore the default setting so you can run the tool again.
Build and run your project.
Test your tool.
When you are finished, close your application.
Your application currently displays the parcels affected by the buffer, but it doesn't show
the buffer itself.
You have finished this exercise; however, you may wish to complete the Challenges:
The first Challenge tests your ability to draw the buffer polygon on your map.
The second Challenge tests your ability to work with DisplayTransformation.
If you want to complete one or both Challenges, do so now. Otherwise, close Visual
Studio.
Conclusion
In this exercise, you applied knowledge you learned in previous lessons to select features
within a specified distance of a location clicked in the map. You worked with spatial
filters, feature cursors, geometry elements, spatial reference, and topological operators.
9-11
These operations are very powerful on their own; you learned here that they can be
combined to do exactly what you want.
In a previous lesson, you learned how to draw graphics on your map. To complete this
Challenge, you need to apply that knowledge to draw your buffer polygon on the map.
Write code to:
Earlier, you used created a point object from coordinates in map units passed to the
MapControl's OnMouseDown event via the mapx and mapy properties of the parameter e.
To complete this Challenge, create the point object from coordinates that are passed to
the MapControl's OnMouseDown event using the x and y properties of the parameter e.
(Hint: You will need to convert from display units to map units.)
9-12
Exercise 9A
9-13
System.IO
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Controls
ESRI.ArcGIS.ADF
ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.GeoDatabase
Imports ESRI.ArcGIS.Display
Public Class MainForm
Private m_mapControl As IMapControl3 = Nothing
Private m_mapDocumentName As String = String.Empty
+ Private Sub MainForm_Load ...
+Main Menu event handlers
'listen to MapReplaced event in order to update the statusbar and the Save menu
+
9-14
Exercise 9A
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
9-15
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
9-16
Exercise 9A
9-17
9-18
Exercise 9A
9-19
Exercise 9B
Create a buffer based on the location clicked in the map and select nearby features
Work with spatial filters, feature cursors, and spatial reference objects
Exercise shortcut
1. Create a new Visual C# ArcGIS Engine MapControl Application.
2. Add the Select Features command to your ToolbarControl.
3. Create a point to represent a new gas station based on a location the user clicks.
4. Create a spatial filter to select the parcel intersecting the new point in
\Student\IPAN\Exercise09\ParcelProximity.mxd.
5. Using your spatial filter, create a cursor that contains the parcel on which the new
gas station will be located. Fetch a single feature from the cursor. Report the land
use of the parcel that was clicked in a text box.
6. Test your project to confirm that the land use displays in the text box.
7. Determine the buffer distance in the parcel layer's native map units.
8. Create a buffer around the polygon clicked with your new tool, then select the
parcels that are within the buffer distance.
9. If the gas station parcel is selected with the neighboring parcels, create a new
selection environment to remove it from the selection.
** (Challenge) Draw the polygon buffer on your map.
** (Challenge) Create the point object and Use DisplayTransformation.
9-21
Property
Value
Language
Visual C#
Project type
Template
MapControl Application
Name
ParcelBuffer
Location
\Student\IPAN\Exercise09
Solution name
ParcelBuffer
Make sure the Create directory for solution check box is checked.
The code that you write will select features based on a location clicked by the user. To
make it easy to deselect features, you will use a built-in tool.
View the form in Design view.
You will to add a new item to the toolbar.
Open the Properties dialog box for your ToolbarControl.
From the Feature Selection category, add the Select Features tool just to the left of the
map scale.
Open the Properties dialog box for your MapControl.
For Map Document, assign ParcelProximity.mxd from your \Student\IPAN\Exercise09
folder.
Drag two TextBox controls and two Label controls onto your form and position each
text box with a label next to it. (Tip: Place these controls in the upper-right corner of
your map or in another location of your choice. Also, make the TextBox controls wider
to accommodate longer text.)
You will use one set of controls to display projection information and the other set to
display land use.
9-22
Exercise 9B
Control
(Name)
Text
Label
lblProj
Projection:
TextBox
txtProj
Label
lblLU
TextBox
txtLU
Land Use:
9-23
Now you are ready to begin writing the code that will select a parcel and buffer it. You
will start by accessing the active view.
Inside your If statement, complete the following code to instantiate the active view:
______________________ activeView = axMapControl1.______________;
Next, you will add code to the OnMouseDown event to capture the point where your user
clicks in the map display. Your code will eventually use this point to identify the
neighboring parcels.
To capture the point clicked by your user, you need a variable to hold a point object.
Because you are working with an event on the MapControl, there are two options for
instantiating a point object and assigning its x and y coordinates:
1. Populate x and y on your point object with coordinates already in map units
2. Populate x and y on your point object with coordinates that have been
transformed from display units
In this exercise, you will use the first option.
Build your project and resolve any conflicts.
Instantiate a new instance of a point object in the variable aPoint.
Complete the following code to assign the x coordinate from one of the properties of e:
aPoint.X = e.________;
9-24
Exercise 9B
9-25
if (feat == ________)
{
txtProj.Text = "No feature selected";
txtLU.Text = "";
return;
}
else
{
txtProj.Text = "Feature Selected";
}
You will now report the land use for the chosen parcel in the other text box.
Complete the following code to find the attribute Landuse and display its value:
txtLU.Text
= feat.__________________(fCursor.FindField("______________")).ToString();
9-26
Exercise 9B
Because the feature class now has a projection, the name of the projection appears in the
text box.
9-27
Next, you will get an interface for the Parcels geometry (polygon) that has the Buffer
method. Your goal is to create a buffer around the polygon you click with your new tool.
To do this, you will use ITopologicalOperator::Buffer.
In the Visual Studio Object Browser, search for ITopologicalOperator, then click its
Buffer method.
Notice that the Buffer method returns a reference to IGeometry and requires a distance
as Double.
Declare the following variables to work with the buffer:
ITopologicalOperator topoOp;
IPolygon buffPoly;
ITopologicalOperator
9-28
Exercise 9B
9-29
Notice that each time you click a parcel to place a new gas station and buffer it, the
parcels neighboring it are highlighted. However, the clicked parcel itself is also
highlighted. You will remove that parcel from the selection in the next step.
Close your application.
Modify the selection environment to subtract features from the current selection
Subtract the gas station parcel
Set the selection environment to the default and create a new selection
Place your cursor in the empty space before the line of code that calls the
PartialRefresh method.
Complete the following code to assign the proper enumeration to the
CombinationMethod property of selEnv to subtract features from the selection:
______.CombinationMethod = esriSelectionResultEnum.______________________________;
Next, you will call the SelectByShape method on the IMap interface to subtract the gas
station parcel from the selection set.
Write the following code to select only the gas station polygon:
axMapControl1.ActiveView.FocusMap.SelectByShape(aPoint, selEnv, ________);
9-30
Exercise 9B
Notice that the first parcel you clicked is removed from the selection. However, when
you clicked another parcel and buffered it, the selected records did not changenot what
you expected.
Close the application.
Below the code you just wrote, complete the following the code to programmatically
restore a new selection:
selEnv.CombinationMethod = esriSelectionResultEnum.__________________________;
Now the selection method will remove the parcel you clicked from the selection, then
restore the default setting so you can run the tool again.
Build and run your project.
Test your tool.
When you are finished, close your application.
Your application currently displays the parcels affected by the buffer, but it doesn't show
the buffer itself.
You have finished this exercise; however, you may wish to complete the Challenges:
The first Challenge tests your ability to draw the buffer polygon on your map.
The second Challenge tests your ability to work with DisplayTransformation.
If you want to complete one or both Challenges, do so now. Otherwise, close Visual
Studio.
9-31
Conclusion
In this exercise, you applied knowledge you learned in previous lessons to select features
within a specified distance of a location clicked in the map. You worked with spatial
filters, feature cursors, geometry elements, spatial reference, and topological operators.
These operations are very powerful on their own; you learned here that they can be
combined to do exactly what you want.
In a previous lesson, you learned how to draw graphics on your map. To complete this
Challenge, you need to apply that knowledge to draw your buffer polygon on the map.
Write code to:
Earlier, you used created a point object from coordinates in map units passed to the
MapControl's OnMouseDown event using the mapx and mapy properties of the parameter e.
To complete this Challenge, create the point object from coordinates that are passed to
the MapControl's OnMouseDown event via the x and y properties of the parameter e.
(Hint: You will need to convert from display units to map units.)
9-32
Exercise 9B
9-33
System;
System.Drawing;
System.Collections;
System.ComponentModel;
System.Windows.Forms;
System.Data;
System.IO;
System.Runtime.InteropServices;
using
using
using
using
using
ESRI.ArcGIS.esriSystem;
ESRI.ArcGIS.Carto;
ESRI.ArcGIS.Controls;
ESRI.ArcGIS.ADF;
ESRI.ArcGIS.SystemUI;
using
using
using
using
ESRI.ArcGIS.Geodatabase;
ESRI.ArcGIS.Geometry;
ESRI.ArcGIS.Display;
Microsoft.VisualBasic;
namespace ParcelBuffer
{
public sealed partial class MainForm : Form
{
+
class private members
+
class constructor
9-34
Exercise 9B
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
ILayer lyr;
IFeatureLayer2 fLayer;
lyr = axMapControl1.ActiveView.FocusMap.get_Layer(0);
if (lyr is IFeatureLayer2)
{
fLayer = lyr as IFeatureLayer2;
}
else
{
txtProj.Text = "No feature layer found";
return;
}
IFeatureCursor fCursor;
fCursor = fLayer.Search(spatFilt, true);
IFeature feat;
feat = fCursor.NextFeature();
if (feat == null)
{
txtProj.Text = "No feature selected";
txtLU.Text = "";
return;
}
else
{
txtProj.Text = "Feature Selected";
}
txtLU.Text = feat.get_Value(fCursor.FindField("Landuse")).ToString();
9-35
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
9-36
Exercise 9B
axMapControl1.ActiveView.FocusMap.SelectByShape(
buffPoly, selEnv, false);
selEnv.CombinationMethod =
esriSelectionResultEnum.esriSelectionResultSubtract;
axMapControl1.Map.SelectByShape(apoint, selEnv, true);
selEnv.CombinationMethod =
esriSelectionResultEnum.esriSelectionResultNew;
axMapControl1.ActiveView.PartialRefresh(
esriViewDrawPhase.esriViewGeoSelection, null, null);
9-37
9-38
Exercise 9B
9-39
10
Creating and editing
data
Exercise 10A: Create data (VB.NET)
Estimated time: 60 minutes
Exercise 10B: Create data (C#)
Estimated time: 60 minutes
Exercise 10A
Exercise shortcut
1. In Visual Studio, create a new Visual Basic Windows Console Application.
2. Programmatically create a new file geodatabase.
3. Create a table in your geodatabase.
4. Add three fields to your table: an OID field, string field, and number field.
5. Add some records to your table. Populate the string and number field for each.
6. Add a new field, PopPerMH, to the USCounties feature class in
\Student\IPAN\Database\US_States.gdb.
7. Use an update cursor to modify existing features in the dataset.
** (Optional) Compare timings for two different ways of storing changes to a table:
using a cursor vs. the Store method.
10-1
Property
Value
Language
Visual Basic
Project type
Windows
Template
Console Application
Name
CreateAndEdit
Location
\Student\IPAN\Exercise10
Solution name
CreateAndEdit
Make sure the Create directory for solution check box is checked.
Click OK.
In the Solution Explorer, rename Module1.vb as CreateEdit.vb.
Add ArcGIS license checking for an ArcView license, including the shutdown option.
(Hint: Project menu > Add ArcGIS License Checking.)
fGDBwsf As IWorkspaceFactory
workName As IWorkspaceName
name As IName
workspace As IWorkspace
10-2
Exercise 10A
In code view, complete the following code to create the new WorkspaceName:
workName = fGDBwsf.____________(parentFolder, nameGDB, Nothing, 0)
The folder path and geodatabase name are passed into your new function. The Nothing
keyword is specified in order to skip the connection properties argument.
In the Visual Studio Object Browser, locate IWorkspaceName.
Notice that the IWorkspaceName interface provides access to only the most basic
workspace properties, including Category, PathName, and Type.
In order to retrieve the actual Workspace object, you will use the Open method supported
by the WorkspaceName class.
Locate the WorkspaceName class.
10-3
10-4
Exercise 10A
Begin the new sub procedure by declaring the variable wksp as IWorkspace.
Set wksp by calling your CreateFileGDB function and passing in the following strings
for the arguments:
Argument
Value
parentFolder
"\Student\IPAN\Exercise10"
nameGDB
"AnnualSales"
In Sub Main, before the method to shut down the application, call your MakeSalesGDB
method.
Build the solution and run your project.
A console window opens, then closes, indicating that your code has run. You can now
check your results.
Start ArcCatalog.
In the Catalog tree, expand your \Student\IPAN\Exercise10 folder.
You see the new AnnualSales file geodatabase.
Note: If you do not see the AnnualSales file geodatabase, press your F5 key to refresh
the view.
Now that you know how the procedure to make a new geodatabase works, you will
complete the MakeSalesGDB sub procedure to create a table inside the new database.
First, you will delete the geodatabase so that you can re-create it with new properties in
the next step. If you create a geodatabase and then try to create it again without deleting it
first, you will raise an error because the geodatabase already exists.
Delete the AnnualSales file geodatabase from ArcCatalog.
Minimize ArcCatalog.
10-5
oidFld
nameFld
salesFld
10-6
Exercise 10A
Note: Remember the need to use _2 when you want to edit the value of a property .
Assign properties for the remaining fields, using the following table as a guide:
Field
Name_2
Type_2
Length_2
nameFld
"Store"
String
16
salesFld
"Sales"
Integer
16
, then
The AddField method appears as a member of IFieldsEdit even though the code
completer does not display it.
10-7
Now that you have created the fields collection, you can create your table.
Declare the variable tbl as ITable.
Using your feature workspace, create the table, passing in five valid arguments. Use
BikeSales for the name of the table. For the final three arguments, use Nothing,
Nothing, and an empty string, as discussed in the lecture.
Build the solution and run your project.
In ArcCatalog, find your new BikeSales table in the AnnualSales geodatabase.
Note: If you do not see the AnnualSales file geodatabase, press F5 to refresh the view.
10-8
Exercise 10A
Although the data formats are what you designated, the names of the data types in
ArcCatalog differ from the names of the field types you used as input (OID, String,
Integer).
Close the table properties.
Delete your AnnualSales geodatabase from ArcCatalog.
In the next step, you will add data to your table.
Minimize ArcCatalog.
10-9
Field name
Value
Store
Full Cycle
Sales
300000
Call the Store method on row to commit the new information to the table.
You already have a variable (row) declared to IRow. Now you just need to instantiate two
additional row objects (as you did a moment ago) and set some values.
Create two additional rows, using the following table as a guide. Make sure you create
a new row for each record, then call the Store method on each new row.
Store
Sales
UBikes
250000
Pro Peloton
225000
Your table contains three new rows, populated with the values you specified.
This is a good way to add a couple of rows here and there, but if you wanted to add many
rows at one time (for example, 500) it would be much faster to use an insert cursor.
Minimize ArcCatalog.
Note: Do not delete the AnnualSales geodatabase, as you will need it later in the
exercise.
10-10
Exercise 10A
Retrieve the value for the Mobilehome field for the feature and store it in the variable
lngHomes.
Complete the following code to calculate the value of the PopPerMH field:
feat.__________(intPopMH) = lngPop / lngHomes
updFeatures.__________________________(________)
10-11
The code for your loop is now complete. The next lines you write will be executed after
the code inside the loop has finished running.
After the loop, enter the following code to notify the operator that the process has
completed, then wait for a response:
Console.WriteLine("Update complete press any key to exit")
Console.ReadKey()
The ReadKey method waits for the operator to intervene by pressing any key, such as Q
or Enter, to resume the process.
In the Sub Main, comment MakeSalesGDB().
Call your CalcField() sub procedure.
Run your project.
When prompted, close the console window.
In ArcCatalog, expand \Student\IPAN\Database\US_States.gdb.
Preview the table for the USCounties feature class and verify that the PopPerMH field
has been updated.
You have finished this exercise; however, you may wish to complete the optional step:
If you want to complete the optional step, do so now. Otherwise, close ArcCatalog and
Visual Studio.
10-12
Exercise 10A
After the CalcField sub procedure, insert the IPAN_Ex10_Timings code snippet.
Declare the necessary module-level variables as documented in the snippet.
Navigate to the AccessData sub procedure and review its code.
The sub procedure begins with a list of variables that you will populate after you have
explored all the code.
Question 8: What type of geodatabase will be opened?
______________________________________________________________________
The AccessData sub procedure calls two other sub procedures: StoreEdit and
UpdateEdit. Each of these calculates the elapsed time for a series of edits.
Navigate to the StoreEdit sub procedure and review its code.
Question 9: What unit of time is used for the elapsed time calculation?
______________________________________________________________________
The code loops for a specified number of iterations, adds rows to a table, and updates an
attribute for each row. Each new row is saved with the Store method on the row object.
Navigate to the UpdateEdit sub procedure and review its code.
Question 10: What type of cursor is used for these edits?
______________________________________________________________________
Return to the AccessData sub procedure.
You want to add several rows to your table and enter an initial sales value for each new
record.
Supply values for each of the variables, using the following table as a guide:
10-13
Variable
Value
m_gdb
"\Student\IPAN\Exercise10\AnnualSales.gdb"
m_tblName
"BikeSales"
m_numRecs
100
m_newValue
m_fldName
"Sales"
Conclusion
In this exercise, you used several ArcObjects for creating data. You created a new
geodatabase, created a table within it, and added rows and values to the table using the
10-14
Exercise 10A
method. Then, you used an update cursor to calculate the value of a field in a
feature class in another geodatabase.
Store
If you completed the optional step, you compared two ways of editing a table: using the
Store method vs. using an insert cursor. You discovered that, although the Store method
is useful for adding a few records and updating a few values, it is faster to use an insert
cursor when you want to add many records at the same time.
10-15
10-16
Exercise 10A
m_fldName As String
m_fldNum As Integer
m_gdb As String
m_newValue As Long
m_numRecs As Long
m_table As ITable
m_tblName As String
fGDBwsf As IWorkspaceFactory
workName As IWorkspaceName
name As IName
workspace As IWorkspace
10-17
10-18
Exercise 10A
row = tbl.CreateRow
row.Value(tbl.FindField("Store")) = "UBikes"
row.Value(tbl.FindField("Sales")) = 250000
row.Store()
row = tbl.CreateRow
row.Value(1) = "Pro Peloton"
row.Value(2) = 225000
row.Store()
End Sub
Public Sub CalcField()
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
wksp = wsf.OpenFromFile("\Student\IPAN\Database\US_States.gdb", 0)
Catch ex As Exception
Console.WriteLine("GDB Not found - press any key to continue")
Console.ReadKey()
End Try
Dim fWS As IFeatureWorkspace
fWS = CType(wksp, IFeatureWorkspace)
Dim fClass As IFeatureClass
fClass = fWS.OpenFeatureClass("USCounties")
Dim fldPopMH As IFieldEdit = New Field
' Dim fldPopMH As IFieldEdit = New FieldClass
With fldPopMH
.Name_2 = "PopPerMH"
.Type_2 = esriFieldType.esriFieldTypeInteger
End With
fClass.AddField(fldPopMH)
10-19
10-20
Exercise 10A
'
'
'
'
'
'
'
'
Declare
Private
Private
Private
Private
Private
Private
Private
10-21
10-22
Exercise 10B
Exercise shortcut
1. In Visual Studio, create a new Visual C# Windows Console Application.
2. Programmatically create a new file geodatabase.
3. Create a table in your geodatabase.
4. Add three fields to your table: an OID field, string field, and number field.
5. Add some records to your table. Populate the string and number field for each.
6. Add a new field, PopPerMH, to the USCounties feature class in
\Student\IPAN\Database\US_States.gdb.
7. Use an update cursor to modify existing features in the dataset.
** (Optional) Compare timings for two different ways of storing changes to a table:
using a cursor vs. the Store method.
10-23
Property
Value
Language
Visual C#
Project type
Windows
Template
Console Application
Name
CreateAndEdit
Location
\Student\IPAN\Exercise10
Solution name
CreateAndEdit
Make sure the Create directory for solution check box is checked.
Click OK.
In the Solution Explorer, rename Program.cs as CreateEdit.cs.
If prompted, click yes for all instances.
Add ArcGIS license checking for an ArcView license, including the shutdown option.
(Hint: Project menu > Add ArcGIS License Checking.)
10-24
Exercise 10B
In code view, complete the following code to create the new WorkspaceName:
workName = fGDBwsf.____________(parentFolder, nameGDB, null, 0);
The folder path and geodatabase name are passed into your new method. The null
keyword is specified in order to skip the connection properties argument.
In the Geodatabase OMD, locate IWorkspaceName. Tip: Search for
IWorkspaceName :, i.e., the interface name followed by a space and a colon.
IWorkspaceName
Notice that the IWorkspaceName interface provides access to only the most basic
workspace properties, including Category, PathName, and Type.
In order to retrieve the actual Workspace object, you will use the Open method supported
by the WorkspaceName class.
Follow the line that extends from the top of the WorkspaceName coclass.
In the list of properties and methods, click the Open method.
10-25
Complete the following code to return the new workspace from CreateFileGDB:
return ________________________;
10-26
Exercise 10B
Set wksp by calling your CreateFileGDB method and passing in the following strings
for the arguments:
Argument
Value
parentFolder
"\\Student\\IPAN\\Exercise10"
nameGDB
"AnnualSales"
Note: If you would like, create variables to hold the string values, then pass the variables
as the arguments.
In Main, after the comment //Do not make any call to ArcObjects after
ShutDownApplication() and before the method to shut down the application, call
MakeSalesGDB.
Build the solution and run your project.
A console window opens, then closes, indicating that your code has run. You can now
check your results.
Start ArcCatalog.
In the Catalog tree, expand your \Student\IPAN\Exercise10 folder.
You see the new AnnualSales file geodatabase.
Note: If you do not see the AnnualSales file geodatabase, press your F5 key to refresh
the view.
Now that you know how to make a new geodatabase, you will complete the
MakeSalesGDB method to create a table inside the new database.
First, you will delete the geodatabase so that you can re-create it with new properties in
the next step. If you create a geodatabase and then try to create it again without deleting it
first, you will raise an error because the geodatabase already exists.
Delete the AnnualSales file geodatabase from ArcCatalog.
10-27
Minimize ArcCatalog.
oidFld
nameFld
salesFld
Just below the declaration for oidFld, complete the following code to set its
properties. Make sure to set the field type as OID.
oidFld.Name_2 = "OID";
oidFld.Type_2 = esriFieldType.________________________________;
Note: Remember the need to use _2 when you want to edit the value of a property
Assign properties for the remaining fields, using the following table as a guide:
10-28
Exercise 10B
Field
Name_2
Type_2
Length_2
nameFld
"Store"
String
16
salesFld
"Sales"
Integer
16
Next, you will add the field objects to the fields collection.
Add each field object to your fldsEdit fields collection.
Note: The order in which you add the fields in code is the order in which they will
appear, from left to right, in the new table.
Now that you have created the fields collection, you can create your table.
Declare the variable tbl as ITable.
Using your feature workspace, create the table, passing in five valid arguments. Use
BikeSales for the name of the table. For the final three arguments, use null, null,
and an empty string.
Build the solution and run your project.
In ArcCatalog, find your new BikeSales table in the AnnualSales geodatabase.
Note: If you do not see the AnnualSales file geodatabase, press F5 to refresh the view.
10-29
Field name
Value
Store
Full Cycle
Sales
300000
Call the Store method on row to commit the new information to the table.
You already have a variable (row) declared to IRow. Now you just need to instantiate two
additional row objects (as you did a moment ago) and set some values.
10-30
Exercise 10B
Create two additional rows, using the following table as a guide. Make sure you create
a new row for each record, then call the Store method on each new row.
Store
Sales
UBikes
250000
Pro Peloton
225000
Your table contains three new rows, populated with the values you specified.
This is a good way to add a couple of rows here and there, but if you wanted to add many
rows at one time (for example, 500) it would be much faster to use an insert cursor.
Minimize ArcCatalog.
Note: Do not delete the AnnualSales geodatabase, as you will need it later in the
exercise.
10-31
Retrieve the value for the Mobilehome field for the feature and store it in the variable
lngHomes.
Complete the following code to calculate the value of the PopPerMH field:
feat.__________(intPopMH, (lngPop / lngHomes));
updFeatures.__________________________(________);
The ReadKey method waits for the operator to intervene by pressing a key, such as Enter,
to resume the process.
In Main, comment MakeSalesGDB();.
10-32
Exercise 10B
If you want to complete the optional step, do so now. Otherwise, close ArcCatalog and
Visual Studio.
10-33
Question 9: What unit of time is used for the elapsed time calculation?
______________________________________________________________________
The code loops for a specified number of iterations, adds rows to a table, and updates an
attribute for each row. Each new row is saved with the Store method on the row object.
Navigate to the UpdateEdit method and review its code.
Question 10: What type of cursor is used for these edits?
______________________________________________________________________
Return to the AccessData method.
You want to add several rows to your table and enter an initial sales value for each new
record.
Supply values for each of the variables, using the following table as a guide:
Variable
Value
m_gdb
"\\Student\\IPAN\\Exercise10\\AnnualSales.gdb"
m_tblName
"BikeSales"
m_numRecs
100
m_newValue
m_fldName
"Sales"
10-34
Exercise 10B
difference you would experience if you were adding thousands of records and updating
more values.
Close the console window.
In ArcCatalog, preview the BikeSales table to confirm that the new records were
added.
If time permits, experiment with fields in other datasets in your
\Student\IPAN\Database folder.
If time permits, experiment with fields in other datasets in your
\Student\IPAN\Database folder (Hint: You may need to change the data type of
m_newValue).
Close ArcCatalog and Visual Studio.
Conclusion
In this exercise, you used several ArcObjects for creating data. You created a new
geodatabase, created a table within it, and added rows and values to the table using the
Store method. Then, you used an update cursor to calculate the value of a field in a
feature class in another geodatabase.
If you completed the optional step, you compared two ways of editing a table: using the
Store method vs. using an insert cursor. You discovered that, although the Store method
is useful for adding a few records and updating a few values, it is faster to use an insert
cursor when you want to add many records at the same time.
10-35
10-36
Exercise 10B
System;
System.Collections.Generic;
System.Text;
ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesGDB;
namespace CreateAndEdit
{
public class CreateEdit
{
private static LicenseInitializer m_AOLicenseInitializer =
new CreateAndEdit.LicenseInitializer();
private static void Main(string[] args)
{
//ESRI License Initializer generated code.
if (!m_AOLicenseInitializer.InitializeApplication(
new esriLicenseProductCode[]
{
esriLicenseProductCode.esriLicenseProductCodeArcInfo
},
new esriLicenseExtensionCode[] { }))
{
System.Console.WriteLine(m_AOLicenseInitializer.LicenseMessage());
System.Console.WriteLine("This application could not initialize
with the correct ArcGIS license and will shutdown.");
m_AOLicenseInitializer.ShutdownApplication();
return;
}
//ESRI License Initializer generated code.
//Do not make any call to ArcObjects after ShutDownApplication()
// MakeSalesGDB();
// CalcField();
AccessData();
m_AOLicenseInitializer.ShutdownApplication();
} // end Main
10-37
10-38
Exercise 10B
10-39
}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
}
Console.WriteLine("Update complete - press any key to exit");
Console.ReadKey();
ArcGIS Snippet Title:
Timings
Long Description:
Timings - Store method versus Insert Cursor
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
Applicable ArcGIS Product Versions:
9.2
9.3
Notes: The snippet assumes the following variables
have been declared:
//
Declare the following variables
//
String m_fldName;
//
int m_fldNum;
//
String m_gdb;
//
long m_newValue;
//
long m_numRecs;
//
ITable m_table;
//
String m_tblName;
private static void AccessData()
{
string m_fldName;
int m_fldNum;
string m_gdb;
long m_newValue = 0;
long m_numRecs = 0;
ITable m_table;
string m_tblName;
m_gdb = "\\Student\\IPAN\\Exercise10\\AnnualSales.gdb";
m_tblName = "BikeSales";
m_numRecs = 100;
m_newValue = 0;
m_fldName = "Sales";
10-40
Exercise 10B
10-41
10-42
11
Geoprocessing
Exercise 11A
Exercise shortcut
1. Open and review an existing workspace, the Geoprocessing.gdb file geodatabase,
from \Student\IPAN\Database folder.
2. In Visual Studio, create a new Visual Basic Windows Console Application.
3. Programmatically determine whether the Buildings feature class resides in the file
geodatabase.
4. Buffer the Buildings feature class.
5. Modify your code to overwrite any existing output. Introduce error handling and
return all geoprocessing messages when an error occurs.
6. Buffer the Buildings feature class and create a new feature class of the output
buffer features. Find the areas of intersection among the output buffer features.
7. Add a field to each polygon feature class in the CityData feature dataset.
** (Optional) Perform a batch process on a larger volume of data using a "List"
method and add a field to each feature class in the CityData feature dataset.
** (Challenge): List the environment properties in the console window, and report
the total number of environments.
11-1
11-2
Exercise 11A
When you run geoprocessing tasks, you generally need to set the workspace, which can
be a file folder or a geodatabase. In a later step, you will set the workspace using the path
you just copied.
Minimize ArcCatalog.
Property
Value
Language
Visual Basic
Project type
Windows
Template
Console Application
Name
GPTasks
Location
\Student\IPAN\Exercise11
Solution name
GPTasks
11-3
Make sure the box for Create directory for solution is checked.
Click OK.
In the Solution Explorer, rename Module1.vb as GeoProc.vb.
Add license checking for an ArcView license, including the shutdown option. (Hint:
Project menu, Add ArcGIS License Checking)
11-4
Exercise 11A
Question 2: Which reference do you need to add to create the GeoProcessor object? (Be
careful two references have very similar names.) What is the name of the other
reference?
______________________________________________________________________
It's that easy to create a GeoProcessor object. Now you can begin to execute tools and
work with other methods and properties on the GeoProcessor object.
Enter the following code for your path (Tip: You can paste the value for the path!):
Dim path As String
path = "\Student\IPAN\Database\Geoprocessing.gdb\CityData"
In the OMD, scroll down in the GeoProcessor coclass until you see the
SetEnvironmentValue method.
This method can be used to set any environment setting for the GeoProcessor object.
In your code, complete the following code to set the workspace environment value for
your data:
gp.__________________________________("__________________", ________)
11-5
Next, you will work with the Exists method on the GeoProcessor object. This will help
you determine whether data is present in the workspacebefore you try to access the
data from a geoprocessing tool.
Use the developer resource of your choice to review the syntax for the Exists method.
Complete the following If statement to check whether the Buildings feature class
exists and report your findings:
If gp.____________("__________________", Nothing) ________
Console.WriteLine("The data is present - press any key")
Console.ReadKey()
Else
Console.WriteLine("The data is missing - press any key")
Console.ReadKey()
Exit Sub
End If
The Exists method verifies that the Buildings feature class exists. This is a handy
method to use because if you try to run a tool on data that does not exist, your tool will
fail. Now you can test for data existence first, and then choose whether to run the tool if
the data exists, or do something else if it doesn't.
Press any key to close the console window.
Comment the If statement you just wrote.
Next, you will run a system tool to buffer a feature class.
to open
Expand the Analysis Tools toolbox, then expand the Proximity toolset.
Right-click the Buffer tool and choose Help.
11-6
Exercise 11A
Notice that the syntax for running this tool applies to .NET, VBA, Python, and other
object-oriented scripting languages. For this tool, you need an input feature class, output
feature class, and buffer distance. The rest of the parameters are optional. Knowing the
sequence in which the parameters appear is important to the success of the tool.
Look at the list of parameters in the Parameter column.
Here, you see whether each parameter is required or optional.
Close the help window.
Minimize ArcCatalog.
If necessary, open the Visual Studio Object Browser.
Locate the IGeoProcessor interface.
Display the result.
Locate the Execute method, then click it.
The first argument is the name of the tool as a string. Remember, it is good practice to
append the alias when referencing a tool name. The second argument expects values as
IVariantArray. This argument holds all the parameters for a tool as an array and is
passed as a variable when you execute the tool. The third argument is for tracking the
cancellation of a tool.
11-7
In your code, create a new instance of a variant array (VarArray) and store it in the
variable param.
You will use the Add method in order to add parameters for your tool. As you saw earlier,
the Buffer tool has many parameters. You will create the three that are required: input,
output, and buffer distance.
Add the three required parameters to your new variant array, using the following table
as a guide:
Parameter
Value
Input
"Buildings"
Output
"GPBuff"
Buffer distance
300
Question 3: What alias you will append to the Buffer tool? (Hint: In ArcCatalog,
right-click the toolbox that contains the Buffer tool and choose Properties.)
______________________________________________________________________
Complete the following code to execute the Buffer tool:
gp._______________("Buffer_________________", __________, Nothing)
11-8
Exercise 11A
11-9
This error tells you nothing about why the operation failed, but it shows the same error
code number that would display in an application using VBA in ArcMap or ArcCatalog.
Fortunately, when you get messages directly from the GeoProcessor object, the
messages will be more helpful.
Click OK to close the View Detail window.
Click the Stop Debugging button
in Visual Studio.
11-10
Exercise 11A
Dim i As Integer
If gp.________________________ > 0 Then
For i = 0 To gp.MessageCount - 1
Console.WriteLine(gp.GetMessage(__))
Next
End If
Now you will create a Try Catch statement to report messages from the GeoProcessor
object in cases of error.
In the Geoprocessing sub procedure, after your code that sets up the parameters,
create a Try Catch statement. (Hint: Type Try and press Enter.)
In the Try section:
Make sure your code will run the Buffer tool only once.
11-11
The error message states that the GPBuff feature class already exists. This is much more
helpful than the previous error. In this case, you can devise a solution because you know
the cause of the error. You have a few options:
11-12
"Buildings"
"BldgsBuff300"
300
Exercise 11A
In ArcToolbox of your ArcCatalog, expand the Analysis Tools toolbox and the
Overlay toolset.
Right-click the Intersect tool and choose Help.
Scroll down to the Scripting syntax.
Question 5: What are the required parameters?
______________________________________________________________________
Close the help window.
In addition to the variant array for the Buffer tool, you will also need a variant array for
the Intersect tool.
In your code, create a new instance of VarArray and store it in the variable
intParams.
Complete the following code to add the input and output parameters for the Intersect
tool. For the input parameter, use the output from your Buffer tool.
intParams.______("_______________________")
intParams.______("OverlapAreas")
11-13
Arrange and symbolize the layers so that you can view the features.
Your map now displays the original Buildings layer plus two new layers, created as
output from the tools. You could keep chaining geoprocessing tools onto the end of this
procedure. For example, you could add a field to the attribute table of the OverlapAreas
layer, then calculate its value.
Close ArcMap without saving changes.
You have finished this exercise; however, you may wish to complete the optional step
and Challenge:
Step 7 shows you how to run a batch process to add a field to each feature class in
a dataset.
The Challenge tests your ability to list all of the environments for the
GeoProcessor object.
If you want to complete one or both of these, do so now. Otherwise, close Visual
Studio and ArcCatalog.
11-14
Exercise 11A
and add a field to each feature class in the CityData feature dataset. You will begin by
creating a GeoProcessor object.
Create a new sub procedure called BatchProcessing with no arguments.
Create the GeoProcessor object and set the workspace. Tip: Copy existing code from
the MultipleTools sub procedure.
The GeoProcessor coclass contains several methods built specifically for creating lists
of data. These methods work with different types of data and provide flexibility for
restricting a search by name or data category.
In the developer resource of your choice, locate the GeoProcessor coclass.
In the list of members, locate the methods that begin with the word "List."
Locate the ListFeatureClasses method.
This method creates a list of all, or some, of the feature classes in the current workspace.
Question 6: What types of filters does the ListFeatureClasses method accept?
______________________________________________________________________
Question 7: What does the ListFeatureClasses method return?
______________________________________________________________________
Declare a variable named gpEnumList to the appropriate interface.
Complete the following code to list all the polygon feature classes in the current
workspace:
gpEnumList = gp.____________________________________("*", "______________", "")
In the Visual Studio Object Browser, search for and display the IGPEnumList
interface.
11-15
Just like the enumerations for layers, this enumeration has only two methods: Next and
Reset. Notice that the Next method returns a string. In this case, the string represents a
feature class name. To access each feature class in the list, you will need a string variable.
Declare a string variable named strFCName to store each feature class.
Set the variable to the Next item in gpEnumList.
In ArcCatalog, refresh the view to display the data you created in the CityData feature
dataset in previous steps.
Question 8: How many polygon feature classes does CityData contain?
______________________________________________________________________
You will programmatically identify which feature classes are in this enumeration and
report their names in the console window.
Create a Do While loop that runs as long as strFCName is not equal to an empty string.
Inside the loop, complete the following code to list the names of each feature class:
Console.WriteLine(_________)
11-16
Exercise 11A
Start ArcMap.
In ArcToolbox, click the Search tab.
Enter AddField as the search word, then click Search.
11-17
strFCName
"Acreage"
"Double"
Call the Execute method on the GeoProcessor object to run the Add Field tool.
To avoid a schema lock error, close ArcCatalog.
Run your project.
Close the console window.
Start ArcCatalog.
Navigate to \Student\IPAN\Database\Geoprocessing.gdb\CityData.
Verify that the Acreage field was added by viewing the properties for some of the
polygon feature classes in the CityData feature dataset. (As an example, the graphic
below shows the fields in the Buildings feature class.)
Imagine the possibilities for batch processing using ArcObjects. After adding the field,
you could calculate it, then build a topology and load feature classes into it, and then
execute a selection to create a subset of features. Batch processing allows you to run
geoprocessing tools on many datasets with minimal interaction from the user.
If you want to complete the Challenge, do so now. Otherwise, close ArcCatalog and
close Visual Studio.
11-18
Exercise 11A
Conclusion
In this exercise, you worked with a GeoProcessor object. This is a very powerful object
in that it has many properties and methods you can use to facilitate geoprocessing your
data. The ability to run a single geoprocessing tool, multiple geoprocessing tools, and
data-intensive batch processes without user intervention boosts productivity.
When you created a GeoProcessor object in previous steps, you also assigned an
environment setting. The instructions guided you to code Workspace as the argument.
But, what if you wanted to assign a different environment setting? How would you know
its value? And how many environments are there, anyway? To complete this Challenge,
you will derive the answers to these questions.
Use developer resources to find the method on the GeoProcessor object that will list
the environment properties.
Write code to list each property, report its name in the console window, and report the
total number of environments.
11-19
11-20
Exercise 11A
Question 10: Which toolbox contains the Add Field tool, and what is its alias?
Answer: Data Management Tools; management
Question 11: What are the required parameters?
Answer: Input table (in_table), field name (field_name), field type (field_type)
11-21
11-22
Exercise 11A
Try
gp.OverwriteOutput = True
gp.Execute("Buffer_analysis", param, Nothing)
ReturnMessages(gp)
Catch ex As Exception
ReturnMessages(gp)
End Try
Console.WriteLine("Process finished - press any key")
Console.ReadKey()
End Sub
Sub ReturnMessages(ByVal gp As IGeoProcessor)
' Print messages from tool execution
Dim i As Integer
If gp.MessageCount > 0 Then
For i= 0 To gp.MessageCount - 1
Console.WriteLine(gp.GetMessage(i))
Next
End If
End Sub
Sub MultipleTools()
Dim gp As IGeoProcessor = New GeoProcessor
'Dim gp As IGeoProcessor = New GeoProcessorClass
Dim path As String
path = "\Student\IPAN\Database\Geoprocessing.gdb\CityData"
gp.SetEnvironmentValue("Workspace", path)
Dim buffParams As IVariantArray = New VarArray
'Dim buffParams As IVariantArray = New VarArrayClass
buffParams.Add("Buildings")
buffParams.Add("BldgsBuff300")
buffParams.Add(300)
Dim intParams As IVariantArray = New VarArray
'Dim intParams As IVariantArray = New VarArrayClass
intParams.Add("BldgsBuff300")
intParams.Add("OverlapAreas")
gp.OverwriteOutput = True
gp.Execute("Buffer_Analysis", buffParams, Nothing)
gp.Execute("Intersect_Analysis", intParams, Nothing)
End Sub
Sub BatchProcessing()
Dim gp As IGeoProcessor = New GeoProcessor
'Dim gp As IGeoProcessor = New GeoProcessorClass
Dim path As String
path = "\Student\IPAN\Database\Geoprocessing.gdb\CityData"
gp.SetEnvironmentValue("Workspace", path)
11-23
11-24
Exercise 11A
11-25
Exercise 11B
Exercise shortcut
1. Open and review an existing workspace, the Geoprocessing.gdb file geodatabase,
from \Student\IPAN\Database folder.
2. In Visual Studio, create a new Visual C# Windows Console Application.
3. Programmatically determine whether the Buildings feature class resides in the file
geodatabase.
4. Buffer the Buildings feature class.
5. Modify your code to overwrite any existing output. Introduce error handling and
return all geoprocessing messages when an error occurs.
6. Buffer the Buildings feature class and create a new feature class of the output
buffer features. Find the areas of intersection among the output buffer features.
7. Add a field to each polygon feature class in the CityData feature dataset.
** (Optional) Perform a batch process on a larger volume of data using a "List"
method and add a field to each feature class in the CityData feature dataset.
** (Challenge): List the environment properties in the console window, and report
the total number of environments.
11-27
11-28
Exercise 11B
When you run geoprocessing tasks, you generally need to set the workspace, which can
be a file folder or a geodatabase. In a later step, you will set the workspace using the path
you just copied.
Minimize ArcCatalog.
Property
Value
Language
Visual C#
Project type
Windows
Template
Console Application
Name
GPTasks
Location
\Student\IPAN\Exercise11
Solution name
GPTasks
11-29
Make sure the box for Create directory for solution is checked.
Click OK.
In the Solution Explorer, rename Program.cs as GeoProc.cs.
Add license checking for an ArcView license, including the shutdown option. (Hint:
Project menu, Add ArcGIS License Checking)
11-30
Exercise 11B
Question 2: Which reference do you need to add to create the GeoProcessor object? (Be
careful two references have very similar names.) What is the name of the other
reference?
______________________________________________________________________
It's that easy to create a GeoProcessor object. Now you can begin to execute tools and
work with other methods and properties on the GeoProcessor object.
Build your project.
Enter the following code for your path (Tip: You can paste the value for the path!):
string path;
path = "\\Student\\IPAN\\Database\\Geoprocessing.gdb\\CityData";
In the OMD, scroll down in the GeoProcessor coclass until you see the
SetEnvironmentValue method.
This method can be used to set any environment setting for the GeoProcessor object.
In your code, complete the following code to set the workspace environment value for
your data:
gp.__________________________________("Workspace", ________);
In Main, after the code Do not make any call to ArcObjects after
ShutDownApplication(), call your Geoprocessing method.
Run your project.
The console window opens with the workspace listed in it.
11-31
The Exists method verifies that the Buildings feature class exists. This is a handy
method to use because if you try to run a tool on data that does not exist, your tool will
fail. Now you can test for data existence first, and then choose whether to run the tool if
the data exists, or do something else if it doesn't.
Press any key to close the console window.
Comment the code block you just wrote starting from object missingType until the
end of If loop.
11-32
Exercise 11B
to open
Expand the Analysis Tools toolbox, then expand the Proximity toolset.
Right-click the Buffer tool and choose Help.
The ArcGIS Desktop help opens for the tool.
Scroll down to Scripting syntax.
Notice that the syntax for running this tool applies to .NET, VBA, Python, and other
object-oriented scripting languages. For this tool, you need an input feature class, output
feature class, and buffer distance. The rest of the parameters are optional. Knowing the
sequence in which the parameters appear is important to the success of the tool.
Look at the list of parameters in the Parameter column.
Here, you see whether each parameter is required or optional.
Close the help window.
Minimize ArcCatalog.
If necessary, open the Visual Studio Object Browser.
Locate the IGeoProcessor interface.
Display the result.
11-33
The first argument is the name of the tool as a string. Remember, it is good practice to
append the alias when referencing a tool name. The second argument expects values as
IVariantArray. This argument holds all the parameters for a tool as an array and is
passed as a variable when you execute the tool. The third argument is for tracking the
cancellation of a tool.
In your code, create a new instance of a variant array (VarArray) store it in the
variable param.
You will use the Add method in order to add parameters for your tool. As you saw earlier,
the Buffer tool has many parameters. You will create the three that are required: input,
output, and buffer distance.
Add the three required parameters to your new variant array, using the following table
as a guide:
Parameter
Value
Input
"Buildings"
Output
"GPBuff"
Buffer distance
300
Question 4: What alias you will append to the Buffer tool? (Hint: In ArcCatalog,
right-click the toolbox that contains the Buffer tool and choose Properties.)
______________________________________________________________________
Complete the following code to execute the Buffer tool:
gp._______________("Buffer_________________", __________, null);
11-34
Exercise 11B
11-35
The error tells you nothing about why the operation failed, but it shows the same error
code number that would display in an application using VBA in ArcMap or ArcCatalog.
Fortunately, when you get messages directly from the GeoProcessor object, the
messages will be more helpful.
Click OK to close the View Detail window.
Click the Stop Debugging button
in Visual Studio.
Now you will create a try catch statement to report messages from the GeoProcessor
object, regardless of whether your tool ran successfully or failed.
In the Geoprocessing method, after your code that sets up the parameters, create a
try catch block.
In the try section:
11-36
Make sure your code will run the Buffer tool only once.
Exercise 11B
The error message states that the GPBuff feature class already exists. This is much more
helpful than the previous error. In this case, you can devise a solution because you know
the cause of the error. You have a few options:
11-37
"Buildings"
"BldgsBuff300"
300
In ArcToolbox of your ArcCatalog, expand the Analysis Tools toolbox and the
Overlay toolset.
Right-click the Intersect tool and choose Help.
Scroll down to the Scripting syntax.
Question 6: What are the required parameters?
______________________________________________________________________
Close the help window.
In addition to the variant array for the Buffer tool, you will also need a variant array for
the Intersect tool.
In your code, create a new instance of VarArray and store it in the variable
intParams.
Complete the following code to add the input and output parameters for the Intersect
tool. For the input parameter, use the output from your Buffer tool.
intParams.______("_______________________");
intParams.______("OverlapAreas");
11-38
Exercise 11B
Your map now displays the original Buildings layer plus two new layers, created as
output from the tools. You could keep chaining geoprocessing tools onto the end of this
procedure. For example, you could add a field to the attribute table of the OverlapAreas
layer, then calculate its value.
Close ArcMap without saving changes.
11-39
You have finished this exercise; however, you may wish to complete the optional step
and Challenge:
Step 7 shows you how to run a batch process to add a field to each feature class in
a dataset.
The Challenge tests your ability to list all of the environments for the
GeoProcessor object.
If you want to complete one or both of these, do so now. Otherwise, close Visual
Studio and ArcCatalog.
11-40
Exercise 11B
In the Visual Studio Object Browser, search for and display the IGPEnumList
interface.
Just like the enumerations for layers, this enumeration has only two methods: Next and
Reset. Notice that the Next method returns a string. In this case, the string represents a
feature class name. To access each feature class in the list, you will need a string variable.
Declare a string variable called strFCName to store each feature class.
Set the variable to the Next item in gpEnumList.
In ArcCatalog, refresh the view to display the data you created in the CityData feature
dataset in previous steps.
Question 9: How many polygon feature classes does CityData contain?
______________________________________________________________________
You will programmatically identify which feature classes are in this enumeration and
report their names in the console window.
Create a while loop that runs as long as strFCName is not equal to an empty string.
Inside the loop, complete the following code to list the names of each feature class:
Console.WriteLine(_________);
11-41
11-42
Exercise 11B
strFCName
"Acreage"
"Double"
Call the Execute method on the GeoProcessor object to run the Add Field tool.
Build your project.
To avoid a schema lock error, close ArcCatalog.
Run your project.
Close the console window.
Start ArcCatalog.
Navigate to \Student\IPAN\Database\Geoprocessing.gdb\CityData.
11-43
Verify that the Acreage field was added by viewing the properties for some of the
polygon feature classes in the CityData feature dataset. (As an example, the graphic
below shows the fields in the Buildings feature class.)
Imagine the possibilities for batch processing using ArcObjects. After adding the field,
you could calculate it, then build a topology and load feature classes into it, and then
execute a selection to create a subset of features. Batch processing allows you to run
geoprocessing tools on many datasets with minimal interaction from the user.
If you want to complete the Challenge, do so now. Otherwise, close ArcCatalog and
close Visual Studio.
Conclusion
In this exercise, you worked with a GeoProcessor object. This is a very powerful object
in that it has many properties and methods you can use to facilitate geoprocessing your
data. The ability to run a single geoprocessing tool, multiple geoprocessing tools, and
data-intensive batch processes without user intervention boosts productivity.
When you created a GeoProcessor object in previous steps, you also assigned an
environment setting. The instructions guided you to code Workspace as the argument.
But, what if you wanted to assign a different environment setting? How would you know
its value? And how many environments are there, anyway? To complete this Challenge,
you will derive the answers to these questions.
Use developer resources to find the method on the GeoProcessor object that will list
the environment properties.
11-44
Exercise 11B
Write code to list each property, report its name in the console window, and report the
total number of environments.
11-45
11-46
Exercise 11B
Question 10: How many polygon feature classes are listed in the console window?
Answer: Six
Question 11: Which toolbox contains the Add Field tool, and what is its alias?
Answer: Data Management Tools; management
Question 12: What are the required parameters?
Answer: Input table (in_table), field name (field_name), field type (field_type)
11-47
System;
System.Collections.Generic;
System.Text;
ESRI.ArcGIS.esriSystem;
ESRI.ArcGIS.Geoprocessing;
namespace GPTasks
{
class GeoProc
{
private static LicenseInitializer m_AOLicenseInitializer1 =
new GPTasks.LicenseInitializer();
private static LicenseInitializer m_AOLicenseInitializer =
new GPTasks.LicenseInitializer();
static void Main(string[] args)
{
//ESRI License Initializer generated code.
if (!m_AOLicenseInitializer1.InitializeApplication(
new esriLicenseProductCode[]
{ esriLicenseProductCode.esriLicenseProductCodeArcView },
new esriLicenseExtensionCode[] { }))
{
System.Console.WriteLine(m_AOLicenseInitializer1.LicenseMessage());
System.Console.WriteLine(
"This application could not initialize with the
correct ArcGIS license and
will shutdown.");
m_AOLicenseInitializer1.ShutdownApplication();
return;
}
//ESRI License Initializer generated code.
//Do not make any call to ArcObjects after ShutDownApplication()
//Geoprocessing();
//MultipleTools();
BatchProcessing();
}
m_AOLicenseInitializer1.ShutdownApplication();
11-48
Exercise 11B
gp.OverwriteOutput = true;
gp.Execute("Buffer_analysis", param, null);
returnMessages(gp);
}
catch
{
returnMessages(gp);
}
11-49
while (!strFCName.Equals(""))
{
Console.WriteLine(strFCName);
IVariantArray fldParams = new VarArrayClass();
fldParams.Add(strFCName);
fldParams.Add("Acreage");
fldParams.Add("Double");
gp.Execute("AddField_management", fldParams, null);
strFCName = gpEnumList.Next();
}
Console.WriteLine("Press any key.");
Console.ReadKey();
11-50
Exercise 11B
11-51
12
Working with layouts
Exercise 12A
Exercise shortcut
1. In ArcMap, open an existing template from \Student\IPAN\Database\Templates
folder. Modify the template in layout view and save it as MyTemplates.mxt.
2. In Visual Studio, create a new Visual Basic Windows Forms Application. Add a
PageLayoutControl, ToolbarControl, and LicenseControl to the form.
3. Load MyTemplates.mxt template into your PageLayoutControl.
4. Load the first map in the map document into your PageLayoutControl from
\Student\IPAN\Exercise12\MapsAndLayers.mxd.
5. Programmatically loop though the elements in the template and find the map
frame. Overwrite the default map with your new template.
6. Loop through the elements to find the two text elements, then tag these two with
an appropriate identifier.
7. Use the tag you just created to find the current map title and modify it.
8. Export the active view of your layout to a PDF file.
** (Optional) Associate the units from your map with the scale bar.
** (Challenge) Modify the second text element with your name.
** (Challenge) Loop through all the maps in your map document and process the
layout for each map.
12-1
Double-click the title text element at the top of the layout page (shown below).
The properties for the text element display. If you wanted to work with this template in
ArcMap, you could edit the title here manually, but you will automate the process using
code.
Close the Properties dialog box.
Using the Zoom In tool
center of the layout page.
Note: Be sure to use the tool on the Layout toolbar, not the Tools toolbar.
12-2
Exercise 12A
You will also modify this text element in this exercise. You will need to devise a strategy
to distinguish between this text element and the title text element.
Close the Properties dialog box.
Locate the scale bar element above the text element.
The text "Unknown Units" displays as part of the scale bar.
Double-click the scale bar to display its properties.
Notice that this is a double alternating scale bar.
Question 1: On the Scale and Units tab, how many times do you see "Unknown Units"?
What units does this refer to?
______________________________________________________________________
Note this information for future reference you will need to modify the units later in this
exercise.
Close the scale bar's Properties dialog box.
Move to the lower-left corner in the layout page.
Select the legend element, then delete it.
On the Layout toolbar, click the Zoom Whole Page button
When you load your template in a later step, it will display at this extent.
From the File menu, choose Save As.
12-3
Close ArcMap.
Now that your are familiar with your template, you can begin writing code for it.
Property
Value
Language
Visual Basic
Project type
Windows
Template
Name
PageLayout
Location
\Student\IPAN\Exercise12
Solution name
PageLayout
Make sure the box for Create directory for solution is checked.
12-4
PageLayoutControl
ToolbarControl
LicenseControl
Exercise 12A
Open the Properties dialog box for the ToolbarControl and do the following:
12-5
Property
Value
Text
Add Map
(Name)
btnAddMap
12-6
Exercise 12A
You need to specify which map (data frame) you want to access.
Set map to point to the first map in your map document.
In the next few steps, you will overwrite some of the elements on your template with
values specific to your map. You will pass gc as an argument to those procedures.
12-7
In a previous exercise, you used the IObjectCopy interface to copy a map from a
MapControl to a PageLayoutControl. In this exercise, you will use IObjectCopy to
overwrite the default map template with your custom template.
Instantiate a new instance of ObjectCopy in your variable mapCopy.
Locate IObjectCopy in the Visual Studio Object Browser.
Question 4: How many members does it have? Which method of IObjectCopy will you
use to overwrite the map frame in the center of your template?
______________________________________________________________________
Call this method on mapCopy to copy your map, passing map and mFrame.Map as
arguments.
Build your project, then run it.
Test the Add Map button.
The first map MapsAndLayers.mxd replaces the default map frame on your template.
Close your application.
12-8
Exercise 12A
contains more than one text element. You will need to determine whether you have found
the title element.
One way to identify the title element is to examine its text and search for a unique
keyword. The default title on the template is "< Double-click to enter map title >". You
could incorporate code that uses the Like operator, for example, to search for the word
"title":
If txtElem.Text Like "*title*" Then
For a single map, this code would solve your dilemma. However, if you are creating more
than one map, the title will change. A different solution is to assign a unique type
(analogous to a tag) to each text element.
Insert a new sub procedure called TagTheElements that accepts the argument gc as
IGraphicsContainer.
Copy the code from your returnMapFrame function and paste it into your
TagTheElements function.
Collapse the returnMapFrame function.
Modify your code so it looks like the following:
gc.Reset()
Dim elem As IElement
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
If TypeOf elem Is ITextElement Then
End If
elem = gc.Next
Loop
After the Dim elem statement, declare txtElem as ITextElement and elemProps as
IElementProperties3.
Inside the If statement, complete the following code to assign a value to txtElem:
txtElem = ________
Question 5: Is the assignment statement txtElem = elem a QI? Why or why not?
______________________________________________________________________
______________________________________________________________________
12-9
After the txtElem assignment statement, begin an If statement to check whether the
text element contains the string "*title*". (Hint: The code appears earlier in this
step.)
Then, if element's Text property contains "*title*", set the variable elemProps equal
to elem.
Once you know that you have a title element, you can "tag" it by assigning its Type
property.
Set the Type property of elemProps to "Title".
To finish, for cases when the element is not the title, write an ElseIf statement that
tests for the string "*text*" in the element's Text property, then set the Type property
to "Cartographer".
Now that you have "tagged" the two text elements, you can use the element's Type
property to assign a title to your map.
gc
as IGraphicsContainer
as String
mapName
The code will be somewhat similar to the map frame function you just wrote, so you can
borrow from it.
Copy the code from your returnMapFrame function and paste it into your
UpdateTitle sub procedure.
Modify your sub procedure's code just as you did in the previous step so it looks like
the following:
gc.Reset()
Dim elem As IElement
12-10
Exercise 12A
From your TagTheElements sub procedure, copy the following declarations and paste
them into your UpdateTitle sub procedure:
Dim txtElem As ITextElement
Dim elemProps As IElementProperties3
Insert and complete the following code after the line that checks for TypeOf:
txtElem = elem
elemProps = ________
If elemProps.Type = "Title" Then
txtElem.________ = mapName
End If
For the final two lines within your "Title" If statement, call the UpdateElement
method on gc, passing txtElem as the argument, then exit the loop.
Navigate to the Click event of btnAddMap.
After the line of code that calls mapCopy.Overwrite, complete the following code to
call the two sub procedures you just wrote:
TagTheElements(____)
UpdateTitle(____, map.________)
12-11
For a PageLayoutControl, this export frame is always the height and width of the page in
device units (pixels) when the layout is zoomed to 100%. Because these values always
correspond to the page instead of the full client area of the application, they are ideal for
use when you want to export a map to a graphics file.
12-12
Exercise 12A
To prepare for the export, you will need to create an envelope that holds the extent of the
map that you want to export.
Instantiate env as a new Envelope.
Call the PutCoords method on your envelope object.
Use the inline help as a guide for passing the appropriate properties from expFrame as
the arguments.
Your Kauai, HI map contains two special characters (a space and a comma) in its name.
It is good practice to avoid special characters in file names, so you will remove those
characters.
Enter the following code to call the Visual Studio Replace function to substitute an
empty string for the comma and space combination:
mapName = Replace(mapName, ", ", "")
In the Desktop Help for .NET (VS2008), view the help for the IExport interface.
Question 9: On which OMD will you find this interface? How many export formats does
IExport support?
______________________________________________________________________
The help for IExport refers to a sample that illustrates how to export to JPEG format. At
the conclusion of this exercise, if you have time, explore the sample code. For now, you
will continue writing your code.
Complete the following code to instantiate ExportPDF:
Dim expPDF As ______________ = New ExportPDF
12-13
Property
Value
ExportFileName
PixelBounds
env
Resolution
300
Call the StartExporting method on your export variable and return the result in hDC.
The StartExporting method allocates memory for the export. Once this method has
been called, the export object is ready to receive drawing instructions.
Complete the following code to complete the export:
activeView.Output(______, 300, ________________, Nothing, Nothing)
expPDF.______________________________()
Add a message box to notify you when the process has completed.
In the Click event of your btnAddMap, after the call to Refresh, call your Export sub
procedure.
Build and run your project.
Click Add Map button and wait for the message box to appear.
Click OK.
Open the PDF file you created.
When you are finished, close your application and PDF file.
12-14
Exercise 12A
You have finished this exercise; however, you may wish to complete the optional step
and Challenges:
Step 9 shows you how to update the scale bar units on the layout.
The first Challenge tests your ability to modify the second text element in the
layout.
The second Challenge tests your ability to update layouts for all three maps in
your map document.
If you want to complete one or more of these, do so now. Otherwise, close Visual
Studio.
Step 9: (Optional) Associate the units from your map with the
scale bar
Currently, your scale bar designates the units as unknown. When you work with data in
ArcMap, each data frame (or map) has a spatial reference including the units associated
with it. In this step, you will determine the units of your map and use them to label your
scale bar.
Create a new sub procedure named UpdateUnits that accepts two arguments: gc as
IGraphicsContainer and map as IMap.
Some of the code will be similar to code that you have already written.
To save time, copy the code from your UpdateTitle sub procedure to UpdateUnits,
then modify the code in your UpdateUnits sub procedure to match the following:
gc.Reset()
Dim elem As IElement
Dim surFrame As IMapSurroundFrame
Dim sBar As __________________
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
elem = gc.Next
Loop
Instead of checking for ITextElement, you will now determine whether you have a
surround frame.
Inside your Do Until loop, check whether elem is a type of IMapSurroundFrame.
Use your knowledge of inheritance to assign surFrame as the element.
12-15
Complete the following code to test whether the name of your map surround is the
name of a scale bar:
If surFrame.______________________.________ Like "*Scale Bar*" Then
sBar = surFrame.______________________
sBar.__________ = map.MapUnits
gc.UpdateElement(________________)
Exit Do
End If
Conclusion
Map elements and map surrounds provide meaningful information about your map. A
programmer does not usually create a layout using code. Typically, it is the cartographer
or map technician who manually creates one or more detailed layout templates. As a
12-16
Exercise 12A
Earlier in this exercise, you discovered that the layout template contains two text
elements. You have already updated the title text element on the layout.
To complete this Challenge, update the second text element with your name.
One advantage of updating layouts in code is that you can update more than one map in a
single process. You learned how to access each map in a map document in a previous
lesson.
To complete this Challenge, modify your code to loop through all the maps in your
map document and process the layout for each map.
Tip: To make your code more efficient and less cluttered, begin your loop after all the
variable declarations.
12-17
12-18
Exercise 12A
Question 9: On which OMD will you find this interface? How many export formats does
IExport support?
Answer: ESRI.ArcGIS.Output (OutputObjectModel.pdf); 10
Question 10: What type of scale bar is in the map surround frame?
Answer: Double alternating scale bar
12-19
ESRI.ArcGIS.Carto
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Display
ESRI.ArcGIS.Geometry
ESRI.ArcGIS.Output
12-20
Exercise 12A
12-21
12-22
Exercise 12A
12-23
gc As IGraphicsContainer = AxPageLayoutControl1.PageLayout
map As IMap
mFrame As IMapFrame
mapCopy As IObjectCopy
Dim i As Integer
For i = 0 To mapDoc.MapCount - 1
map = mapDoc.Map(i)
mFrame = returnMapFrame(gc)
mapCopy = New ObjectCopy
'mapCopy = New ObjectCopyClass
mapCopy.Overwrite(map, mFrame.Map)
TagTheElements(gc)
UpdateTitle(gc, map.Name)
UpdateUnits(gc, map) ' Optional step
UpdateElement(gc, map.Name) ' Challenge step
AxPageLayoutControl1.Refresh()
Export(map.Name)
Next
End Sub
12-24
Exercise 12B
Exercise shortcut
1. In ArcMap, open an existing template from \Student\IPAN\Database\Templates
folder. Modify the template in layout view and save it as MyTemplates.mxt.
2. In Visual Studio, create a new Visual C# Windows Forms Application. Add a
PageLayoutControl, ToolbarControl, and LicenseControl to the form.
3. Load MyTemplates.mxt template into your PageLayoutControl.
4. Load the first map in the map document into your PageLayoutControl from
\Student\IPAN\Exercise12\MapsAndLayers.mxd.
5. Programmatically loop though the elements in the template and find the map
frame. Overwrite the default map with your new template.
6. Loop through the elements to find the two text elements, then tag these two with
an appropriate identifier.
7. Use the tag you just created to find the current map title and modify it.
8. Export the active view of your layout to a PDF file.
** (Optional) Associate the units from your map with the scale bar.
** (Challenge) Modify the second text element with your name.
** (Challenge) Loop through all the maps in your map document and process the
layout for each map.
12-25
Double-click the title text element at the top of the layout page (shown below).
The properties for the text element display. If you wanted to work with this template in
ArcMap, you could edit the title here manually, but you will automate the process using
code.
Close the Properties dialog box.
Using the Zoom In tool
center of the layout page.
Note: Be sure to use the tool on the Layout toolbar, not the Tools toolbar.
12-26
Exercise 12B
You will also modify this text element later in this exercise. You will need to devise a
strategy to distinguish between this text element and the title text element.
Close the Properties dialog box.
Locate the scale bar element above the text element.
The text "Unknown Units" displays as part of the scale bar.
Double-click the scale bar to display its properties.
Notice that this is a double alternating scale bar.
Question 1: On the Scale and Units tab, how many times do you see "Unknown Units"?
What units does this refer to?
______________________________________________________________________
Note this information for future reference you will need to modify the units later in this
exercise.
Close the scale bar's Properties dialog box.
Move to the lower-left corner in the layout page.
On the Layout toolbar, click the Zoom Whole Page button
When you load your template in a later step, it will display at this extent.
From the File menu, choose Save As.
In the Save As dialog box, specify the following:
12-27
Close ArcMap.
Now that your are familiar with your template, you can begin writing code for it.
Property
Value
Language
Visual C#
Project type
Windows
Template
Name
PageLayout
Location
\Student\IPAN\Exercise12
Solution name
PageLayout
Make sure the box for Create directory for solution is checked.
PageLayoutControl
ToolbarControl
LicenseControl
Open the Properties dialog box for the ToolbarControl and do the following:
12-28
Exercise 12B
12-29
Property
Value
Text
Add Map
(Name)
btnAddMap
as IMap
mFrame as IMapFrame
mapCopy as IObjectCopy
param as object
map
Next, you need to specify which map (data frame) you want to access.
Set map to point to the first map in your map document.
Build your project.
12-30
Exercise 12B
In the next few steps, you will overwrite some of the elements on your template with
values specific to your map. You will pass gc as an argument to those methods.
12-31
After the code that assigns the first map, complete the following code to call your
returnMapFrame method, passing gc as the argument:
mFrame = ____________________(__);
In a previous exercise, you used the IObjectCopy interface to copy a map from a
MapControl to a PageLayoutControl. In this exercise, you will use IObjectCopy to
overwrite the default map template with your custom template.
Instantiate a new instance of ObjectCopy in your variable mapCopy.
Set param equal to mFrame.Map.
Locate IObjectCopy in the Visual Studio Object Browser.
Question 4: How many members does it have? Which method of IObjectCopy will you
use to overwrite the map frame in the center of your template? How is the second
argument passed to Overwrite?
______________________________________________________________________
Call this method on mapCopy to copy your map, passing map and param as arguments.
Build your project, then run it.
Test the Add Map button.
The first map in MapsAndLayers.mxd replaces the default map frame on your template.
Close your application.
12-32
Exercise 12B
For a single map, this code would solve your dilemma. However, if you are creating more
than one map, the title will change. A different solution is to assign a unique type
(analogous to a tag) to each text element.
Insert a new method called tagTheElements that accepts the argument gc as
IGraphicsContainer.
Copy the code from your returnMapFrame function and paste it into your
tagTheElements function.
Collapse the returnMapFrame function.
Modify your code so it looks like the following:
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
while (elem != null)
{
if (elem is ITextElement)
}
elem = gc.Next();
After the declaration and assignment for IElement, declare txtElem as ITextElement
and elemProps as IElementProperties3.
Inside the if statement, complete the following code to assign a value to txtElem:
txtElem = ________ as ITextElement;
Once you know that you have a title element, you can "tag" it by assigning its Type
property.
Inside your if statement, set elemProps equal to elem.
Then, set the Type property of elemProps to "Title".
12-33
To finish, for cases when the element is not the title, write code that tests whether the
element's Text property contains "text" and, if it does, set the Type property to
"Cartographer".
Now that you have "tagged" the two text elements, you can use the element's Type
property to assign a title to your map.
as IGraphicsContainer
mapName as string
gc
The code will be somewhat similar to the map frame method you wrote earlier, so you
can borrow from it.
Copy the code from your returnMapFrame method and paste it into your
UpdateTitle function.
Delete the return statements.
You want to test whether the element is a type of ITextElement, so make that change
to your code, then delete the return statements.
Just as you did earlier for the map frame, you will need to loop through the elements to
locate the title text element. When you explored the template, you discovered that it
contains more than one text element. You will need to determine whether you have found
the title element.
One way to identify the title element is to examine its Type property and search for a
unique keyword, such as in the following code:
if (elemProps.Type.Equals("Title"))
12-34
Exercise 12B
As the final line within your if statement, call the UpdateElement method on gc,
passing txtElem as the argument.
Navigate to the Click event of btnAddMap.
After the line of code that calls mapCopy.Overwrite, complete the following code to
call the two methods you just wrote:
tagTheElements(____);
UpdateTitle(____, map.________);
12-35
For a PageLayout, this export frame is always the height and width of the page in device
units (pixels) when the layout is zoomed to 100%. Because these values always
correspond to the page instead of the full client area of the application, they are ideal for
use when you want to export a map to a graphics file.
To prepare for the export, you will need to create an envelope that holds the extent of the
map that you want to export.
Instantiate env as a new EnvelopeClass.
Call the PutCoords method on your envelope object.
Use the inline help as a guide for passing the appropriate properties from expFrame as
the arguments.
Your Kauai, HI map contains two special characters (a space and a comma) in its name.
It is good practice to avoid special characters in file names, so you will remove those
characters.
Enter the following code to call the Visual Studio Replace function to substitute an
empty string for the comma and space:
mapName = mapName.Replace(", ", "");
12-36
Exercise 12B
In the Desktop Help for .NET (VS2008), view the help for the IExport interface.
Question 7: On which OMD will you find this interface? How many export formats does
IExport support?
______________________________________________________________________
The help for IExport refers to a sample that illustrates how to export to JPEG format. At
the conclusion of this exercise, if you have time, explore the sample code. For now, you
will continue writing your code.
Complete the following code to instantiate ExportPDFClass:
______________ expPDF = new ExportPDFClass() as ______________;
Property
Value
ExportFileName
"\\Student\\IPAN\\Exercise12\\" + mapName +
".PDF"
PixelBounds
env
Resolution
300
Call the StartExporting method on your export variable and return the result in hDC.
The StartExporting method allocates memory for the export. Once this method has
been called, the export object is ready to receive drawing instructions.
Complete the following code to complete the export:
activeView.Output(______, 300, ______ ________________, null, null);
expPDF._____________________________();
Add a message box to notify you when the process has completed.
12-37
In the Click event of your btnAddMap, call the Export method after you refresh the
layout.
Build and run your project.
Click Add Map button and wait for the message box to appear.
Click OK.
Open the PDF file you created.
When you are finished, close your application and PDF file.
You have finished this exercise; however, you may wish to complete the optional step
and Challenges:
Step 9 shows you how to update the scale bar units on the layout.
The first Challenge tests your ability to modify the second text element in the
layout.
The second Challenge tests your ability to update layouts for all three maps in
your map document.
If you want to complete one or more of these, do so now. Otherwise, close Visual
Studio.
Step 9: (Optional) Associate the units from your map with the
scale bar
Currently, your scale bar designates the units as unknown. When you work with data in
ArcMap, each data frame (or map) has a spatial reference including the units associated
with it. In this step, you will determine the units of your map and use them to label your
scale bar.
Create a new method named UpdateUnits that accepts two arguments: gc as
IGraphicsContainer and map as IMap.
Some of the code will be similar to code that you have already written.
To save time, copy the code from your UpdateTitle method to UpdateUnits, then
modify the code in your UpdateUnits method to match the following:
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
12-38
Exercise 12B
Instead of checking for ITextElement, you will now determine whether you have a
surround frame.
After the declaration for IElement, declare the variable surFrame as
IMapSurroundFrame and sBar as IScaleBar.
Inside your while loop, check whether elem is IMapSurroundFrame.
Use your knowledge of inheritance to assign surFrame as the element.
Complete the following code to test whether the name of your map surround is the
name of a scale bar:
if (elem is IMapSurroundFrame)
{
surFrame = elem as IMapSurroundFrame;
sBar = surFrame.Object as _____________;
sBar.__________ = map.MapUnits;
gc.UpdateElement(________________ as ____________________);
break;
}
12-39
Conclusion
Map elements and map surrounds provide meaningful information about your map. A
programmer does not usually create a layout using code. Typically, it is the cartographer
or map technician who manually creates one or more detailed layout templates. As a
programmer, however, you can automate map production processes by associating a
layout with a map or a collection of maps and then updating elements such as the title,
other text, and scale bar.
You have already updated the title text element on the layout. In the first step, you
discovered that the layout template contains two text elements.
To complete this Challenge, update the second text element with your name.
One advantage of updating layouts in code is that you can update more than one map in a
single process. You learned how to access each map in a map document in a previous
lesson.
To complete this Challenge, modify your code to loop through all the maps in your
map document and process the layout for each map.
12-40
Exercise 12B
Tip: To make your code more efficient and less cluttered, begin your loop after all the
variable declarations.
12-41
12-42
Exercise 12B
System;
System.Collections.Generic;
System.ComponentModel;
System.Data;
System.Drawing;
System.Text;
System.Windows.Forms;
using
using
using
using
using
ESRI.ArcGIS.Carto;
ESRI.ArcGIS.esriSystem;
ESRI.ArcGIS.Geometry;
ESRI.ArcGIS.Output;
ESRI.ArcGIS.Display;
namespace PageLayout
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string fName = "\\Student\\IPAN\\Database\\Templates\\MyTemplate.mxt";
axPageLayoutControl1.LoadMxFile(fName);
}
private void btnAddMap_Click(object sender, EventArgs e)
{
string mName = "\\Student\\IPAN\\Exercise12\\MapsAndLayers.mxd";
IMapDocument mapDoc = new MapDocumentClass();
mapDoc.Open(mName, "");
IGraphicsContainer gc =
axPageLayoutControl1.PageLayout as IGraphicsContainer;
IMap map;
IMapFrame mFrame;
IObjectCopy mapCopy;
object param;
map = mapDoc.get_Map(0);
mFrame = returnMapFrame(gc);
mapCopy = new ObjectCopyClass();
param = mFrame.Map;
mapCopy.Overwrite(map, ref param);
tagTheElements(gc);
UpdateTitle(gc, map.Name);
UpdateUnits(gc, map); // Optional step
12-43
axPageLayoutControl1.Refresh();
}
Export(map.Name);
12-44
Exercise 12B
12-45
}
// End optional step
}
12-46
Exercise 12B
12-47
12-48
Export(map.Name);
A
ESRI data license
agreement
Appendix A
A-1
Permitted Uses:
Licensee may run the setup and install one (1) copy of the Training Course onto a permanent
electronic storage device and reproduce one (1) copy of the Training Course and/or any online
documentation in hard-copy format for Licensee's own personal use only.
Licensee may use one (1) copy of the Training Course on a single processing unit.
Licensee may make only one (1) copy of the original Training Course for archival purposes during
the term of this Agreement, unless the right to make additional copies is granted to Licensee in
writing by ESRI.
Licensee may use the Training Course provided by ESRI for the stated purpose of Licensee's own
personal GIS training and education.
Licensee shall not sell, rent, lease, sublicense, lend, assign, time-share, or transfer, in whole or in part,
or provide unlicensed third parties access to the Training Course, any updates, or Licensee's rights
under this Agreement.
Licensee shall not separate the component parts of the Training Course for use on more than one (1)
computer, used in conjunction with any other software package, and/or merged and compiled into a
separate database(s) for other analytical uses.
Licensee shall not reverse engineer, decompile, or disassemble the Training Course, except and only
to the extent that such activity is expressly permitted by applicable law notwithstanding this
restriction.
Licensee shall not make any attempt to circumvent the technological measure(s) (e.g., software or
hardware key) that effectively controls access to the Training Course, except and only to the extent
that such activity is expressly permitted by applicable law notwithstanding this restriction.
Licensee shall not remove or obscure any copyright, trademark, and/or proprietary rights notices of
ESRI or its licensor(s).
Term: The license granted by this Agreement shall commence upon Licensee's receipt of the Training Course
and shall continue until such time that (1) Licensee elects to discontinue use of the Training Course and
terminates this Agreement or (2) ESRI terminates for Licensee's material breach of this Agreement. The
Agreement shall automatically terminate without notice if Licensee fails to comply with any provision of this
Agreement. Upon termination of this Agreement in either instance, Licensee shall return to ESRI or destroy
all copies of the Training Course, and any whole or partial copies, in any form and deliver evidence of such
destruction to ESRI, which evidence shall be in a form acceptable to ESRI in its sole discretion. The parties
hereby agree that all provisions that operate to protect the rights of ESRI and its licensor(s) shall remain in
force should breach occur.
Limited Warranty and Disclaimer: ESRI warrants that the media upon which the Training Course is
provided will be free from defects in materials and workmanship under normal use and service for a period of
ninety (90) days from the date of receipt.
EXCEPT FOR THE LIMITED WARRANTY SET FORTH ABOVE, THE TRAINING COURSE
CONTAINED THEREIN IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND, EITHER
A-2
Appendix A
EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. ESRI
DOES NOT WARRANT THAT THE TRAINING COURSE WILL MEET LICENSEE'S NEEDS OR
EXPECTATIONS; THAT THE USE OF THE TRAINING COURSE WILL BE UNINTERRUPTED; OR
THAT ALL NONCONFORMITIES, DEFECTS, OR ERRORS CAN OR WILL BE CORRECTED. THE
TRAINING DATABASE HAS BEEN OBTAINED FROM SOURCES BELIEVED TO BE RELIABLE,
BUT ITS ACCURACY AND COMPLETENESS, AND THE OPINIONS BASED THEREON, ARE NOT
GUARANTEED. THE TRAINING DATABASE MAY CONTAIN SOME NONCONFORMITIES,
DEFECTS, ERRORS, AND/OR OMISSIONS. ESRI AND ITS LICENSOR(S) DO NOT WARRANT THAT
THE TRAINING DATABASE WILL MEET LICENSEE'S NEEDS OR EXPECTATIONS, THAT THE
USE OF THE TRAINING DATABASE WILL BE UNINTERRUPTED, OR THAT ALL
NONCONFORMITIES CAN OR WILL BE CORRECTED. ESRI AND ITS LICENSOR(S) ARE NOT
INVITING RELIANCE ON THIS TRAINING DATABASE, AND LICENSEE SHOULD ALWAYS
VERIFY ACTUAL DATA, WHETHER MAP, SPATIAL, RASTER, TABULAR INFORMATION, AND
SO FORTH. THE DATA CONTAINED IN THIS PACKAGE IS SUBJECT TO CHANGE WITHOUT
NOTICE.
Exclusive Remedy and Limitation of Liability: During the warranty period, Licensee's exclusive
remedy and ESRI's entire liability shall be the return of the license fee paid for the Training Course upon the
Licensee's deinstallation of all copies of the Training Course and providing a Certification of Destruction in a
form acceptable to ESRI.
IN NO EVENT SHALL ESRI OR ITS LICENSOR(S) BE LIABLE TO LICENSEE FOR COSTS OF
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOST SALES OR
BUSINESS EXPENDITURES, INVESTMENTS, OR COMMITMENTS IN CONNECTION WITH ANY
BUSINESS, LOSS OF ANY GOODWILL, OR FOR ANY INDIRECT, SPECIAL, INCIDENTAL, AND/OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT OR USE OF THE TRAINING
COURSE, HOWEVER CAUSED, ON ANY THEORY OF LIABILITY, AND WHETHER OR NOT ESRI
OR ITS LICENSOR(S) HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THESE
LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
ANY LIMITED REMEDY.
No Implied Waivers: No failure or delay by ESRI or its licensor(s) in enforcing any right or remedy under
this Agreement shall be construed as a waiver of any future or other exercise of such right or remedy by ESRI
or its licensor(s).
Order for Precedence: This Agreement shall take precedence over the terms and conditions of any
purchase order or other document, except as required by law or regulation.
Export Regulation: Licensee acknowledges that the Training Course and all underlying information or
technology may not be exported or re-exported into any country to which the U.S. has embargoed goods, or to
A-3
anyone on the U.S. Treasury Department's list of Specially Designated Nationals, or to the U.S. Commerce
Department's Table of Deny Orders. Licensee shall not export the Training Course or any underlying
information or technology to any facility in violation of these or other applicable laws and regulations.
Licensee represents and warrants that it is not a national or resident of, or located in or under the control of,
any country subject to such U.S. export controls.
Severability: If any provision(s) of this Agreement shall be held to be invalid, illegal, or unenforceable by a
court or other tribunal of competent jurisdiction, the validity, legality, and enforceability of the remaining
provisions shall not in any way be affected or impaired thereby.
Governing Law: This Agreement, entered into in the County of San Bernardino, shall be construed and
enforced in accordance with and be governed by the laws of the United States of America and the State of
California without reference to conflict of laws principles.
Entire Agreement: The parties agree that this Agreement constitutes the sole and entire agreement of the
parties as to the matter set forth herein and supersedes any previous agreements, understandings, and
arrangements between the parties relating hereto.
A-4
B
Suggested reading
Appendix B
Reading list
1.
2.
C# How to Program
H.M. Deitel, P. J. Deitel, J. Listfield, T.R. Nieto, C. Yaeger, M. Zlatkina. Prentice
Hall.
3.
4.
5.
6.
B-1
C
Additional information
Appendix C
Additional information
What is e?
In a few of the exercises, you worked with events. Some of the events passed a variable e
that you accessed. You learned that the value of e varied, depending on the event.
Private Sub axMapControl1_OnMouseMove(ByVal sender As Object, _
ByVal e As IMapControlEvents2_OnMouseMoveEvent) _
Handles axMapControl1.OnMouseMove
The mapX and mapY properties of e return coordinates in map units. The x and y
properties of e return coordinates in display units.
Coding tip
After typing the first few characters of a variable that you have already declared, press
CTRL+SPACEBAR for the code completer. If the variable name is unique, the code
completer will finish the variable. If the sequence of characters is not unique, a code
completion list will appear.
Help resources
The resources on your computer may vary depending on which developer kit(s) you have
installed.
C-1
With the ArcGIS Snippet Finder, you can find and insert ArcGIS snippets into a Visual
Studio 2008 project using keyword searches.
To find lists of useful keyboard shortcuts, search the Microsoft Download Center for:
You can unregister a DLL sample from your machine when you are finished using it. To
unregister a DLL, use the Assembly Registration Tool (regasm.exe) with the command
line flag /unregister.
From your Start menu, click Run. In the Run dialog box, type cmd (Start > Run >
cmd).
In the Command Window:
Type cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.xxxxx
(where
xxxxx
C-2
E
Extend ArcGIS
Desktop with a custom
tool (VB.NET)
Appendix E
Property
Value
Language
Visual Basic
Project type
Template
Name
Customize
Location
\Student\IPAN\Extras
Solution name
Customize
Make sure the Create directory for solution check box is checked.
When you create a new project using an ArcGIS Project template, the ArcGIS Project
Wizard opens automatically to help you add ArcGIS references to the project. In this
case, however, you will add the necessary ArcGIS references in a later step.
Click Finish on the ArcGIS Project Wizard.
E-1
Categories: ArcGIS
Templates: Base Command
Name: myExtent.vb
Click Add.
In the ArcGIS New Item Wizard Options dialog box, select Desktop ArcMap
Command and then click OK.
In the myExtent.vb code window, notice that most of the plumbing code has been
automatically generated for you:
E-2
Appendix E
Notice that the <ComClass> attributes and the COM GUIDs region are automatically
added to the class for you when using the COM class template. The GUIDs provide the
COM identity for the class you just added and its COM interfaces.
Collapse the region when you are finished.
The ProgID is determined in a logical way: from the Project Name and the Class Name.
In this case, the Customize.DLL is implemented in a project named Customize and has
one class called myExtent. Therefore, the ProgID is Customize.myExtent.
Finally, notice how the class is set to inherit from BaseCommand abstract class.
Inheriting the BaseCommand allows you to create commands more easily.
Save the solution.
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Geometry
ESRI.ArcGIS.SystemUI
Note: To know more about these libraries, see the Desktop Help for .NET (VS2008).
Click Finish.
At the top of the code window, before the beginning of the class declaration, add all
the references that you imported in your code.
E-3
When you created a Base Command in the previous step, a bitmap was also added by
default to your project. While you could use this bitmap as the icon for your custom
command, in this case, you will use a specific icon from your ArcGIS\Bin\Icons directory
instead.
In the Solution Explorer, right-click myExtent.bmp and choose Delete. Click OK on
the message box.
Now right-click the Customize project and click Add > Existing Item.
At the bottom of the Add Existing Item dialog box, open the Objects of type
drop-down list and choose Image Files.
Navigate to your \Program Files\ArcGIS\Bin\Icons directory, select
zoom_in_tool_1.bmp and click Add.
In the Solution Explorer, right-click zoom_in_tool_1.bmp and choose Properties.
In the Properties window, open the Build Action drop-down list and choose Embedded
Resource, as shown below.
E-4
Appendix E
E-5
The Added Objects dialog box indicates that one new object, myExtent, was added to the
document.
Click OK to dismiss the Added Objects dialog box.
In the Customize dialog box, locate your control (My Extent Command) in the Extent
Commands category.
E-6
Appendix E
Title: ILDASM
Command: ...\Program Files\Microsoft SDKs\Windows\v6.0A\bin\ildasm.exe
Click OK.
Now you are ready to use ILDASM.
From the Tools menu, choose ILDASM.
In ILDASM, click File > Open.
Navigate to Customize.DLL and click Open.
Explore the metadata and the Intermediate Language code for your DLL.
Close ILDASM.
E-7
In this step, you will access the Component Category Manager, a utility that allows you
to add or remove classes from any component category.
In Windows Explorer, navigate to \Program Files\ArcGIS\Bin and double-click
categories.exe.
In the Component Category Manager, scroll down and expand ESRI MX Commands.
The Component Category Manager searches the registry and lists all the classes
registered to the ESRI MX Commands category.
Notice that Customize.myExtent is in this category. This is the DLL that you registered
with ArcMap.
If you want to remove the DLL from your ArcMap application, click
Customize.myExtent to select it and then click Remove Object.
In the message box that appears, click Yes to confirm that you wish to delete the object
permanently.
Click Exit.
You have completed this exercise.
Conclusion
In this exercise, you created a command by inheriting from the BaseCommand class. You
added some code so that the command would zoom a map to a specific extent of a
E-8
Appendix E
selected layer in ArcMap. You then used ILDASM to explore the metadata and the
Intermediate Language code of your DLL. Finally, you learned how to use the
Component Category Manager to add or remove objects from ArcMap.
E-9
F
Extend ArcGIS
Desktop with a custom
tool (C#)
Appendix F
Property
Value
Language
Visual C#
Project type
Template
Name
Customize
Location
\Student\IPAN\Extras
Solution name
Customize
Make sure the Create directory for solution check box is checked.
When you create a new project using an ArcGIS Project template, the ArcGIS Project
Wizard opens automatically to help you add ArcGIS references to the project. In this
case, however, you will add the necessary ArcGIS references in a later step.
Click Finish on the ArcGIS Project Wizard.
F-1
Categories: ArcGIS
Templates: Base Command
Name: myExtent.cs
Click Add.
In the ArcGIS New Item Wizard Options dialog box, select Desktop ArcMap
Command and then click OK.
In the myExtent.cs code window, notice that most of the plumbing code has been
automatically generated for you:
The GUIDs are automatically added to the class for you when using the COM class
template. The GUIDs provide the COM identity for the class you just added and its COM
interfaces. The ProgID is determined in a logical way: from the Project Name and the
Class Name. In this case, the Customize.DLL is implemented in a project named
F-2
Appendix F
Customize and has one class called myExtent. Therefore, the ProgID is
Customize.myExtent.
Finally, notice how the class is set to inherit from BaseCommand abstract class.
Inheriting the BaseCommand allows you to create commands more easily.
Save the solution.
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Geometry
ESRI.ArcGIS.SystemUI
Note: To know more about these libraries, see the Desktop Help for .NET (VS2008).
Click Finish.
At the top of the code window, before the beginning of the class declaration, add all
the references that you imported in your code.
F-3
When you created a Base Command in the previous step, a bitmap was also added by
default to your project. While you could use this bitmap as the icon for your custom
command, in this case, you will use a specific icon from your ArcGIS\Bin\Icons directory
instead.
In the Solution Explorer, right-click myExtent.bmp and choose Delete. Click OK on
the message box.
Now right-click the Customize project and click Add > Existing Item.
At the bottom of the Add Existing Item dialog box, open the Objects of type
drop-down list and choose Image Files.
Navigate to your \Program Files\ArcGIS\Bin\Icons directory, select
zoom_in_tool_1.bmp and click Add.
In the Solution Explorer, right-click zoom_in_tool_1.bmp and choose Properties.
In the Properties window, open the Build Action drop-down list and choose Embedded
Resource, as shown below.
F-4
Appendix F
F-5
The Added Objects dialog box indicates that one new object, myExtent, was added to the
document.
Click OK to dismiss the Added Objects dialog box.
In the Customize dialog box, locate your control (My Extent Command) in the Extent
Commands category.
F-6
Appendix F
Title: ILDASM
Command: ...\Program Files\Microsoft SDKs\Windows\v6.0A\bin\ildasm.exe
Click OK.
Now you are ready to use ILDASM.
From the Tools menu, choose ILDASM.
In ILDASM, click File > Open.
Navigate to Customize.DLL and click Open.
Explore the metadata and the Intermediate Language code for your DLL.
Close ILDASM.
F-7
In this step, you will access the Component Category Manager, a utility that allows you
to add or remove classes from any component category.
In Windows Explorer, navigate to \Program Files\ArcGIS\Bin and double-click
categories.exe.
In the Component Category Manager, scroll down and expand ESRI MX Commands.
The Component Category Manager searches the registry and lists all the classes
registered to the ESRI MX Commands category.
Notice that Customize.myExtent is in this category. This is the DLL that you registered
with ArcMap.
If you want to remove the DLL from your ArcMap application, click
Customize.myExtent to select it and then click Remove Object.
In the message box that appears, click Yes to confirm that you wish to delete the object
permanently.
Click Exit.
You have completed this exercise.
Conclusion
In this exercise, you created a command by inheriting from the BaseCommand class. You
added some code so that the command would zoom a map to a specific extent of a
F-8
Appendix F
selected layer in ArcMap. You then used ILDASM to explore the metadata and the
Intermediate Language code of your DLL. Finally, you learned how to use the
Component Category Manager to add or remove objects from ArcMap.
F-9