0% found this document useful (0 votes)
453 views

Introduction To Programming Arcobjects U

enjoy

Uploaded by

BatzolbooBataa
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
453 views

Introduction To Programming Arcobjects U

enjoy

Uploaded by

BatzolbooBataa
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 539

Introduction to

Programming
TM
ArcObjects Using the

Microsoft .NET
Framework

Copyright 2001-2009 ESRI


All rights reserved.
Course version 2.1. Revised April 2009.
Printed in the United States of America.
The information contained in this document is the exclusive property of ESRI. This work is protected under United States copyright law
and other international copyright treaties and conventions. No part of this work may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying and recording, or by any information storage or retrieval system, except as
expressly permitted in writing by ESRI. All requests should be sent to Attention: Contracts and Legal Services Manager, ESRI, 380 New
York Street, Redlands, CA 92373-8100 USA.
The information contained in this document is subject to change without notice.

U. S. GOVERNMENT RESTRICTED/LIMITED RIGHTS


Any software, documentation, and/or data delivered hereunder is subject to the terms of the License
Agreement. In no event shall the U.S. Government acquire greater than RESTRICTED/LIMITED RIGHTS. At
a minimum, use, duplication, or disclosure by the U.S. Government is subject to restrictions as set forth in FAR
52.227-14 Alternates I, II, and III (JUN 1987); FAR 52.227-19 (JUN 1987) and/or FAR 12.211/12.212
(Commercial Technical Data/Computer Software); and DFARS 252.227-7015 (NOV 1995) (Technical Data)
and/or DFARS 227.7202 (Computer Software), as applicable. Contractor/Manufacturer is ESRI, 380 New
York Street, Redlands, CA 92373-8100 USA.
@esri.com, 3D Analyst, ACORN, Address Coder, ADF, AML, ArcAtlas, ArcCAD, ArcCatalog, ArcCOGO, ArcData, ArcDoc, ArcEdit,
ArcEditor, ArcEurope, ArcExplorer, ArcExpress, ArcGIS, ArcGlobe, ArcGrid, ArcIMS, ARC/INFO, ArcInfo, ArcInfo Librarian,
ArcInfoProfessional GIS, ArcInfoThe World's GIS, ArcLessons, ArcLocation, ArcLogistics, ArcMap, ArcNetwork, ArcNews,
ArcObjects, ArcOpen, ArcPad, ArcPlot, ArcPress, ArcQuest, ArcReader, ArcScan, ArcScene, ArcSchool, ArcScripts, ArcSDE, ArcSdl,
ArcSketch, ArcStorm, ArcSurvey, ArcTIN, ArcToolbox, ArcTools, ArcUSA, ArcUser, ArcView, ArcVoyager, ArcWatch, ArcWeb,
ArcWorld, ArcXML, Atlas GIS, AtlasWare, Avenue, Business Analyst Online, BusinessMAP, CommunityInfo, Data Automation Kit,
Database Integrator, DBI Kit, EDN, ESRI, ESRI BIS, ESRITeam GIS, ESRIThe GIS Company, ESRIThe GIS People, ESRIThe
GIS Software Leader, FormEdit, GeoCollector, Geographic Design System, Geography Matters, Geography Network, GIS by ESRI, GIS
Data ReViewer, GIS Day, GIS for Everyone, GISData Server, JTX, MapBeans, MapCaf, MapData, MapObjects, Maplex, MapStudio,
ModelBuilder, MOLE, MPS-Atlas, NetEngine, PC ARC/INFO, PC ARCPLOT, PC ARCSHELL, PC DATA CONVERSION, PC
STARTER KIT, PC TABLES, PC ARCEDIT, PC NETWORK, PC OVERLAY, PLTS, Rent-a-Tech, RouteMAP, SDE, SiteReporter,
SML, SourcebookAmerica, Spatial Database Engine, StreetEditor, StreetMap, Tapestry, the ARC/INFO logo, the ArcAtlas logo, the
ArcCAD logo, the ArcCAD WorkBench logo, the ArcCOGO logo, the ArcData logo, the ArcData Online logo, the ArcEdit logo, the
ArcEurope logo, the ArcExplorer logo, the ArcExpress logo, the ArcGIS logo, the ArcGIS Explorer logo, the ArcGrid logo, the ArcIMS
logo, the ArcInfo logo, the ArcLogistics Route logo, the ArcNetwork logo, the ArcPad logo, the ArcPlot logo, the ArcPress for ArcView
logo, the ArcPress logo, the ArcScan logo, the ArcScene logo, the ArcSDE CAD Client logo, the ArcSDE logo, the ArcStorm logo, the
ArcTIN logo, the ArcTools logo, the ArcUSA logo, the ArcView 3D Analyst logo, the ArcView Data Publisher logo, the ArcView GIS
logo, the ArcView Image Analysis logo, the ArcView Internet Map Server logo, the ArcView logo, the ArcView Network Analyst logo,
the ArcView Spatial Analyst logo, the ArcView StreetMap 2000 logo, the ArcView StreetMap logo, the ArcView Tracking Analyst logo,
the ArcWorld logo, the Atlas GIS logo, the Avenue logo, the BusinessMAP logo, the Community logo, the Data Automation Kit logo, the
Digital Chart of the World logo, the ESRI Data logo, the ESRI globe logo, the ESRI Press logo, the Geography Network logo, the MapCaf
logo, the MapObjects Internet Map Server logo, the MapObjects logo, the MOLE logo, the NetEngine logo, the PC ARC/INFO logo, the
Production Line Tool Set logo, the RouteMAP IMS logo, the RouteMAP logo, the SDE logo, The Geographic Advantage, The World's
Leading Desktop GIS, Water Writes, www.esri.com, www.esribis.com, www.geographynetwork.com, www.gis.com, www.gisday.com,
and Your Personal Geographic Information System are trademarks, registered trademarks, or service marks of ESRI in the United States,
the European Community, or certain other jurisdictions.
Other companies and products mentioned herein may be trademarks or registered trademarks of their respective trademark owners.

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

Exploring ArcGIS Engine controls

Programming with COM and .NET

Exercise 2: Create your first mapping application


Review the developer help
Create a new project in Visual Studio
Examine and modify your project
Run your project and resolve an error
Navigate your map
Open a map document dynamically
(Optional) Programmatically determine the number of layers in your map

Exercise 3A: Program with COM (VB.NET)


Create a new project in Visual Studio
Add a custom button to your project
Add code to your custom button
Work with the map
Work with the active view
(Optional) Add a MapControl to your project
Exercise 3B: Program with COM (C#)
Create a new project in Visual Studio
Add a custom button to your project
Add code to your custom button

Copyright 2001-2009 ESRI

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

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Work with the map


Work with the active view
(Optional) Add a MapControl to your project

ii

Contents

3-21
3-21
3-23

Understanding object model diagrams


Exercise 4A: Create an ArcObjects application (VB.NET)
Create a new project in Visual Studio
Add controls to your form
Explore ArcGIS Snippet Finder
Add the Snippet to your code
Browse the developer help
Navigate the Geodatabase OMD
Explore the ArcGIS Resource Centers
Make your code work for you
"Do something" with your shapefile
Run your project and check your results

4-1
4-1
4-2
4-3
4-4
4-5
4-6
4-9
4-10
4-11
4-13

Exercise 4B: Create an ArcObjects application (C#)


Create a new project in Visual Studio
Add controls to your form
Explore ArcGIS Snippet Finder
Add the Snippet to your code
Browse the developer help
Navigate the Geodatabase OMD
Explore the ArcGIS Resource Centers
Make your code work for you
"Do something" with your shapefile
Run your project and check your results

4-19
4-19
4-20
4-21
4-23
4-24
4-25
4-28
4-28
4-30
4-32

Working with maps and layers


Exercise 5A: Work with maps and layers (VB.NET)
Open an existing project in Visual Studio
Load a map document programmatically
Test your project
Access the layers in a map
(Optional) Respond to MapControl events
(Optional) Distinguish between feature and raster layers

5-1
5-1
5-3
5-6
5-6
5-11
5-12

Exercise 5B: Work with maps and layers (C#)


Open an existing project in Visual Studio
Load a map document programmatically
Test your project
Access the layers in a map
(Optional) Respond to MapControl events

5-21
5-21
5-23
5-26
5-26
5-31

Copyright 2001-2009 ESRI

Contents

(Optional) Distinguish between feature and raster layers

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

Exercise 6B: Access data with ArcObjects (C#)


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-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

Exercise 7B: Display layers (C#)


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

7-35
7-35
7-36
7-38
7-41
7-43
7-45

Copyright 2001-2009 ESRI

iii

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

(Optional) Apply a stretch renderer to raster data

7-49

Querying and selecting data


Exercise 8A: Queries and selections (VB.NET)
Apply a query filter and loop through a subset of records
Work with spatial and query filters
(Optional) Display a query filter as a selection
Challenge: Open a feature class from a feature workspace

8-1
8-1
8-5
8-9
8-13

Exercise 8B: Queries and selections (C#)


Apply a query filter and loop through a subset of records
Work with spatial and query filters
(Optional) Display a query filter as a selection
Challenge: Open a feature class from a feature workspace

8-21
8-21
8-25
8-29
8-33

Working with geometry

10
iv

Contents

Exercise 9A: Create a parcel proximity tool (VB.NET)


Create a new project in Visual Studio
Create a new point when the map is clicked
Create a spatial filter
Create a cursor and return a feature from it
Test your project
Determine the spatial reference for a geodataset
Buffer the gas station parcel and select neighboring parcels
Remove the gas station parcel from the selection
Challenge: Draw the polygon buffer
Challenge: Use DisplayTransformation

9-1
9-2
9-3
9-4
9-5
9-6
9-7
9-8
9-10
9-12
9-12

Exercise 9B: Create a parcel proximity tool (C#)


Create a new project in Visual Studio
Create a new point when the map is clicked
Create a spatial filter
Create a cursor and return a feature from it
Test your project
Determine the spatial reference for a geodataset
Buffer the gas station parcel and select neighboring parcels
Remove the gas station parcel from the selection
Challenge: Draw the polygon buffer
Challenge: Use DisplayTransformation

9-21
9-22
9-23
9-24
9-25
9-26
9-27
9-28
9-30
9-32
9-32

Creating and editing data


Exercise 10A: Create data (VB.NET)
Create a new project in Visual Studio

10-1
10-1

Copyright 2001-2009 ESRI

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

Exercise 10B: Create data (C#)


Create a new project in Visual Studio
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-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

Exercise 11B: Access the GeoProcessor (C#)


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-27
11-28
11-29
11-30
11-33
11-35
11-38
11-40
11-44

Working with layouts


Exercise 12A: Update and export a layout (VB.NET)
Explore a map template in ArcMap
Create a new project in Visual Studio
Load a map template
Load your map document
Add your map template to the layout

Copyright 2001-2009 ESRI

12-1
12-2
12-4
12-5
12-6
12-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Contents

Tag your elements with a unique type


Modify the map title
Export your layout to a file
(Optional) Associate the units from your map with the scale bar
Challenge: Modify the second text element
Challenge: Create layouts for all maps

12-8
12-10
12-12
12-15
12-17
12-17

Exercise 12B: Update and export a layout (C#)


Explore a map template in ArcMap
Create a new project in Visual Studio
Load a map template
Load your map document
Add your map template to the layout
Tag your elements with a unique type
Modify the map title
Export your layout to a file
(Optional) Associate the units from your map with the scale bar
Challenge: Modify the second text element
Challenge: Create layouts for all maps in the map document

12-25
12-26
12-28
12-29
12-29
12-31
12-32
12-34
12-35
12-38
12-40
12-40

Appendix A: ESRI data license agreement


Appendix B: Suggested reading
Appendix C: Additional information
Appendix D: Extend ArcGIS Desktop with a custom tool (VB.NET)
Appendix E: Extend ArcGIS Desktop with a custom tool (C#)

vi

Copyright 2001-2009 ESRI

1
Introduction

Exercise 1A: Install the course data


Estimated time: 10 minutes
Exercise 1B: Verify the system
requirements for the ArcGIS Engine
Developer Kit
Estimated time: 25 minutes

Exercise 1A

Exercise 1A: Install the course data


Estimated time: 10 minutes
In this exercise, you will install the data that you will use throughout this course. The data
is stored on a CD and will be copied to your hard drive by an automated install program.
After installing the data, you will have the opportunity to create an ESRI Global Account,
which will allow you to access all pages on the ESRI Support Center, a valuable online
technical resource.

Step 1: Record user information


You need to log on to your Windows workstation to install the course data. A unique user
name, password, and domain (if applicable) are required to log on. Your instructor will
provide these to you.
Record the workstation information provided by your instructor in the spaces below.

Workstation user name: ____________________________________


Workstation password: ____________________________________
Workstation domain, if any: ________________________________

Step 2: Log on to Windows


In the Log On to Windows dialog box, enter the workstation user name and password
provided by your instructor.
If your workstation is part of a domain, in the "Log on to" drop-down list, choose the
appropriate domain.
Click OK.
Note: If you have trouble logging on to Windows, ask your instructor for help.

Step 3: Install the data


Now that you are logged on, you can install the course data.
Remove the training data CD from the back of your exercise book and place it in the
CD drive.

Copyright 2001-2009 ESRI

1-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Click Next in the welcome panel.


Click the option to accept the ESRI license agreement, then click Next.
By default, the course data will be installed to the C:\Student folder.
Note: If for some reason you need to install the course data to a different location, click
Change and browse to that location. Select the folder where you want to store the course
data, then click OK. Be sure to note the location of the folder you've selected so that you
can easily access the data in the upcoming exercises.

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.

Step 4: Modify a setting in ArcCatalog


In this step, you will modify a setting in ArcCatalog to explicitly view file extensions.
From your Start menu, choose All Programs > ArcGIS > ArcCatalog to start
ArcCatalog.
From the Tools menu, choose Options.
In the Options dialog box, at the bottom of the General tab, uncheck the Hide file
extensions check box.

1-2

Copyright 2001-2009 ESRI

Exercise 1A

Click OK to apply the change, then close ArcCatalog.

Step 5: (Optional) Create an ESRI Global Account


To access certain pages on the ESRI Support Center Web site, you must log on with an
ESRI Global Account.

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.

Click the Create a new ESRI Global Account link.

Copyright 2001-2009 ESRI

1-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 1B

Exercise 1B: Verify the system requirements for the


ArcGIS Engine Developer Kit
Estimated time: 25 minutes
By default, ArcObjects applications developed using the Microsoft .NET Framework do
not have a visual component (a container for the map). In this course, you will use the
MapControl from the ArcGIS Engine Developer Kit, which will allow you to create
applications that display maps.
Before you begin writing your applications, you will verify the system requirements to
use the ArcGIS Engine Developer Kit, and also configure your development
environment.
In this exercise, you will:

Verify system requirements for the ArcGIS Engine Developer Kit


Import code snippets
Perform software authorization
Verify the ArcGIS license

Step 1: Verify Microsoft .NET Framework 3.5 installation


Prior to installing the ArcGIS Engine Developer Kit, the Microsoft .NET Framework 3.5
and Visual Studio 2008 must be installed. In this step, you will verify that the correct
version of the .NET Framework is installed on your machine.
From your Start menu, choose Control Panel and then open Add or Remove Programs.

Copyright 2001-2009 ESRI

1-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Verify that Microsoft .NET Framework 3.5 appears in the list of installed programs. If
it is not, ask your instructor for help.

Close both dialog boxes.

Step 2: Import code snippets into Visual Studio


In this step, you will import the code snippets that you will use in the exercises into
Visual Studio.
On your desktop, double-click the shortcut for Microsoft Visual Studio 2008.
Note: Or click Start menu > All Programs > Microsoft Visual Studio 2008 > Microsoft
Visual Studio 2008.

If prompted, choose the settings for the language you will use for this course:

Visual Basic Development Settings


or
Visual C# Development Settings
then click Start Visual Studio.
From the Tools menu, choose Code Snippets Manager.
In the Code Snippets Manager, from the Language drop-down list, choose the
language you will use in the exercises (Visual Basic or Visual C#).
Click Add.
In the Code Snippets Directory window, navigate to your \Student\IPAN folder.

1-6

Copyright 2001-2009 ESRI

Exercise 1B

Select IPAN_CodeSnippets and click OK.


Click OK to close the Code Snippets Manager, then close Visual Studio.

Step 3: Authorize the software


Software copy protection of ArcGIS products requires the use of an authorization file to
complete the installation process. In this step, you will run the Software Authorization
Wizard to enable the ArcGIS Engine Developer Kit for use. To save time, an
authorization file has been provided for you.
From the Start menu, choose All Programs > ArcGIS > Software Authorization
DevKit.
On the first panel, choose the option indicating that you have received the
authorization file from ESRI.

Click Next.

Copyright 2001-2009 ESRI

1-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

On the second panel, do the following:

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.

Step 4: Verify the license on your system


The file AuthorizationSummary.exe is a utility that summarizes the license availability on
your system based on the software authorization .ecp file that was used to unlock the
software.
To open the wizard, click Start > All Programs > ArcGIS > Authorization Summary.
Question 1: What is the .ecp expiration date and software version for the ArcGIS Engine
Developer Kit?
______________________________________________________________________

1-8

Copyright 2001-2009 ESRI

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.

Step 5: Identify the .NET ArcObjects API


The modular and cross-platform nature of ArcObjects allows you to choose an
application programming interface (API) to begin ArcObjects development. An API is a
set of interfaces, methods, protocols, and tools that you can use to build or customize
software programs. In this step, you will explore the folder structure of the .NET
ArcObjects API.
In Windows Explorer, navigate to the C:\Program Files\ArcGIS directory and scroll
through the list of folders.
Each API (COM, .NET, Java) is represented with its own directory. For example, the Bin
directory contains the ArcObjects binary files that can be used with all developer APIs.
During this class, you will work with ArcObjects from some of these libraries.
Question 2: In the Bin directory, which file's name indicates that it controls licensing?
______________________________________________________________________
The DotNet directory contains the .NET ArcObjects binary files that can be used with the
.NET API.
Note: As long as the name of a file does not end with UI, you can use it to create
applications on any machine. However, if a file's name ends with UI, it can only be used
on machines that have ArcGIS Desktop installed.

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.

Copyright 2001-2009 ESRI

1-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Click the C:\Program Files\ArcGIS\com directory to display its contents.

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

Copyright 2001-2009 ESRI

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.

Step 6: Prepare the ESRI Object Browser for future use


The ESRI Object Browser is a developer tool that is installed with the developer kit. In
this step, you will prepare it for use throughout this class.
Click Start > All Programs > ArcGIS > Developer Tools.
Point to ESRI Object Browser, right-click, and choose Send To > Desktop (create
shortcut).
Double-click the new desktop shortcut to open the ESRI Object Browser.
In order to use the ESRI Object Browser, you need to reference ArcGIS class libraries.
From the File menu, choose Object Library References.
In the Object Library References dialog box, click Add.

Copyright 2001-2009 ESRI

1-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

For File name, type *.olb and press Enter.


(This narrows the list to object library reference files.)
Select all the files.
Click Open.

Click OK to return to the ESRI Object Browser.


When you search for ArcObjects in the ESRI Object Browser in later exercises, you may
find it helpful for them to display the same way as in the OMDs (object model diagrams).
In the center of the ESRI Object Browser, next to Show Selected Objects, click the
drop-down arrow and choose as AO Diagram.

Now you will perform a search.


In the upper left corner of the ESRI Object Browser, do the following:

1-12

Under Search For, type Map.


Make sure the Exact option is selected.
Under Coclasses, verify that the Coclass Name check box is checked.

Click Search.

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

1-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 1B Questions


Question 1: What is the .ecp expiration date and software version for the ArcGIS Engine
Developer Kit?
Answer: Answers will vary.
Question 2: In the Bin directory, which file's name indicates that it controls licensing?
Answer: LicenseControl.ocx
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?
Answer: ESRI.ArcGIS.DataSourcesRaster.dll
Question 4: In the com directory, which file's name indicates that it allows you to work
with geodatabase data sources?
Answer: esriDataSourcesGDB.olb

1-14

Copyright 2001-2009 ESRI

2
Exploring ArcGIS
Engine controls
Exercise 2: Create your first mapping
application
Estimated time: 45 minutes

Exercise 2

Exercise 2: Create your first mapping application


Estimated time: 45 minutes
In this exercise, you will become familiar with several controls as you create an
application to display and navigate a map.
In this exercise, you will:

Explore the ArcGIS Engine application framework


Work with visual controls you can use within the framework
Create a simple application using components of the framework

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.

Step 1: Review the developer help


The developer help offers general information about ArcObjects, as well as technical
documents, sample code, and more. In this step, you will review some developer help
topics.
On your desktop, double-click the shortcut for the Desktop Help for .Net (VS2008).
The developer help opens with a list of topics on the left and a welcome page on the
right.
Note: If necessary, click the Contents button

Copyright 2001-2009 ESRI

2-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

Getting started >


ArcObjects: Foundation of ArcGIS >
ArcObjects libraries shared across the ArcGIS platform

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

Copyright 2001-2009 ESRI

Exercise 2

In the table of links on the page, click the Controls library link (

).

Take a moment to read the description of this library.


With the controls in this library, you can build an ArcGIS Engine application that is
visually similar to ArcMap for example, one that contains a map, layout, table of
contents, and toolbar.
Click the MapControl link.
The help for the MapControlClass opens in a new tab.
Take a moment to read the Description to learn about the MapControl's functionality.
The MapControl provides properties, methods, and events for managing layers that you
draw in your map. You will use one of the properties in this exercise, and learn about
other properties, methods, and events in later lessons.
Minimize the help window.

Step 2: Create a new project in Visual Studio


There are several different types of .NET applications you can create. You will begin by
creating a new Windows application.
Start Visual Studio.
Before you create your project, you will set the default location for saving your Visual
Studio projects.
From the Tools menu, choose Options.
In the Options dialog box, do the following:

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.

Now you will create your project.


From the File menu, point to New, then choose Project.

Copyright 2001-2009 ESRI

2-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the New Project dialog box, do the following:

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

Copyright 2001-2009 ESRI

Exercise 2

Note: If the Form1 form control does not display, right-click the Form1 file in the
Solution Explorer and choose View Designer.

Question 1: What is the extension of the Form1 file?


______________________________________________________________________
Beneath the Solution Explorer is the Properties window, which allows you to modify
certain properties of forms and controls used in your applications.
Note: If you do not see the Properties window, click View menu > Properties Window.

Step 3: Examine and modify your project


In this step, you will modify your form.
Click the Form1 form control to display its properties in the Properties window.
In the Properties window, do the following:

Locate the Text property. (Hint: Appearance category)


Replace the default text with First Map.
Press Enter.

You will now add controls from a toolbox to your form.


From the View menu, choose Toolbox.
The Toolbox window displays. Notice that the controls are grouped into several
categories.
Locate the ArcGIS Windows Forms group and expand it, if necessary.
Drag a MapControl, TOCControl, and ToolbarControl onto your form.
Resize your form and/or controls as needed.
Right-click your MapControl and choose Properties.
On the General tab in the Properties dialog box, do the following:

For Map Document, browse to the \Student\IPAN\Exercise02 folder and open


SouthAmerica.mxd.
Make sure that Brazil is selected in the Available Maps drop-down list.
Modify some other properties for the MapControl as you wish.
Click OK.

Copyright 2001-2009 ESRI

2-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Notice that the icons display as you add them.


From the Map Inquiry category, add the following commands:

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

Copyright 2001-2009 ESRI

Exercise 2

Step 4: Run your project and resolve an error


Now that you have set up the properties for your controls, you are ready to test your
changes.
Click the Start Debugging button

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

to run your project.

Your project now deploys without any errors.

Step 5: Navigate your map


You are ready to use the commands just you added. In this step, you will experiment with
the tools on your toolbar.
Spend a minute or two using some of the zoom tools on your toolbar.
Notice that your map display responds to the commands just as it would in ArcMap.
Click the Full Extent button

Copyright 2001-2009 ESRI

, then click the Measure tool

2-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the Measure window, click the Choose Units


Kilometers.

button and choose Distance >

Use the Measure tool to answer the following question.


Question 5: What is the approximate distance between Manaus and Porto Velho?
______________________________________________________________________
Click the Identify tool

and click the city of Belem in the map.

Question 6: What is the population of Belem?


______________________________________________________________________
Use the Find tool

or other tool(s) to locate the city of Goiania.

Question 7: What city is nearest to Goiania?


______________________________________________________________________
Your project offers functionality similar to that of ArcMap without writing any code!
Close your application.

Step 6: Open a map document dynamically


There is almost always more than one way to accomplish a task programmatically. In this
step, you will modify your ToolbarControl so that you can click a built-in button on your
application to browse to and open a map document.
Open the Properties dialog box for your ToolbarControl and do the following:

Add the Open command to your ToolbarControl. (Hint: Generic category)


Click OK.

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.

Run your project.


Click the new Open button
open SouthAmerica.mxd.

2-8

, browse to your \Student\IPAN\Exercise02 folder, and

Copyright 2001-2009 ESRI

Exercise 2

The map document displays in the MapControl.


Close your application.
You have finished this exercise; however, you may wish to complete the optional step:

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.

Step 7: (Optional) Programmatically determine the number of


layers in your map
Like Visual Studio controls, the ArcGIS Engine controls have properties and methods. In
this step, you will use Microsoft's IntelliSense to help you programmatically determine
how many layers are in your map. You will learn more about properties and methods for
other ArcGIS Engine controls in upcoming lessons.
Question 8: Where can you find the name of your MapControl?
______________________________________________________________________
You will use this name to access the MapControl in your code.
In the Toolbox window, expand the Common Controls group and drag a Button
control onto your form.
Double-click the Button to open the code for its Click event.
In the Click event for your button, begin a line of code by typing the following:
MessageBox.Show(String.Format("{0:#} layers in map",

Type the name of your MapControl followed by a period (.).


Question 9: Which property of the MapControl will return the number of layers in your
map?
______________________________________________________________________
Based on your answer, finish the line of code.
Run your project.

Copyright 2001-2009 ESRI

2-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 2

Answers to Exercise 2 Questions


Question 1: What is the extension of the Form1 file?
Answer: The file extension is .cs or .vb, depending on the language you are using.
Question 2: On which controls can you assign a buddy control? What can you set it to?
Answer: ToolbarControl, TOCControl; AxMapControl1
Question 3: Which control can you add to your form to eliminate the error?
Answer: LicenseControl
Question 4: Which license is in effect? How many product licenses can you choose from?
Answer: ArcGIS Engine; five
Question 5: What is the approximate distance between Manaus and Porto Velho?
Answer: 760 kilometers
Question 6: What is the population of Belem?
Answer: 1,200,000
Question 7: What city is nearest to Goiania?
Answer: Brasilia
Question 8: Where can you find the name of your MapControl?
Answer: It appears on the control itself in Design view, and in the (Name) property
in the Properties window.
Question 9: Which property of the MapControl will return the number of layers in your
map?
Answer: LayerCount
Question 10: How many layers are in your map?
Answer: Three

Copyright 2001-2009 ESRI

2-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 2 (VB.NET)


Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'Optional step: Determine the number of layers in the map
MessageBox.Show(String.Format("{0:#} layers in map", AxMapControl1.LayerCount))
End Sub
End Class

2-12

Copyright 2001-2009 ESRI

Exercise 2

Exercise Solution: Exercise 2 (C#)


using
using
using
using
using
using
using
using

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));

Copyright 2001-2009 ESRI

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 3A: Program with COM (VB.NET)


Estimated time: 45 minutes
In this exercise, you will access the properties of a map in a map document.
In this exercise, you will:

Use developer resources


Access the properties of a map and list their values

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.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following table as a guide:

Property

Value

Language

Visual Basic

Template

Windows Forms Application

Name

MapDocInfo

Location

\Student\IPAN\Exercise03

Solution name

MapDocInfo

Copyright 2001-2009 ESRI

3-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

On the left, scroll down and select Debugging.


On the right, scroll down and verify that the Redirect all Output Window text to
the Immediate Window check box is unchecked.
Click OK.

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.

Step 2: Add a custom button to your project


In this step, to prepare your project to retrieve some information from your map, you will
add a Visual Studio button.
If necessary, display the Toolbox window. (Hint:

3-2

Copyright 2001-2009 ESRI

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

Step 3: Add code to your custom button


In this step, you will access a map document and determine its name and other properties
without viewing the data. Instead, you will rely on other resources, such as the Desktop
Help for .Net (VS2008), Microsoft's IntelliSense, and your lecture book.
Double-click your Info button to open its Click event.
Declare the variable mapDoc to hold a reference to IMapDocument.
Notice that blue squiggles appear below IMapDocument.
Hover your mouse pointer over IMapDocument.
Your syntax is not recognized, so you will need to add the appropriate reference. You
will use the Library Locator to determine which reference you need.
Open Windows Explorer and do the following:

Navigate to C:\Program Files\ArcGIS\DeveloperKit\Tools.


Right-click LibraryLocator.exe and choose Send To > Desktop (create shortcut).
Close Windows Explorer.

Double-click the new shortcut to open the Library Locator.

Copyright 2001-2009 ESRI

3-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

On the References tab, expand Desktop ArcMap.


Double-click ESRI.ArcGIS.Carto to add it to the list of selected assemblies.
Click Finish.

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

Copyright 2001-2009 ESRI

Exercise 3A

Question 2: What changed in the Dim statement you wrote?


______________________________________________________________________
______________________________________________________________________
The IMapDocument interface is found on the MapDocument coclass, which makes your
mapDoc variable a creatable object.
Use the following code to create a new MapDocument object.
Dim mapDoc as IMapDocument = New MapDocument
Note: You will learn more about this syntax in the next lesson.

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.

Copyright 2001-2009 ESRI

3-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Write the code to open a map document, adding the appropriate drive letter to the
following path:
mapDoc.Open("\Student\IPAN\Exercise03\SouthAmerica.mxd")

Open the Desktop Help for .Net (VS2008).


Click the Search button

to display the Search tab.

Note: If prompted, for Online Help Settings, choose Use local help as primary source,
and then click OK.

In the Search box, type IMapDocument interface and click Search.


In the list of results, do the following:

On the right, click Local Help.


On the left, click the IMapDocument Interface link.

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.________________________)

In Visual Studio, make sure the Output window is displayed.


Note: Debug menu > Windows > Output

Save your project, then build it.

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.

Run your project (Hint:

).

In your application, click the Info button.


Question 4: What value is returned when you click the Info button?
______________________________________________________________________
Close your application.

3-6

Copyright 2001-2009 ESRI

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()

Run your project and test the change.

Step 4: Work with the map


Although your application does not currently display a map, you can still access the map
and the active view for your map document. In this step, you will use .NET casting to
move between the interfaces for the map and the active view.
Before the code that closes the window, declare the variable inMap to hold a reference
to IMap.
Complete the following code to set inMap equal to the first map in your map
document:
inMap = ________.Map(0)

Write the name of the map to the Output window.


Run your project and test your code.
After the application closes, click the Clear All button

in your Output window.

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.

Beware of non-string and non-numeric properties as they may cause


runtime errors.

Build and run your project.


Test your changes.

Copyright 2001-2009 ESRI

3-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Question 5: What are the map's distance units?


______________________________________________________________________

Step 5: Work with the active view


In this step, you will find the X and Y values for the lower-left and upper-right corners of
the extent of your map. You will add your code to your custom button.
Continuing with your code, declare the variable actView as IActiveView.
Write code to cast implicitly (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.
Change your implicit cast to an explicit cast.
Test your change.
Inside your sub procedure, write the Extent property of the active view to the Output
window.
Click inside your sub procedure.
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:

3-8

Copyright 2001-2009 ESRI

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.

Step 6: (Optional) Add a MapControl to your project


In this step, you will add your map document to a MapControl.
To view your project in Design view, click the View Designer button
the Solution Explorer.

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.

Copyright 2001-2009 ESRI

3-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

In the Products list, check the box for ArcView.


Check the box to shut down the application if the selected licenses are not
available.
Click OK.

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.________________________________)

Comment the line Me.Close().


Click the Info button to test your code.
SouthAmerica.mxd displays in the MapControl.
Close your application, then close Visual Studio.

3-10

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

3-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 3A Questions


Question 1: Which library do you need to add to your project?
Answer: ESRI.ArcGIS.Carto
Question 2: What changed in the Dim statement you wrote?
Answer: IMapDocument no longer displays an error, but the variable mapDoc is
flagged as an unused local variable
Question 3: What parameter does the property return? How many types of documents
does it include?
Answer: esriMapDocumentType; four types
Question 4: What value is returned when you click the Info button?
Answer: esriMapDocumentTypeMxd
Question 5: What are the map's distance units?
Answer: esriMiles
Question 6: Which assembly is required?
Answer: ESRI.ArcGIS.Geometry
Question 7: What is the minimum X value (rounded to the nearest integer)?
Answer: -84
Question 8: What is the maximum Y?
Answer: 7
Question 9: Which module initializes the license with the application and shuts down the
license?
Answer: ApplicationEvents.vb

3-12

Copyright 2001-2009 ESRI

Exercise 3A

Exercise Solution: Exercise 3A (VB.NET)


Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Geometry
Public Class Form1
Private Sub btnInfo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim mapDoc As IMapDocument = New MapDocument
mapDoc.Open("\Student\IPAN\Exercise03\SouthAmerica.mxd")
Debug.WriteLine(mapDoc.DocumentType) ' Search help first
Dim inMap As IMap
inMap = mapDoc.Map(0)
Debug.WriteLine("Map name: " & inMap.Name)
Debug.WriteLine("Distance units: " & inMap.DistanceUnits.ToString())
Dim actView As IActiveView
'actView = inMap ' QI / Implicit conversion
actView = CType(inMap, IActiveView) ' Explicit conversion
Debug.WriteLine("ActiveView focus map name: " & actView.FocusMap.Name)
'Debug.WriteLine("XMin: " & actView.Extent.XMin)
Debug.WriteLine("XMin: " & Math.Round(actView.Extent.XMin,
"YMin: " & Math.Round(actView.Extent.YMin,
vbCrLf & _
"XMax: " & Math.Round(actView.Extent.XMax,
"YMax: " & Math.Round(actView.Extent.YMax,

0) & " " & _


0) & _
0) & " " & _
0))

AxMapControl1.LoadMxFile(mapDoc.DocumentFilename)
'Me.Close()
End Sub
End Class

Copyright 2001-2009 ESRI

3-13

Exercise 3B

Exercise 3B: Program with COM (C#)


Estimated time: 45 minutes
In this exercise, you will access the properties of a map in a map document.
In this exercise, you will:

Use developer resources


Access the properties of a map and list their values

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.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following table as a guide:

Property

Value

Language

Visual C#

Template

Windows Forms Application

Name

MapDocInfo

Location

\Student\IPAN\Exercise03

Solution name

MapDocInfo

Copyright 2001-2009 ESRI

3-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

On the left, scroll down and select Debugging.


On the right, scroll down and verify that the Redirect all Output Window text to
the Immediate Window check box is unchecked.
Click OK.

Step 2: Add a custom button to your project


In this step, to prepare your project to retrieve some information from your map, you will
add a Visual Studio button.
If necessary, display the Toolbox window. (Hint:

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

Step 3: Add code to your custom button


In this step, you will access a map document and determine its name and other properties
without viewing the data. Instead, you will rely on other resources, such as the Desktop
Help for .Net (VS2008), Microsoft's IntelliSense, and your lecture book.
Double-click your Info button to open its Click event.
Declare the variable mapDoc to hold a reference to IMapDocument.
From the Build menu, choose Build MapDocInfo to build your project.

3-16

Copyright 2001-2009 ESRI

Exercise 3B

Hover your mouse pointer over IMapDocument.


Your syntax is not recognized, so you will need to add the appropriate reference. You
will use the Library Locator to determine which reference you need.
Open Windows Explorer and do the following:

Navigate to C:\Program Files\ArcGIS\DeveloperKit\Tools.


Right-click LibraryLocator.exe and choose Send To > Desktop (create shortcut).
Close Windows Explorer.

Double-click the new shortcut to open the Library Locator.


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.

Copyright 2001-2009 ESRI

3-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the Add ArcGIS Reference dialog box, do the following:

On the References tab, expand Desktop ArcMap.


Double-click ESRI.ArcGIS.Carto to add it to the list of selected assemblies.
Click Finish.

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:

).

Click inside your btnInfo_Click method.


Question 2: What changed in the variable declaration you wrote?
______________________________________________________________________
______________________________________________________________________
The IMapDocument interface is found on the MapDocument coclass, which makes your
mapDoc variable a creatable object.
Use the following code to create a new MapDocument object.
IMapDocument mapDoc = new MapDocumentClass();
Note: You will learn more about this syntax in the next lesson. Also, you may have
noticed the additional "Class" added to the class name. You will learn more about it in
Lesson 10.

Build your project.


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.

3-18

Copyright 2001-2009 ESRI

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", "");

Open the Desktop Help for .Net (VS2008).


Click the Search button

to display the Search tab.

Note: If prompted, for Online Help Settings, choose Use local help as primary source,
and then click OK.

In the Search box, type IMapDocument interface and click Search.

Copyright 2001-2009 ESRI

3-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the list of results, do the following:

On the right, click Local Help.


On the left, click the IMapDocument Interface link.

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.________________________);

In Visual Studio, make sure the Output window is displayed.


Note: Debug menu > Windows > Output

Build your project, then run it.


If necessary, display the Output window.
Click the Info button on your application.
Question 4: What value is returned in the Output window when you click the Info button?
______________________________________________________________________
Close your application.
In your button's Click event, skip several lines after
System.Diagnostics.Debug.WriteLine and then use the following syntax to close
your application as soon as the process finishes:
this.Close();

Run your project and test the change.

3-20

Copyright 2001-2009 ESRI

Exercise 3B

Step 4: Work with the map


Although your application does not currently display a map, you can still access the map
and the active view for your map document. In this step, you will use .NET casting to
move between the interfaces for the map and the active view.
Before the code that closes the application, declare the variable inMap to hold a
reference to IMap.
Complete the following code to assign inMap to the first map in your map document:
inMap = ________.get_Map(0);

Write the name of the map to the Output window.


Run your project and test your code.
After the application closes, click the Clear All button

in your Output window.

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.

Beware of non-string and non-numeric properties as they may cause


runtime errors.

Build and run your project.


Test your changes.
Question 5: What are the map's distance units?
______________________________________________________________________

Step 5: Work with the active view


In this step, you will find the X and Y values for the lower-left and upper-right corners of
the extent of your map. You will add your code to your custom button.

Copyright 2001-2009 ESRI

3-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

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.

Step 6: (Optional) Add a MapControl to your project


In this step, you will add your map document to a MapControl.
To view your project in Design view, click the View Designer button
the Solution Explorer.

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.

Copyright 2001-2009 ESRI

3-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

From the Project menu, choose Add ArcGIS License Checking.


In the ArcGIS License Initializer dialog box, do the following:

In the Products list, check the box for ArcView.


Check the box to shut down the application if the selected licenses are not
available.
Click OK.

Code that manages the license is added to your project.


Question 9: Which module initializes the license with the application and shuts down the
license?
______________________________________________________________________
The license-handling routine added references and namespaces that it needs, but you need
to add a using statement to the code for your form.
View the Form1 code.
Add the following code after the other using statements:
using ESRI.ArcGIS.esriSystem;

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.________________________________);

Comment the line this.Close().


Click the Info button to test your code.
SouthAmerica.mxd displays in the MapControl.
Close your application.
Save your project and close Visual Studio.

3-24

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

3-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 3B Questions


Question 1: Which library do you need to add to your project?
Answer: ESRI.ArcGIS.Carto
Question 2: What changed in the variable declaration you wrote?
Answer: IMapDocument no longer displays an error, but the variable mapDoc is
flagged as never used
Question 3: What parameter does the property return? How many types of documents
does it include?
Answer: esriMapDocumentType; four types
Question 4: What value is returned in the Output window when you click the Info button?
Answer: esriMapDocumentTypeMxd
Question 5: What are the map's distance units?
Answer: esriMiles
Question 6: Which assembly is required?
Answer: ESRI.ArcGIS.Geometry
Question 7: What is the minimum X value (rounded to the nearest integer)?
Answer: -84
Question 8: What is the maximum Y?
Answer: 7
Question 9: Which module initializes the license with the application and shuts down the
license?
Answer: LicenseInitializer.cs

3-26

Copyright 2001-2009 ESRI

Exercise 3B

Exercise Solution: Exercise 3B (C#)


using
using
using
using
using
using
using

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();

Copyright 2001-2009 ESRI

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 4A: Create an ArcObjects application (VB.NET)


Estimated time: 45 minutes
Several help systems are available for ArcObjects developers. In this exercise, you will
use these systems to help you create a simple application to access geographic data. You
will count the number of features in a shapefile, taking advantage of a pre-written snippet
to jump-start your application.
In this exercise, you will:

Explore and use various developer resources


Navigate object model diagrams (OMDs)
Make simple modifications to the code

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.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following table as a guide:

Property

Value

Language

Visual Basic

Template

Windows Forms Application

Name

CountFeatures

Location

\Student\IPAN\Exercise04

Solution name

CountFeatures

Copyright 2001-2009 ESRI

4-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Make sure the Create directory for solution check box is checked.

Your project opens in Design view as a Visual Studio form control.

Step 2: Add controls to your form


In this step, you will add a button and a text box to your form.
Right-click Form1 and choose Properties.
In the Properties window, specify the following:

(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

Copyright 2001-2009 ESRI

Exercise 4A

Step 3: Explore ArcGIS Snippet Finder


The ArcGIS Snippet Finder helps you find and insert ArcGIS snippets into a Visual
Studio project using keyword searches. It is an ArcGIS integrated development
environment (IDE) integration product that comes with the ArcGIS Desktop and ArcGIS
Engine Software Developer Kit (SDK).
In the Solution Explorer, right-click Form1.vb > View Code.
Right-click anywhere in the class. In the context menu that opens, choose ArcGIS
Snippet Finder.

In the ArcGIS Snippet Finder dialog box, from the Tools menu, choose Options.
In the Preferences dialog box, do the following:

On the left side, click Directories.


On the right side, make sure VBNet is selected under Language.
Click Add, navigate to the C:\Student\IPAN\IPAN_CodeSnippets\VisualBasic
folder, and click OK.

Close the Preferences Window.

Copyright 2001-2009 ESRI

4-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the ArcGIS Snippet Finder, do the following:

Verify that the path at the top reads:


C:\Student\IPAN\IPAN_CodeSnippets\VisualBasic\*.snippet.
For Keyword(s), type Shapefile and click Search.
In the results list, select IPAN_Ex04_CountFeatures.snippet, if necessary.

Take a moment to review the snippet text in the bottom pane.


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 the ArcGIS SDK is available in the developer
help topic, Visual Studio Integration Tools > Snippet Index.

Step 4: Add the Snippet to your code


In this step, you will add the snippet that you reviewed in the ArcGIS Snippet Finder.

4-4

Copyright 2001-2009 ESRI

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.

Step 5: Browse the developer help


In this step, you will use the developer help to find out information about classes,
interfaces, properties, and methods.
Double-click your desktop shortcut to the Desktop Help for .NET (VS2008).
In the table of contents, navigate to:

Building solutions with ArcGIS Engine using .NET >


Getting started >
ArcObjects: Foundation of ArcGIS >
ArcObjects libraries shared across the ArcGIS platform

On the right, scroll down and read the description for the Geodatabase library.

Copyright 2001-2009 ESRI

4-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

The attributes for your shapefile are stored in a table.


Question 3: What is the relationship between Table and Dataset?
______________________________________________________________________
Question 4: What is the relationship between the Table object and the Row object? What
is the minimum number of Rows in a Table?
______________________________________________________________________
Scroll down past the Workspace Objects diagram to the WorkspaceFactory objects.
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.

Step 6: Navigate the Geodatabase OMD


In this step, you will examine one of the standard OMDs for ArcObjects to help you
understand relationships between classes.
Return to the top of the Geodatabase help page.

4-6

Copyright 2001-2009 ESRI

Exercise 4A

Under Additional library information, click Object Model Diagram.

The Geodatabase OMD opens, but in very small print.


To enlarge the display area, do the following:

Close the Contents window.


On the toolbar, change the zoom percent to 100.
Press Enter.

Make sure you are viewing the top of the diagram.


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.

Copyright 2001-2009 ESRI

4-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Use the PDF tools to search for the Table class.

Recall that you learned about inheritance in the lecture.


Question 6: What does ITable inherit from? What kind of inheritance is this?
______________________________________________________________________
The IClass interface has methods and properties that apply to all tables.
Using the Hand tool
Table class.

to pan, follow the solid line that extends from the top of the

Recall from the previous step that a Table is a type of Dataset.


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.

4-8

Copyright 2001-2009 ESRI

Exercise 4A

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 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).

Step 7: Explore the ArcGIS Resource Centers


The Desktop Help for .NET (VS2008) is a static version of ArcGIS developer help. The
most current documentation and help, however, is available in the ArcGIS Resource

Copyright 2001-2009 ESRI

4-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 8: Make your code work for you


To make your code work, you will begin by adding the necessary assembly references to
your code in Visual Studio.
In the code view, hover your mouse pointer over IWorkspaceFactory.
Question 11: What is the error that displays?
______________________________________________________________________
You will search for IWorkspaceFactory in the Library Locator. First, you will add the
Library Locator to Visual Studio for easier navigation.
From the Tools menu, choose External Tools.
In the External Tools dialog box, do the following:

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.

Copyright 2001-2009 ESRI

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.

Question 12: Which library contains the IWorkspaceFactory interface?


______________________________________________________________________
Click Copy.
In the Solution Explorer, right-click CountFeatures and choose Add ArcGIS
Reference.
In the Add ArcGIS Reference dialog box, expand Desktop ArcMap and add the
necessary reference.
Scroll to the top of your class.
Before the code for your class, import the namespace.
On your own, resolve the syntax error for ShapefileWorkspaceFactory.
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.

Step 9: "Do something" with your shapefile


The code that you have entered so far finds and opens a shapefile. For your code to be
useful, it needs to perform at least one additional action. In this step, you will "do
something," as directed by the comment in the snippet.
Review the code.

Copyright 2001-2009 ESRI

4-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

On the Object Browser tab, do the following:

In the <Search> box, type ITable.


Press Enter.
In the tree on the left, find ESRI.ArcGIS.Geodatabase.ITable and select it, if
necessary.

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

Copyright 2001-2009 ESRI

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.

Step 10: Run your project and check your results


In this step, you will run your project. Before you do, you will add license checking to it.
From the Project menu, choose Add ArcGIS License Checking.

Copyright 2001-2009 ESRI

4-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the ArcGIS License Initializer dialog box, do the following:

Under Products, check the check box for ArcView.


Check the Shut down this application if any selected license(s) is not available
check box.
Click OK.

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

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

4-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 4A Questions


Question 1: How many interfaces does the sample use? What is the name of the coclass?
Answer: Four; ShapefileWorkspaceFactory
Question 2: What are the two methods?
Answer: OpenFromFile and OpenTable
Question 3: What is the relationship between Table and Dataset?
Answer: A Table is a type of Dataset.
Question 4: What is the relationship between the Table object and the Row object? What
is the minimum number of Rows in a Table?
Answer: A Table is composed of Rows; 0
Question 5: Based on the symbology for the WorkspaceFactory objects, what is the
relationship between a ShapefileWorkspaceFactory and a WorkspaceFactory?
Answer: ShapefileWorkspaceFactory is a type of WorkspaceFactory.
Question 6: What does ITable inherit from? What kind of inheritance is this?
Answer: IClass; interface inheritance
Question 7: Can a Workspace contain more than one Dataset?
Answer: Yes
Question 8: Which class can instantiate (or create) a Workspace?
Answer: WorkspaceFactory
Question 9: What does OpenFromFile return, and what does OpenTable return?
Answer: IWorkspace; ITable

4-16

Copyright 2001-2009 ESRI

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

Copyright 2001-2009 ESRI

4-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 4A (VB.NET)


Imports ESRI.ArcGIS.GeoDatabase
Imports ESRI.ArcGIS.DataSourcesFile
Public Class frmCount
Private Sub btnCount_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnCount.Click
' 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)
'
' Applicable ArcGIS Product Versions:
' 9.2
' 9.3
'
' Notes:
' This snippet is intended to be inserted inside a Function or Sub.
' It is not intended to be added to the base level of the Class.
'Enter a valid path
Dim filePath As String = "\Student\IPAN\Database"
Dim tableName As String = "Cities.shp"
Dim pFact As IWorkspaceFactory = New ShapefileWorkspaceFactory
Dim pWorkspace As IWorkspace = pFact.OpenFromFile(filePath, 0)
Dim pFWorkspace As IFeatureWorkspace = pWorkspace
Dim pTable As ITable = pFWorkspace.OpenTable(tableName)
'Do something with the table
Dim numRows As Long
numRows = pTable.RowCount(Nothing)
txtCount.Text = numRows.ToString
End Sub
End Class

4-18

Copyright 2001-2009 ESRI

Exercise 4B

Exercise 4B: Create an ArcObjects application (C#)


Estimated time: 45 minutes
Several help systems are available for ArcObjects developers. In this exercise, you will
use these systems to help you create a simple application to access geographic data,
taking advantage of a pre-written snippet to jump-start your application.
In this exercise, you will:

Explore and use various developer resources


Navigate object model diagrams (OMDs)
Make simple modifications to the code

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.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following table as a guide:

Property

Value

Language

Visual C#

Template

Windows Forms Application

Name

CountFeatures

Location

\Student\IPAN\Exercise04

Solution name

CountFeatures

Copyright 2001-2009 ESRI

4-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Make sure the Create directory for solution check box is checked.

Your project opens in Design view as a Visual Studio form control.

Step 2: Add controls to your form


In this step, you will add a button and a text box to your form.
Right-click Form1 and choose Properties.
In the Properties window, specify the following:

(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

Copyright 2001-2009 ESRI

Exercise 4B

Step 3: Explore ArcGIS Snippet Finder


The ArcGIS Snippet Finder helps you find and insert ArcGIS snippets into a Visual
Studio project using keyword searches. It is an ArcGIS integrated development
environment (IDE) integration product that comes with the ArcGIS Desktop and ArcGIS
Engine Software Developer Kit (SDK).
In the Solution Explorer, right-click Form1.cs > View Code.
Right-click anywhere in the class. In the context menu that opens, choose ArcGIS
Snippet Finder.

In the ArcGIS Snippet Finder, from the Tools menu, choose Options.
In the Preferences dialog box, do the following:

On the left side, click Directories.


On the right side, make sure CSharp is selected under Language.
Click Add, navigate to the C:\Student\IPAN\IPAN_CodeSnippets\CSharp folder,
and click OK.

Copyright 2001-2009 ESRI

4-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Close the Preferences dialog box.


In the ArcGIS Snippet Finder, do the following:

Verify that the path at the top reads:


C:\Student\IPAN\IPAN_CodeSnippets\CSharp\*.snippet.
For Keyword(s), type Shapefile and click Search.
In the results list, select IPAN_Ex04_CountFeatures.snippet, if necessary.

Take a moment to review the snippet text in the bottom pane.

4-22

Copyright 2001-2009 ESRI

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.

Step 4: Add the Snippet to your code


In this step, you will add the snippet that you previewed in the ArcGIS Snippet Finder.
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 > CSharp>
IPAN_Ex04_CountFeatures.
Build your solution.
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.

Copyright 2001-2009 ESRI

4-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 5: Browse the developer help


In this step, you will use the developer help to find out information about classes,
interfaces, properties, and methods.
Double-click your desktop shortcut to the Desktop Help for .NET (VS2008).
In the table of contents, navigate to:

Building solutions with ArcGIS Engine using .NET >


Getting started >
ArcObjects: Foundation of ArcGIS >
ArcObjects libraries shared across the ArcGIS platform

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.

The attributes for your shapefile are stored in a table.


Question 3: What is the relationship between Table and Dataset?
______________________________________________________________________
Question 4: What is the relationship between the Table object and the Row object? What
is the minimum number of Rows in a Table?
______________________________________________________________________
Scroll down past the Workspace Objects diagram to the WorkspaceFactory objects.

4-24

Copyright 2001-2009 ESRI

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.

Step 6: Navigate the Geodatabase OMD


In this step, you will examine one of the standard OMDs for ArcObjects to help you
understand relationships between classes.
Return to the top of the Geodatabase help page.
Under Additional library information, click Object Model Diagram.

The Geodatabase OMD opens, but in very small print.


To enlarge the display area, do the following:

Close the Contents window.


On the toolbar, change the zoom percent to 100.
Press Enter.

Make sure you are viewing the top of the diagram.

Copyright 2001-2009 ESRI

4-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Recall that you learned about inheritance in the lecture.


Question 6: What does ITable inherit from? What kind of inheritance is this?
______________________________________________________________________
The IClass interface has methods and properties that apply to all tables.
Using the Hand tool
Table class.

to pan, follow the solid line that extends from the top of the

Recall from the previous step that a Table is a type of Dataset.

4-26

Copyright 2001-2009 ESRI

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).

Copyright 2001-2009 ESRI

4-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 7: Explore the ArcGIS Resource Centers


The Desktop Help for .NET (VS2008) is a static version of ArcGIS developer help. The
most current documentation and help, however, is available in the ArcGIS Resource
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 link to .NET, 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.

Step 8: Make your code work for you


To make your code work, you will begin by adding the necessary assembly references to
your code in Visual Studio.
Build your project.
In the code view, hover your mouse pointer over IWorkspaceFactory.
Question 11: What is the error that displays?
______________________________________________________________________
You will search for IWorkspaceFactory in the Library Locator. First, you will add the
Library Locator to Visual Studio for easier navigation.
From the Tools menu, choose External Tools.

4-28

Copyright 2001-2009 ESRI

Exercise 4B

In the External Tools dialog box, do the following:

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.

Question 12: Which library contains the IWorkspaceFactory interface?


______________________________________________________________________
Click Copy.
In the Solution Explorer, right-click CountFeatures and choose Add ArcGIS
Reference.
In the Add ArcGIS Reference dialog box, expand Desktop ArcMap and add the
necessary reference.
Scroll to the top of your class.
Before the code for your class, import the namespace with the using directive.

For the library name, use Geodatabase (with a lowercase "d").

Build your project.


On your own, resolve the remaining syntax error.

Copyright 2001-2009 ESRI

4-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 9: "Do something" with your shapefile


The code that you have entered so far finds and opens a shapefile. For your code to be
useful, it needs to perform at least one additional action. In this step, you will "do
something," as directed by the comment in the snippet.
Review the code.
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

On the Object Browser tab, do the following:

4-30

In the <Search> box, type ITable.


Press Enter.
In the tree on the left, find ESRI.ArcGIS.Geodatabase.ITable and select it, if
necessary.

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

4-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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 (place the code immediately after the comment):
________ numRows;

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.

Step 10: Run your project and check your results


In this step, you will run your project. Before you do, you will add license checking to it.
From the Project menu, choose Add ArcGIS License Checking.
In the ArcGIS License Initializer dialog box, do the following:

Under Products, check the check box for ArcView.


Check the Shut down this application if any selected license(s) is not available
check box.
Click OK.

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

Copyright 2001-2009 ESRI

Exercise 4B

Question 17: How many features are in your shapefile?


______________________________________________________________________
Close your application, then 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.

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.

Copyright 2001-2009 ESRI

4-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 4B Questions


Question 1: How many interfaces does the sample use? What is the name of the coclass?
Answer: Four; ShapefileWorkspaceFactory
Question 2: What are the two methods?
Answer: OpenFromFile and OpenTable
Question 3: What is the relationship between Table and Dataset?
Answer: A Table is a type of Dataset.
Question 4: What is the relationship between the Table object and the Row object? What
is the minimum number of Rows in a Table?
Answer: A Table is composed of Rows; 0
Question 5: Based on the symbology for the WorkspaceFactory objects, what is the
relationship between a ShapefileWorkspaceFactory and a WorkspaceFactory?
Answer: ShapefileWorkspaceFactory is a type of WorkspaceFactory.
Question 6: What does ITable inherit from? What kind of inheritance is this?
Answer: IClass; interface inheritance
Question 7: Can a Workspace contain more than one Dataset?
Answer: Yes
Question 8: Which class can instantiate (or create) a Workspace?
Answer: WorkspaceFactory
Question 9: What does OpenFromFile return, and what does OpenTable return?
Answer: IWorkspace; ITable

4-34

Copyright 2001-2009 ESRI

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

Copyright 2001-2009 ESRI

4-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 4B (C#)


using
using
using
using
using
using
using

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

Copyright 2001-2009 ESRI

Exercise 4B

long numRows;
numRows = tab.RowCount(null);
txtCount.Text = numRows.ToString();

Copyright 2001-2009 ESRI

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 5A: Work with maps and layers (VB.NET)


Estimated time: 45 minutes
As an ArcObjects programmer, there are several ways you can access maps in a
document. In this exercise, you will work with maps and layers and learn more about
handling events.
Remember that what you define as a map in ArcObjects is referred to as a data frame in
the ArcMap interface. A map is simply a collection of layers. Different maps in the same
document can have a different set of layers, can represent various extents, and can even
have different spatial references (projections, map units, and so on).
In this exercise, you will:

Display map and layer properties in a custom form


Work with layer properties
Work with map events

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.

Step 1: Open an existing project in Visual Studio


You will begin this exercise by opening an existing project that has been created for you.

Copyright 2001-2009 ESRI

5-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Start Visual Studio.


From the File menu, choose Open Project.
Browse to the \Student\IPAN\Exercise05\VisualBasic\MapsAndLayers folder and
open MapsAndLayers.sln.
In the Solution Explorer, notice that your project contains a form (Form1).
View the project in Design view. (Tip: If necessary, double-click Form1.vb in the
Solution Explorer).

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

Copyright 2001-2009 ESRI

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.

Step 2: Load a map document programmatically


In a previous exercise, you used the properties of the MapControl to load a map
document and choose a map to display. That is one way to add a map. Another way is to
add the map document programmatically, and then allow the user to browse to the
desired map.
Your first step is to access the collection of maps found in the map document. You will
then populate the cboMaps combo box with the names of the maps.
The map document you will load contains three data frames, each of which contains
many layers. This reinforces the OMD relationships; a document is composed of many
maps and a map is composed of many layers.
Using the developer resource of your choice, find the members on the MapControl
object.
Question 3: Which interface is returned by the Map property?
______________________________________________________________________
In the Toolbox window, drag an OpenFileDialog control from the Dialogs group onto
your form and place it anywhere you like.
Note: If you cannot access the Toolbox window, make sure you are in Design view

Now you will access the dialog box from a button.


Double-click your Load Mxd button to open its Click event.

Copyright 2001-2009 ESRI

5-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 5A

Navigate to the beginning of the class and paste your code.


Instead of Dim, use the Private keyword to declare the variable.
Rename the variable m_mapDocument (it should still point to the IMapDocument
interface).

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.

Copyright 2001-2009 ESRI

5-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 3: Test your project


You will now test your code.
Build and run your project.
A license error message displays.
Click OK on the error message, then close your application.
From the Project menu, choose Add ArcGIS License Checking.
In the ArcGIS License Initializer dialog box, do the following:

Under Products, check the check box for ArcView.


Check the Shut down this application if any selected license(s) is not available
check box.
Click OK.

Run your project again.


Click the Load Mxd button.
Browse to your \Student\IPAN\Exercise05 folder and open MapsAndLayers.mxd.
Question 5: What is the name of the active data frame in the map document?
______________________________________________________________________
Although you have added the map document, notice that the map in the MapControl is
currently empty. In a previous exercise, you specified a map in the MapControl's
Properties dialog box. In the next step, you will replicate that process by writing code to
select a map from the combo box.
Close your application.

Step 4: Access the layers in a map


When accessing a map from a maps collection, you do not refer to it by its name. Instead,
you use its index number, which represents the position of the map in the collection).
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.

5-6

Copyright 2001-2009 ESRI

Exercise 5A

View the code for Form1.


At the beginning of your class, below the declaration for IMapDocument, declare the
following variables:
Private m_enumLayers As IEnumLayer
Private m_map As IMap
Private m_layer As ILayer2

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.

Copyright 2001-2009 ESRI

5-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.________()

Remember that there are two kinds of looping structures:

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

Run the project to test your code.

5-8

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

5-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

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.

Step 5: (Optional) Respond to MapControl events


In this optional step, you will respond to an event on the MapControl and copy the map to
a PageLayoutControl. You will begin by adding a PageLayoutControl to your form.
View your form in Design view.
In the Toolbox window, drag a PageLayoutControl from the ArcGIS Windows Forms
group onto your form and place it anywhere you like.
If necessary, resize your form and/or controls.
Note: The controls can be small and even overlap.

In the Solution Explorer, click the View Code button

to switch to code view.

On the Visual Studio navigation bar, do the following:

In the Class Name drop-down list, choose AxMapControl1.


Open the Method Name drop-down list.

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.

Copyright 2001-2009 ESRI

5-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Load MapsAndLayers.mxd and display a map.


Notice that the map now displays in the PageLayoutControl.
To synchronize the MapControl's focus map with the PageLayoutControl so that they
both display the same map data, you would need to write more code; however, this topic
is outside the scope of this course.
Note: For sample code that illustrates how to synchronize the PageLayoutControl with
the MapControl, refer to C:\ProgramFiles\ArcGIS\DeveloperKit\SamplesNET\
Engine\MapAndPageLayoutSynchApp.

Close your application.


To learn how to distinguish feature layers from raster layers, continue on to the next
step. Otherwise, close Visual Studio.

Step 6: (Optional) Distinguish between feature and raster layers


In this optional step, you will determine whether the layers in your map document are
feature or raster layers.
Make sure you are in code view

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

Copyright 2001-2009 ESRI

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 <> ""

Navigate to the top of the lboMapLayers_SelectedValueChanged event and enter the


following code:
btnLayerInfo.Enabled = lboMapLayers.Text <> ""

Run your project and test your changes.


One by one, choose each map to answer the following question.
Question 9: Which layer is not a feature layer?
______________________________________________________________________
Now that you can programmatically distinguish between feature layers and raster layers,
your next step might be to populate the Fields list box. You will learn how to access
fields in a later lesson.
Close your application, then close Visual Studio.

Copyright 2001-2009 ESRI

5-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 5A

Answers to Exercise 5A Questions


Question 1: What is the name of the form?
Answer: frmDocInfo
Question 2: What type of control are lboMapLayers and lboFields? What type of items
can be stored in them?
Answer: ListBox; a collection of strings
Question 3: Which interface is returned by the Map property?
Answer: IMap
Question 4: Which reference do you need to add?
Answer: ESRI.ArcGIS.Carto
Question 5: What is the name of the active data frame in the map document?
Answer: Kauai, HI
Question 6: Which property on the IMaps interface returns a pointer to an object that
supports IMap?
Answer: Item
Question 7: Which property on the IMap interface returns a reference to an object that
supports IEnumLayer?
Answer: Layers
Question 8: Which method on the IEnumLayer interface returns a reference to an object
that supports ILayer?
Answer: Next
Question 9: Which layer is not a feature layer?
Answer: The Kauai and Nihau layer in the Kauai, HI map

Copyright 2001-2009 ESRI

5-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 5A (VB.NET)


Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.esriSystem
Public Class frmDocInfo
Private m_mapDocument As IMapDocument
Private m_enumLayers As IEnumLayer
Private m_map As IMap
Private m_layer As ILayer2
Private Sub btnClose_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnClose.Click
Me.Close()
End Sub
Private Sub btnFrameInfo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnFrameInfo.Click
Dim sDocName As String
Dim sMapName As String
Dim iMapCount As Integer
sDocName = m_mapDocument.DocumentFilename
sMapName = m_map.Name
iMapCount = m_mapDocument.MapCount
MessageBox.Show("Mxd Name: " & sDocName & vbCrLf & _
"Active Frame: " & sMapName & vbCrLf & _
"Data Frames: " & iMapCount & vbCrLf)
End Sub
Private Sub btnLayerInfo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnLayerInfo.Click
MessageBox.Show(m_map.LayerCount.ToString() & " layers in the active map")
End Sub
Private Sub btnFieldInfo_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnFieldInfo.Click
MessageBox.Show("You will learn how to access fields in a later lesson")
End Sub
Private Sub btnLoadMxd_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnLoadMxd.Click

5-16

Copyright 2001-2009 ESRI

Exercise 5A

'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Open a file dialog
Long Description:
Open a file dialog to select a map document
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted inside a Function or Sub.
It is not intended to be added to the base level of the Class.

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 <> ""

Copyright 2001-2009 ESRI

5-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Copy map
Long Description:
Copy a map to a layout
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted inside a Function or Sub.
It is not intended to be added to the base level of the Class.

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

Copyright 2001-2009 ESRI

Exercise 5A

'Overwrite the PageLayoutControl's map


objectCopy.Overwrite(copiedMap, toOverwriteMap)
End Sub
Private Sub lboMapLayers_SelectedValueChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles lboMapLayers.SelectedValueChanged
btnLayerInfo.Enabled = lboMapLayers.Text <> ""
lboFields.Items.Clear()
m_enumLayers.Reset() ' Move the enum pointer above the first layer
m_layer = m_enumLayers.Next() ' Return the first layer from the enumeration
Do Until m_layer Is Nothing ' Begin the conditional loop
If m_layer.Name = lboMapLayers.Text Then ' Check whether this is the layer
Exit Do ' If the layer is found, exit the loop (but not the Sub)
End If
m_layer = m_enumLayers.Next() ' Return another layer
Loop ' End the loop
If Not TypeOf m_layer Is IFeatureLayer2 Then
'Does it support this interface?
lboFields.Items.Add("Not a feature layer")
Exit Sub ' Stop executing the procedure
End If
btnFieldInfo.Enabled = lboMapLayers.Text <> ""
End Sub
End Class

Copyright 2001-2009 ESRI

5-19

Exercise 5B

Exercise 5B: Work with maps and layers (C#)


Estimated time: 45 minutes
As an ArcObjects programmer, there are several ways you can access maps in a
document. In this exercise, you will work with maps and layers and learn more about
handling events.
Remember that what you define as a map in ArcObjects is referred to as a data frame in
the ArcMap interface. A map is simply a collection of layers. Different maps in the same
document can have a different set of layers, can represent various extents, and can even
have different spatial references (projections, map units, and so on).
In this exercise, you will:

Display map and layer properties in a custom form


Work with layer properties
Work with map events

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.

Step 1: Open an existing project in Visual Studio


You will begin this exercise by opening an existing project that has been created for you.

Copyright 2001-2009 ESRI

5-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Start Visual Studio.


From the File menu, choose Open Project.
Browse to the \Student\IPAN\Exercise05\CSharp\MapsAndLayers folder, then open
MapsAndLayers.sln.
In the Solution Explorer, notice that your project contains a form, Form1.
View the project in Design view. (Tip: If necessary, double-click Form1.vb in the
Solution Explorer).

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

Copyright 2001-2009 ESRI

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.

Step 2: Load a map document programmatically


In a previous exercise, you used the properties of the MapControl to load a map
document and choose a map to display. That is one way to add a map. Another way is to
add the map document programmatically, and then allow the user to browse to the
desired map.
Your first step is to access the collection of maps found in the map document. You will
then populate the cboMaps combo box with the names of the maps.
The map document you will load contains three data frames, each of which contains
many layers. This reinforces the OMD relationships; a document is composed of many
maps and a map is composed of many layers.
Using the developer resource of your choice, find the members on the MapControl
object.
Question 3: Which interface is returned by the Map property?
______________________________________________________________________
In the Toolbox window, drag an OpenFileDialog control from the Dialogs group onto
your form and place it anywhere you like.
Note: If you cannot access the Toolbox window, make sure you are in Design view

Now you will access the dialog box from a button.


Double-click your Load Mxd button to open its Click event.

Copyright 2001-2009 ESRI

5-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 5B

Navigate to the beginning of the class and paste your code.


Use the private keyword to declare the variable.
Rename the variable m_mapDocument (it should still point to the IMapDocument
interface).

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.________;

Copyright 2001-2009 ESRI

5-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

The code you have written populates a combo box, which will allow you to choose the
map you want to display.

Step 3: Test your project


You will now test your code.
Build and run your project.
A license error message displays.
Click OK on the error message, then close your application.
From the Project menu, choose Add ArcGIS License Checking.
In the ArcGIS License Initializer dialog box, do the following:

Under Products, check the check box for ArcView.


Check the Shut down this application if any selected license(s) is not available
check box.
Click OK.

Run your project again.


Click the Load Mxd button.
Browse to your \Student\IPAN\Exercise05 folder and open MapsAndLayers.mxd.
Question 5: What is the name of the active data frame in the map document?
______________________________________________________________________
Although you have added the map document, notice that the map in the MapControl is
currently empty. In a previous exercise, you specified a map in the MapControl's
Properties dialog box. In the next step, you will replicate that process by writing code to
select a map from the combo box.
Close your application.

Step 4: Access the layers in a map


When accessing a map from a maps collection, you do not refer to it by its name. Instead,
you use its index number, which represents the position of the map in the collection.

5-26

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

5-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:
{

//Pull a map from the collection


m_map = m_mapDocument.get_Map(i);
if (m_map.Name.Equals(cboMaps.SelectedItem))
//Is this the chosen map?
{
axMapControl1.Map = m_map;
break;
//Exits the loop once the map is found
}
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 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 ______________;

Remember that there are two kinds of looping structures:

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

Copyright 2001-2009 ESRI

Exercise 5B

do
{

lboMapLayers.Items.Add(m_layer.Name);
m_layer = m_enumLayers.Next() as ILayer2;
} while (m_layer != null);

Run the project to test your code.


Note: If you have errors, compare your code with the following:
for (int i = 0; i < m_mapDocument.MapCount; i++)
{
m_map = m_mapDocument.get_Map(i);
if (m_map.Name.Equals(cboMaps.SelectedItem))
{
axMapControl1.Map = m_map;
break; // Exits once the map is found
}
}
m_enumLayers = m_map.get_Layers(null, true);
// Not just one layer!
m_layer = m_enumLayers.Next() as ILayer2;
do
{

lboMapLayers.Items.Add(m_layer.Name);
m_layer = m_enumLayers.Next() as ILayer2;
} while (m_layer != null);

Copyright 2001-2009 ESRI

5-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 5B

Note: The button will be disabled until a map name is chosen.

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.

Step 5: (Optional) Respond to MapControl events


In this optional step, you will respond to an event on the MapControl and copy the map to
a PageLayoutControl. You will begin by adding a PageLayoutControl to your form.
View your form in Design view.
In the Toolbox window, drag a PageLayoutControl from the ArcGIS Windows Forms
group onto your form and place it anywhere you like.

Copyright 2001-2009 ESRI

5-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

If necessary, resize your form and/or controls.


Note: The controls can be small and even overlap.

Click your MapControl to display its properties in the Properties window.


Click the Events button

Double-click the OnMapReplaced event.


The code for the event displays.
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.
Load MapsAndLayers.mxd and display a map.
Notice that the map now displays in the PageLayoutControl.
To synchronize the MapControl's focus map with the PageLayoutControl so that they
both display the same map data, you would need to write more code; however, this topic
is outside the scope of this course.
Note: For sample code that illustrates how to synchronize the PageLayoutControl with
the MapControl, refer to C:\ProgramFiles\ArcGIS\DeveloperKit\SamplesNET\
Engine\MapAndPageLayoutSynchApp.

Close your application.


To learn how to distinguish feature layers from raster layers, continue on to the next
step. Otherwise, close Visual Studio.

Step 6: (Optional) Distinguish between feature and raster layers


In this optional step, you will determine whether the layers in your map document are
feature or raster layers.

5-32

Copyright 2001-2009 ESRI

Exercise 5B

In Design view, click the lboMapLayers list box to display its properties in the
Properties window.
Click the Events button

Double-click the SelectedValueChanged event.


The code for the event displays.
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.)
//Move the enum pointer above the first layer
m_enumLayers.__________();
// Return first layer from the enumeration
m_layer = m_enumLayers.________() as ILayer2;
// Begin the loop
do
{
if (m_layer.Name == lboMapLayers.Text) //Check whether this is the layer
{
// Determine whether you have a feature layer
}
m_layer = ____________________.________() as ILayer2; //Return another layer
} while (m_layer != null);

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

Copyright 2001-2009 ESRI

5-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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 != "");

Navigate to the top of the lboMapLayers_SelectedValueChanged event and enter the


following code:
btnLayerInfo.Enabled = (lboMapLayers.Text != "");

Run your project and test your changes.


One by one, choose each map to answer the following question.
Question 9: Which layer is not a feature layer?
______________________________________________________________________
Now that you can programmatically distinguish between feature layers and raster layers,
your next step might be to populate the Fields list box. You will learn how to access
fields in a later lesson.
Close your application, then close Visual Studio.

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

Copyright 2001-2009 ESRI

Exercise 5B

Answers to Exercise 5B Questions


Question 1: What is the name of the form?
Answer: frmDocInfo
Question 2: What type of control are lboMapLayers and lboFields? What type of items
can be stored in them?
Answer: ListBox; a collection of strings
Question 3: Which interface is returned by the Map property?
Answer: IMap
Question 4: Which reference do you need to add?
Answer: ESRI.ArcGIS.Carto
Question 5: What is the name of the active data frame in the map document?
Answer: Kauai, HI
Question 6: Which property on the IMaps interface returns a pointer to an object that
supports IMap?
Answer: Item
Question 7: Which property on the IMap interface returns a reference to an object that
supports IEnumLayer?
Answer: Layers
Question 8: Which method on the IEnumLayer interface returns a reference to an object
that supports ILayer?
Answer: Next
Question 9: Which layer is not a feature layer?
Answer: The Kauai and Nihau layer in the Kauai, HI map

Copyright 2001-2009 ESRI

5-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 5B (C#)


using
using
using
using
using
using
using

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

Copyright 2001-2009 ESRI

Exercise 5B

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

ArcGIS Snippet Title:


Open file dialog
Long Description:
Opens a file dialog to select a map document
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
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.

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;

lblDataFrame.Text = "Active Data Frame: "


+ m_mapDocument.ActiveView.FocusMap.Name;

private void cboMaps_SelectedValueChanged(object sender, EventArgs e)


{
lboMapLayers.Items.Clear();
for (int i = 0; i < m_mapDocument.MapCount; i++)
{
//Pull a map from the collection
m_map = m_mapDocument.get_Map(i);
if (m_map.Name.Equals(cboMaps.SelectedItem))
//Is this the chosen map?
{
axMapControl1.Map = m_map;
break;
//Exits the loop once the map is found
}
}
m_enumLayers = m_map.get_Layers(null,true);
m_layer = m_enumLayers.Next() as ILayer2;

Copyright 2001-2009 ESRI

5-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

do
{

lboMapLayers.Items.Add(m_layer.Name);
m_layer = m_enumLayers.Next() as ILayer2;
} while (m_layer != null);

btnFrameInfo.Enabled = cboMaps.Text != "";


btnLayerInfo.Enabled = cboMaps.Text != "";

private void btnFrameInfo_Click(object sender, System.EventArgs e)


{
string sDocName = m_mapDocument.DocumentFilename;
string sMapName = m_map.Name;
int iMapCount = m_mapDocument.MapCount;
MessageBox.Show(("Mxd Name: "
+ (sDocName + ("\r\n" + ("Active Frame: "
+ (sMapName + ("\r\n" + ("Data Frames: "
+ (iMapCount + "\r\n")))))))));
}
private void axMapControl1_OnMapReplaced(object sender, _
ESRI.ArcGIS.Controls.IMapControlEvents2_OnMapReplacedEvent e)
{
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

ArcGIS Snippet Title:


Copy map
Long Description:
Copy a map to a layout
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
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.

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

// Overwrite the PageLayoutControl's map


objectCopy.Overwrite(copiedMap, ref toOverwriteMap);

Copyright 2001-2009 ESRI

Exercise 5B

private void lboMapLayers_SelectedValueChanged(object sender, EventArgs e)


{
btnLayerInfo.Enabled = (lboMapLayers.Text != "");
lboFields.Items.Clear();
m_enumLayers.Reset();
//move the enum pointer above the first layer
m_layer = m_enumLayers.Next() as ILayer2;
//Return the first layer from the enumeration

do //begin the loop


{
if (m_layer.Name == lboMapLayers.Text) //check whether this is the layer
{
//Determine whether you have a feature layer
if (!(m_layer is IFeatureLayer2))
{
lboFields.Items.Add("Not a feature layer");
}
break;
//If the layer is found, exit the loop (but not the event)
}
m_layer = m_enumLayers.Next() as ILayer2;
//Return another layer
} while (m_layer != null);
btnFieldInfo.Enabled = (lboMapLayers.Text != "");

Copyright 2001-2009 ESRI

5-39

6
Accessing data

Exercise 6A: Access data with


ArcObjects (VB.NET)
Estimated time: 45 minutes
Exercise 6B: Access data with
ArcObjects (C#)
Estimated time: 45 minutes

Exercise 6A

Exercise 6A: Access data with ArcObjects (VB.NET)


Estimated time: 45 minutes
In this exercise, you will use the WorkspaceFactory in order to access an existing file
geodatabase. You will access feature datasets and feature classes and create new feature
layers. You will then set the data source and general properties of the new feature layers
and add them to your MapControl.
In this exercise, you will:

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.

Step 1: Open an existing workspace


In this step, you will use ArcObjects code to open an existing workspace, the World.gdb
file geodatabase. You will begin by examining the geodatabase and its contents.
Start ArcCatalog.

Copyright 2001-2009 ESRI

6-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Navigate to and expand your \Student\IPAN\Database folder.


Expand the World.gdb geodatabase and the World feature dataset it contains.

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.

Step 2: Create a new project in Visual Studio


Start Visual Studio.
Create a new project, using the following table as a guide:

!
6-2

Property

Value

Language

Visual Basic

Project type

ArcGIS > Engine

Template

MapControl Application

Name

DataAccess

Location

\Student\IPAN\Exercise06

Solution name

DataAccess

Make sure the Create directory for solution check box is checked.

Copyright 2001-2009 ESRI

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.

Step 3: Explore classes and interfaces for working with data


Before you begin developing your application, you will review topics in the available
resources to help you understand the code that you will need to write.
Using the developer resource of your choice, examine the WorkspaceFactory class
and the interfaces supported by it.
Question 3: Which interface supported by WorkspaceFactory has a method that returns a
workspace from a file?
______________________________________________________________________
Question 4: What is the name of the method?
______________________________________________________________________
Add the reference to your project and import the namespace.
Now you will explore two OMDs to help you understand how to access data.
Open the Geodatabase OMD.
Locate the WorkspaceFactory class in the upper left and the wormhole below it.

Copyright 2001-2009 ESRI

6-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

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

Set the workspace variable by writing the following code:


workspace = wsFactory.OpenFromFile _
("\Student\IPAN\Database\World.gdb", 0)
Note: The second parameter for OpenFromFile is a window handle object (hWnd),
which is an integer that references an application's window and can be used to tie other
dialog boxes or data to a particular application.

Build your project.

Step 4: Access feature classes


Now that you have used the WorkspaceFactory class to open your geodatabase, you are
ready to access the data in that workspace. In this step, you will access feature classes
that reside in the workspace.
Using the Geodatabase OMD, locate the IFeatureWorkspace interface. (Hint: Look
in the Workspace class.)

Copyright 2001-2009 ESRI

6-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Question 6: Which method can be used to access a feature class?


______________________________________________________________________
Question 7: What is returned by this method?
______________________________________________________________________
Declare the variable fWS as a reference to IFeatureWorkspace.
Do a QI to the workspace with the following code:
fWS = workspace

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

Copyright 2001-2009 ESRI

Exercise 6A

Step 5: Create feature layers


In order to add these data sources to the map, you need to create layers. These layers are
in-memory copies of the corresponding feature classes that are stored on disk.
Question 8: What type of layers are Countries and Lakes?
______________________________________________________________________
Declare a variable named countriesLayer to the IFeatureLayer interface.
Complete the following code to create a new feature layer:
countriesLayer = ______ ________________________

Declare another variable named lakesLayer to the IFeatureLayer interface.


Complete the following code to create a new feature layer:
lakesLayer= ______ ________________________;

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

Step 6: Set the data sources for the feature layers


In order for a feature layer to reference data correctly, it must point to its data source on
disk. If you were to add the Countries and Lakes layers to the map right now, they would
be empty layers, referencing no data. In this step, you will set the data source for the new
feature layers.
Open the ESRI Object Browser, if necessary, and do the following:

In the Interfaces area, verify that you are searching for an interface name.

Copyright 2001-2009 ESRI

6-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Make sure no other search options are checked.


Search for IFeatureLayer.
Double-click the result and view its methods and properties.

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

Copyright 2001-2009 ESRI

Exercise 6A

Step 7: Set general layer properties


In this step, you will set the name and some other properties for your new feature layers.
Using the following table as a guide, set properties for your feature layers:

Layer

Property

Value

countriesLayer

Name

World Countries

countriesLayer

ShowTips

True

------------------------

------------------------

------------------------

lakesLayer

Name

World Lakes

lakesLayer

ShowTips

False

lakesLayer

Visible

False

Note: Remember to enclose string values within quotes.

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.

Step 8: Add layers to your MapControl


Now that you have the properties set for your new feature layers, you will add them to
your MapControl.
At this point, you do not have any variables pointing to an interface that will allow you to
add a layer to the map.
In the Visual Studio Object Browser, search for AddLayer.
Several occurrences of AddLayer appear, indicating that you have more than one option.
Note: AddLayer is an overloaded method. You can find documentation on the
interfaces that support this method by searching the help for AddLayer.

Copyright 2001-2009 ESRI

6-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Find the ESRI.ArcGIS.Controls namespace in the list.

Multiple references to the AddLayer method display.


is something that an object knows how to do. In this case, the MapControl
knows how to add layers. You just have to tell the MapControl to do it, like when you
click the Add Data button in ArcMap. This method expects a layer that supports ILayer
as an argument.
AddLayer

Question 10: Which types of layers support ILayer?


______________________________________________________________________
In your code, use the AddLayer method to add the Countries layer to your MapControl
(axMapControl1).
Add the Lakes layer to the MapControl.
Your procedure is now ready to runyou just need to call it.
Use the Class Name and Method Name drop-down lists to navigate to the
MainForm_Load event.
Just before End Sub, set the MapControl's ShowMapTips property to True.
Call your AddData sub procedure.

6-10

Copyright 2001-2009 ESRI

Exercise 6A

Step 9: Run your project


Now you are ready to run your project and view your map.
Build and run your project.
Notice that your two new layers are added with the properties you set.
The TOCControl gives you some functionality that you find in ArcMap, such as the
ability to rename a data frame, or map.
Click the data frame name, then click it again so it is editable.
Change the name to World View.

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:

Step 10 shows you how to display MapTips for selected layers

If you want to complete the optional step, do so now. Otherwise, close Visual Studio.

Step 10: (Optional) Control MapTips for your layers dynamically


In your custom applications that use the ArcGIS Engine controls, you have learned that
you can replicate some of the functionality of ArcMap. In this step, you will conditionally
show MapTips for a selected layer. You will begin by adding a CheckBox control to your
form.
View your form in Design view.
Click the MapControl.

Copyright 2001-2009 ESRI

6-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the Properties window, change the MapControl's Dock property to None.


Resize your MapControl so that there is enough room on the form for a check box.
In the Toolbox window, drag a CheckBox control from the Common Controls group
onto your form.
Change the CheckBox control's Name property to chkShowTips.
Change the Text property to Show MapTips.
The following graphic illustrates one possible configuration (yours may differ):

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

Copyright 2001-2009 ESRI

Exercise 6A

Question 11: Which variable do you need to add to your code?


______________________________________________________________________
Add the module-level variable to the beginning of your class.
Return to the TOCControl's OnMouseDown event.
Note: Ignore the implicit conversion warnings.

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

Navigate to the CheckedChanged event of chkShowTips and enter the following


condition to manage the visibility of the MapTips:
If chkShowTips.CheckState = CheckState.Checked Then
axMapControl1.ShowMapTips = True
Else
axMapControl1.ShowMapTips = False
End If

Copyright 2001-2009 ESRI

6-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Finally, navigate to the AddData sub procedure.


Comment the lines that currently control the visibility of MapTips for your two feature
layers.
Run your project.
In the table of contents, check the World Lakes layer to turn it on, and if necessary,
click the layer to select it.
Check the Show MapTips box.
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-14

Copyright 2001-2009 ESRI

Exercise 6A

Answers to Exercise 6A Questions


Question 1: How many feature datasets are in this geodatabase?
Answer: One (World)
Question 2: How many feature classes are there? How many stand-alone feature classes?
Answer: Three (Countries, Lakes, Faults); One (Faults)
Question 3: Which interface supported by WorkspaceFactory has a method that returns a
workspace from a file?
Answer: IWorkspaceFactory (or IWorkspaceFactory2)
Question 4: What is the name of the method?
Answer: OpenFromFile
Question 5: What is the relationship between all of the various workspace factories and
the WorkspaceFactory class?
Answer: They are all types of workspace factories
Question 6: Which method can be used to access a feature class?
Answer: OpenFeatureClass
Question 7: What is returned by this method?
Answer: A reference to IFeatureClass
Question 8: What type of layers are Countries and Lakes?
Answer: Feature layers
Question 9: What does the symbol used for FeatureClass property mean ?
Answer: It is set by reference (it has a hollow box)

Copyright 2001-2009 ESRI

6-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Question 10: Which types of layers support ILayer?


Answer: All, since the ILayer interface is found on the abstract class that all layers
inherit from.
Question 11: Which variable do you need to add to your code?
Answer: m_layer as ILayer
Question 12: What data type do the x and y properties of e return?
Answer: Integer
Question 13: Which types of layers will display MapTips?
Answer: Feature layers

6-16

Copyright 2001-2009 ESRI

Exercise 6A

Exercise Solution: Exercise 6A (VB.NET)


Imports
Imports
Imports
Imports
Imports
Imports
Imports
Imports

System.IO
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Carto
ESRI.ArcGIS.Controls
ESRI.ArcGIS.ADF
ESRI.ArcGIS.SystemUI
ESRI.ArcGIS.Geodatabase
ESRI.ArcGIS.DataSourcesGDB

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
axMapControl1.ShowMapTips = False
chkShowTips.CheckState = CheckState.Unchecked
AddData()
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)

Copyright 2001-2009 ESRI

6-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

'Make sure that the MapDocument is not readonly


If mapDoc.IsReadOnly(m_mapDocumentName) Then
MessageBox.Show("Map document is read only!")
mapDoc.Close()
Return
End If
'Replace its contents with the current map
mapDoc.ReplaceContents(CType(m_mapControl.Map, IMxdContents))
'save the MapDocument in order to persist it
mapDoc.Save(mapDoc.UsesRelativePaths, False)
'close the MapDocument
mapDoc.Close()
End If
End Sub
Private Sub menuSaveAs_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles menuSaveAs.Click
'execute SaveAs Document command
Dim command As ICommand = New ControlsSaveAsDocCommandClass()
command.OnCreate(m_mapControl.Object)
command.OnClick()
End Sub
Private Sub menuExitApp_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles menuExitApp.Click
'exit the application
Application.Exit()
End Sub
#End Region
'listen to the MapReplaced event in order to update the statusbar and the Save menu
Private Sub axMapControl1_OnMapReplaced(ByVal sender As Object, _
ByVal e As IMapControlEvents2_OnMapReplacedEvent) _
Handles axMapControl1.OnMapReplaced
'get the current document name from the MapControl
m_mapDocumentName = m_mapControl.DocumentFilename
'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 menu and write the doc name to the statusbar
menuSaveDoc.Enabled = True
statusBarXY.Text = 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

6-18

Copyright 2001-2009 ESRI

Exercise 6A

Private Sub AddData()


Dim wsFactory As IWorkspaceFactory
wsFactory = New FileGDBWorkspaceFactory
Dim workspace As IWorkspace
workspace = wsFactory.OpenFromFile _
("\Student\IPAN\Database\World.gdb", 0)
Dim fWS As IFeatureWorkspace
'fWS = workspace ' Original code, implicit casting
fWS = CType(workspace, IFeatureWorkspace) ' Explicit casting
Dim fcCountries As IFeatureClass
fcCountries = fWS.OpenFeatureClass("Countries")
Dim fcLakes As IFeatureClass
fcLakes = fWS.OpenFeatureClass("Lakes")
Dim countriesLayer As IFeatureLayer
countriesLayer = New FeatureLayer
Dim lakesLayer As IFeatureLayer
lakesLayer = New FeatureLayer
countriesLayer.FeatureClass = fcCountries
lakesLayer.FeatureClass = fcLakes
countriesLayer.Name = "World Countries"
' countriesLayer.ShowTips = True
lakesLayer.Name = "World Lakes"
' lakesLayer.ShowTips = False
lakesLayer.Visible = False
'Add layers
axMapControl1.AddLayer(countriesLayer)
axMapControl1.AddLayer(lakesLayer)
End Sub

Copyright 2001-2009 ESRI

6-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Private Sub axTOCControl1_OnMouseDown(ByVal sender As Object, _


ByVal e _
ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent)
Handles axTOCControl1.OnMouseDown
' ArcGIS Snippet Title:
' Find layer in TOC
'
' Long Description:
' Find the selected layer in the table of contents
'
' Intended ArcGIS Products for this snippet:
' ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
' ArcGIS Engine
'
' Applicable ArcGIS Product Versions:
' 9.2
' 9.3
'
' Notes:
' This snippet is intended to be inserted into the OnMouseDown
' event of the TOC Control.
' The code assumes that a module-level variable (m_layer) has
' been declared as ILayer
Dim
Dim
Dim
Dim
Dim

map As Map = Nothing


layer As ILayer = Nothing
other As Object = Nothing
item As esriTOCControlItem
index As Object = Nothing

Dim toc As ITOCControl2 = axTOCControl1.Object


toc.HitTest(e.x, e.y, item, map, layer, other, index)
If item = esriTOCControlItem.esriTOCControlItemLayer Then
m_layer = layer
End If
End Sub
Private Sub chkShowTips_CheckedChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles chkShowTips.CheckedChanged
If chkShowTips.CheckState = CheckState.Checked Then
axMapControl1.ShowMapTips = True
Else
axMapControl1.ShowMapTips = False
End If
End Sub

6-20

Copyright 2001-2009 ESRI

Exercise 6A

Private Sub chkShowTips_CheckStateChanged(ByVal sender As Object, _


ByVal e As System.EventArgs) Handles chkShowTips.CheckStateChanged
' ArcGIS Snippet Title:
' Show tips
'
' Long Description:
' Show map tips
'
' Intended ArcGIS Products for this snippet:
' ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
' ArcGIS Engine
'
' Applicable ArcGIS Product Versions:
' 9.2
' 9.3
'
' Notes:
' This snippet is intended to be inserted into the CheckStateChanged
' event of a Visual Studio CheckBox.
' The code assumes that a module-level variable (m_layer)
' has been declared as ILayer
Dim i As Integer
Dim layer As ILayer
'Loop through the layers in the map
For i = 0 To axMapControl1.LayerCount - 1
layer = axMapControl1.get_Layer(i)
If TypeOf layer Is IFeatureLayer Then
'Show MapTips based for selected layer,
'depending on status of CheckBox
If layer Is m_layer Then ' Note use of IS, rather than =
If chkShowTips.CheckState = 1 Then
layer.ShowTips = True
Else
layer.ShowTips = False
End If
Else
layer.ShowTips = False
End If
End If
Next i
End Sub
End Class

Copyright 2001-2009 ESRI

6-21

Exercise 6B

Exercise 6B: Access data with ArcObjects (C#)


Estimated time: 45 minutes
In this exercise, you will use the WorkspaceFactory in order to access an existing file
geodatabase. You will access feature datasets and feature classes and create new feature
layers. You will then set the data source and general properties of the new feature layers
and add them to your MapControl.
In this exercise, you will:

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.

Step 1: Open an existing workspace


In this step, you will use ArcObjects code to open an existing workspace, the World.gdb
file geodatabase. You will begin by examining the geodatabase and its contents.
Start ArcCatalog.

Copyright 2001-2009 ESRI

6-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Navigate to and expand your \Student\IPAN\Database folder.


Expand the World.gdb geodatabase and the World feature dataset it contains.

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.

Step 2: Create a new project in Visual Studio


Start Visual Studio.
Create a new project, using the following table as a guide:

6-24

Property

Value

Language:

Visual C#

Project type:

ArcGIS > Engine

Template:

MapControl Application

Name:

DataAccess

Location:

\Student\IPAN\Exercise06

Solution name:

DataAccess

Copyright 2001-2009 ESRI

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.

Step 3: Explore classes and interfaces for working with data


Before you begin developing your application, you will review topics in the available
resources to help you understand the code that you will need to write.
Using the developer resource of your choice, examine the WorkspaceFactory class
and the interfaces supported by it.
Question 4: Which interface supported by WorkspaceFactory has a method that returns a
workspace from a file?
______________________________________________________________________
Question 5: What is the name of the method?
______________________________________________________________________
Add the reference to your project and import the namespace.
Now you will explore two OMDs to help you understand how to access data.
Open the Geodatabase OMD.

Copyright 2001-2009 ESRI

6-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 6B

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.

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.

Copyright 2001-2009 ESRI

6-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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;

Set the workspace variable by writing the following code:


workspace = wsFactory.OpenFromFile("\\Student\\IPAN\\Database\\World.gdb", 0);
Note: The second parameter for OpenFromFile is a window handle object (hWnd),
which is an integer that references an application's window and can be used to tie other
dialog boxes or data to a particular application.

Build your project.

Step 4: Access feature classes


Now that you have used the WorkspaceFactory class to open your geodatabase, you are
ready to access the data in that workspace. In this step, you will access feature classes
that reside in the workspace.
Using the Geodatabase OMD, locate the IFeatureWorkspace interface. (Hint: Look
in the Workspace class.)
Question 7: Which method can be used to access a feature class?
______________________________________________________________________
Question 8: What is returned by this method?
______________________________________________________________________
Declare the variable fWS as a reference to IFeatureWorkspace.
Cast to the workspace with the following code:

6-28

Copyright 2001-2009 ESRI

Exercise 6B

fWS = workspace as IFeatureWorkspace;

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.

Step 5: Create feature layers


In order to add these data sources to the map, you need to create layers. These layers are
in-memory copies of the corresponding feature classes that are stored on disk.
Question 9: What type of layers are Countries and Lakes?
______________________________________________________________________
Declare a variable named countriesLayer to the IFeatureLayer interface.
Complete the following code to create a new feature layer:
countriesLayer = ______ ________________________;

Declare another variable named lakesLayer to the IFeatureLayer interface.


Complete the following code to create a new feature layer:
lakesLayer= ______ ________________________;

Copyright 2001-2009 ESRI

6-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Verify that your code for the two new feature layers matches the following:
IFeatureLayer countriesLayer;
countriesLayer = new FeatureLayer();
IFeatureLayer lakesLayer;
lakesLayer = new FeatureLayer();

Step 6: Set the data sources for the feature layers


In order for a feature layer to reference data correctly, it must point to its data source on
disk. If you were to add the Countries and Lakes layers to the map right now, they would
be empty layers, referencing no data. In this step, you will set the data source for the new
feature layers.
Open the ESRI Object Browser, if necessary, and do the following:

In the Interfaces area, verify that you are searching for an interface name.

Make sure no other search options are checked.


Search for IFeatureLayer.
Double-click the result and view its methods and properties.

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

Copyright 2001-2009 ESRI

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.

Step 7: Set general layer properties


In this step, you will set the name and some other properties for your new feature layers.
Using the following table as a guide, set properties for your feature layers:

Layer

Property

Value

countriesLayer

Name

World Countries

countriesLayer

ShowTips

true

------------------------

------------------------

------------------------

lakesLayer

Name

World Lakes

lakesLayer

ShowTips

false

lakesLayer

Visible

false

Note: Remember to enclose string values within quotes.

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

Copyright 2001-2009 ESRI

6-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

layers contain lots of data coming from a multiuser geodatabase. In cases like these,
making a layer invisible is more efficient.

Step 8: Add layers to your MapControl


Now that you have the properties set for your new feature layers, you will add them to
your MapControl.
At this point, you do not have any variables pointing to an interface that will allow you to
add a layer to the map.
In the Visual Studio Object Browser, search for AddLayer.
Several occurrences of AddLayer appear, indicating that you have more than one option.
Note: AddLayer is an overloaded method. You can find documentation on the
interfaces that support this method by searching the help for AddLayer.

Find the ESRI.ArcGIS.Controls namespace in the list.

Multiple references to the AddLayer method display.


is something that an object knows how to do. In this case, the MapControl
knows how to add layers. You just have to tell the MapControl to do it, like when you
click the Add Data button in ArcMap. This method expects a layer that supports ILayer
as an argument.
AddLayer

Question 11: Which types of layers support ILayer?


______________________________________________________________________
In your code, use the AddLayer method to add the Countries layer to your MapControl
(axMapControl1).
Add the Lakes layer to the MapControl.

6-32

Copyright 2001-2009 ESRI

Exercise 6B

Your code is now ready to runyou just need to call it.


In Design view, click your form to display its properties in the Properties window.
Click the Events button

Double-click Load to go to the MainForm_Load event.


The code for the event displays.
Just before the end of the event, set the MapControl's ShowMapTips property to true.
Call your AddData method.

Step 9: Run your project


Now you are ready to run your project and view your map.
Build and run your project.
Notice that your two new layers are added with the properties you set.
The TOCControl gives you some functionality that you find in ArcMap, such as the
ability to rename a data frame, or map.
Click the data frame name, then click it again so it is editable.
Change the name to World View.

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:

Step 10 shows you how to display MapTips for selected layers

Copyright 2001-2009 ESRI

6-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

If you want to complete the optional step, do so now. Otherwise, close Visual Studio.

Step 10: (Optional) Control MapTips for your layers dynamically


In your custom applications that use the ArcGIS Engine controls, you have learned that
you can replicate some of the functionality of ArcMap. In this step, you will conditionally
show MapTips for a selected layer. You will begin by adding a CheckBox control to your
form.
View your form in Design view.
Click the MapControl.
In the Properties window, change the MapControl's Dock property to None.
Resize your MapControl so that there is enough room on the form for a check box.
In the Toolbox window, drag a CheckBox control from the Common Controls group
onto your form.
Change the CheckBox control's Name property to chkShowTips.
Change the Text property to Show MapTips.
The following graphic illustrates one possible configuration (yours may differ):

6-34

Copyright 2001-2009 ESRI

Exercise 6B

Click your TOCControl to display its properties in the Properties window.


Click the Events button

, then double-click OnMouseDown.

Code for the axTOCControl1_OnMouseDown event opens.


Place your mouse pointer inside the event code, then right-click and insert the snippet
IPAN_Ex06_TOC_HitTest.
Review the code.
Question 12: Which variable do you need to add to your code?
______________________________________________________________________
Add the module-level variable to the beginning of your class.
Return to the TOCControl's OnMouseDown event.
In the event, find the line of code that contains the HitTest method.
Right-click the HitTest method and choose Go To Definition.

Copyright 2001-2009 ESRI

6-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Question 13: 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.
(Hint: View the properties for chkShowTips and click Events
.)
Insert the snippet IPAN_Ex06_ShowTips.
Question 14: 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;

Navigate to the CheckedChanged event of chkShowTips and enter the following


condition to manage the visibility of the MapTips:
if (chkShowTips.CheckState == CheckState.Checked)
axMapControl1.ShowMapTips = true;
else
axMapControl1.ShowMapTips = false;

Finally, navigate to your AddData method.


Comment the lines that currently control the visibility of MapTips for your two feature
layers.
Build and run your project.
In the table of contents, check the box for the World Lakes layer to turn it on, and if
necessary, click the layer to select it.
Check the Show MapTips check box.

6-36

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

6-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 6B Questions


Question 1: How many feature datasets are in this geodatabase?
Answer: One (World)
Question 2: How many feature classes are there?
Answer: Three (Countries, Lakes, Faults)
Question 3: How many stand-alone feature classes are there?
Answer: One (Faults)
Question 4: Which interface supported by WorkspaceFactory has a method that returns a
workspace from a file?
Answer: IWorkspaceFactory (or IWorkspaceFactory2)
Question 5: What is the name of the method?
Answer: OpenFromFile
Question 6: What is the relationship between all of the various workspace factories and
the WorkspaceFactory class?
Answer: They are all types of workspace factories
Question 7: Which method can be used to access a feature class?
Answer: OpenFeatureClass
Question 8: What is returned by this method?
Answer: A reference to IFeatureClass
Question 9: What type of layers are Countries and Lakes?
Answer: Feature layers
Question 10: What does the symbol used for FeatureClass property mean ?
Answer: It is set by reference (it has a hollow box)

6-38

Copyright 2001-2009 ESRI

Exercise 6B

Question 11: Which types of layers support ILayer?


Answer: All, since the ILayer interface is found on the abstract class that all layers
inherit from.
Question 12: Which variable do you need to add to your code?
Answer: ILayer m_layer;
Question 13: What data type do the x and y properties of e return?
Answer: Integer
Question 14: Which types of layers will display MapTips?
Answer: Feature layers

Copyright 2001-2009 ESRI

6-39

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 6B (C#)


using
using
using
using
using
using
using
using

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

Copyright 2001-2009 ESRI

Exercise 6B

#region Main Menu event handlers


private void menuNewDoc_Click(object sender, EventArgs e)
{
//execute New Document command
ICommand command = new CreateNewDocument();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuOpenDoc_Click(object sender, EventArgs e)
{
//execute Open Document command
ICommand command = new ControlsOpenDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuSaveDoc_Click(object sender, EventArgs e)
{
//execute Save Document command
if (m_mapControl.CheckMxFile(m_mapDocumentName))
{
//create a new instance of a MapDocument
IMapDocument mapDoc = new MapDocumentClass();
mapDoc.Open(m_mapDocumentName, string.Empty);
//Make sure that the MapDocument is not readonly
if (mapDoc.get_IsReadOnly(m_mapDocumentName))
{
MessageBox.Show("Map document is read only!");
mapDoc.Close();
return;
}
//Replace its contents with the current map
mapDoc.ReplaceContents((IMxdContents)m_mapControl.Map);
//save the MapDocument in order to persist it
mapDoc.Save(mapDoc.UsesRelativePaths, false);

//close the MapDocument


mapDoc.Close();

private void menuSaveAs_Click(object sender, EventArgs e)


{
//execute SaveAs Document command
ICommand command = new ControlsSaveAsDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuExitApp_Click(object sender, EventArgs e)
{
//exit the application
Application.Exit();
}
#endregion

Copyright 2001-2009 ESRI

6-41

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

//listen to MapReplaced event in order to update the statusbar


//and the Save menu
private void axMapControl1_OnMapReplaced(object sender,
IMapControlEvents2_OnMapReplacedEvent e)
{
//get the current document name from the MapControl
m_mapDocumentName = m_mapControl.DocumentFilename;

//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);
}

private void axMapControl1_OnMouseMove(object sender,


IMapControlEvents2_OnMouseMoveEvent e)
{
statusBarXY.Text =
string.Format("{0}, {1} {2}", e.mapX.ToString("#######.##"),
e.mapY.ToString("#######.##"),
axMapControl1.MapUnits.ToString().Substring(4));
}
private void AddData()
{
IWorkspaceFactory wsFactory;
wsFactory = new FileGDBWorkspaceFactory();
IWorkspace workspace;
workspace = wsFactory.OpenFromFile(
"\\Student\\IPAN\\Database\\World.gdb", 0);
IFeatureWorkspace fWS;
fWS = workspace as IFeatureWorkspace;
IFeatureClass fcCountries;
fcCountries = fWS.OpenFeatureClass("Countries");
IFeatureClass fcLakes;
fcLakes = fWS.OpenFeatureClass("Lakes");
IFeatureLayer countriesLayer;
countriesLayer = new FeatureLayer();
IFeatureLayer lakesLayer;
lakesLayer = new FeatureLayer();
countriesLayer.FeatureClass = fcCountries;
lakesLayer.FeatureClass = fcLakes;

6-42

Copyright 2001-2009 ESRI

Exercise 6B

countriesLayer.Name = "World Countries";


//countriesLayer.ShowTips = true;
lakesLayer.Name = "World Lakes";
//lakesLayer.ShowTips = false;
lakesLayer.Visible = false;

axMapControl1.AddLayer(countriesLayer);
axMapControl1.AddLayer(lakesLayer);

private void axTOCControl1_OnMouseDown(object sender,


ITOCControlEvents_OnMouseDownEvent e)
{
// ArcGIS Snippet Title:
// Find layer in TOC
//
// Long Description:
// Find the selected layer in the table of contents
//
// Intended ArcGIS Products for this snippet:
// ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
// ArcGIS Engine
//
// Applicable ArcGIS Product Versions:
// 9.2
// 9.3
//
// Notes:
// This snippet is intended to be inserted into the OnMouseDown event
// of the TOC Control
// The code assumes that a module-level variable (m_layer)
// has been declared as ILayer
IBasicMap map = null;
ILayer layer = null;
object other = null;
object index = null;
esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
axTOCControl1.HitTest(e.x, e.y, ref item, ref map, ref layer,
ref other, ref index);

if ((item == esriTOCControlItem.esriTOCControlItemLayer))
{
m_layer = layer as ILayer;
}

Copyright 2001-2009 ESRI

6-43

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private void chkShowTips_CheckStateChanged(object sender, System.EventArgs e)


{
// ArcGIS Snippet Title:
// Show tips
//
// Long Description:
// Show map tips
//
// Intended ArcGIS Products for this snippet:
// ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
// ArcGIS Engine
//
// Applicable ArcGIS Product Versions:
// 9.2
// 9.3
//
// Notes:
// This snippet is intended to be inserted into the CheckStateChanged
// event of a Visual Studio CheckBox
// The code assumes that a module-level variable (m_layer)
// has been declared as ILayer

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;
}
}
}

Copyright 2001-2009 ESRI

Exercise 6B

private void chkShowTips_CheckedChanged(object sender, EventArgs e)


{
if (chkShowTips.CheckState == CheckState.Checked)
{
axMapControl1.ShowMapTips = true;
else
axMapControl1.ShowMapTips = false;
}
}

Copyright 2001-2009 ESRI

6-45

7
Rendering data

Exercise 7A: Display layers (VB.NET)


Estimated time: 90 minutes
Exercise 7B: Display layers (C#)
Estimated time: 90 minutes

Exercise 7A

Exercise 7A: Display layers (VB.NET)


Estimated time: 90 minutes
In this exercise, you will display data in different ways by rendering a feature layer and a
raster layer. In addition, you will save symbology to a layer file, which can then be used
by others who access the same data.
In this exercise, you will:

Create a simple renderer


Create a raster renderer
Save symbology to a layer file

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

3. Apply an RGB renderer to render raster data.


4. Save the symbology you created to a layer (.lyr) file.
** (Optional) Apply a scale-dependent renderer to set a scale threshold to the layers.
** (Optional) Apply a stretch color ramp renderer to render your raster data.

Step 1: Open a Visual Studio project


To save time, you will begin by opening a project that has already been started for you.
Start Visual Studio.
From the File menu, choose Open Project.
Browse to your \Student\IPAN\Exercise07\VisualBasic\DisplayingData folder and
open the DisplayingData solution.

Copyright 2001-2009 ESRI

7-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

View MainForm in code view.


Notice that the project contains many lines of pre-written code.
To reduce the code that you need to scroll through, by right-click anywhere in the code
window and choose Outlining > Collapse to Definitions.
View MainForm in Design view.
This project is based on the ArcGIS Engine MapControl Application template and
contains four ArcGIS Engine controls: a ToolbarControl, TOCControl, MapControl, and
LicenseControl. In addition, several Visual Studio controls have been added for choosing
renderer properties at run time.
Using the Properties window, note the names of some of the controls.
You will use these names in the code later.
Before continuing, decide which type of data you want to work with in this exercise.
Choose one of the following options:

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.

Step 2: Create a fill symbol for vector polygons


In this step, you will create a new fill symbol, set properties on it, and then apply it to a
polygon layer with a simple renderer.
Double-click the Render button on the form to view the code for its Click event
(btnRender_Click).
When a user clicks this button, a new renderer will be applied to the layer that the user
specifies.
Examine the first two lines of code.
This code creates a reference to the chosen layer by passing the selected name in the
cboLayer combo box to the GetLayerByName function, which has been written for you.
You will browse the code in the function to learn how it works.

7-2

Copyright 2001-2009 ESRI

Exercise 7A

Right-click the GetLayerByName and choose Go To Definition, as shown below.

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.

You are now ready to create a simple renderer.


Return to the Click event for the Render button.
After the selected layer is referenced, a Select Case statement constructs the feature
renderer. The Select Case statement is based on the m_strOption variable, which is set
every time the combo boxes are changed.
Under the Case "Simple" statement, complete the following code to create a new
simple fill symbol:
Dim sym As ______________________________ = New ____________________________

Now set the style to a solid fill for your symbol by completing the following code:
sym.__________

= esriSimpleFillStyle.________________________

Complete the following code to create a new RgbColor object:


Dim color As __________________ = ______ ________________

Define the color using the following code:

Copyright 2001-2009 ESRI

7-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

color.RGB = RGB(CInt(cboRed.Text), CInt(cboGreen.Text), CInt(cboBlue.Text))


The CInt function converts an expression to Integer data type.
Assign color to your new symbol.
Call the ApplySimple method to create and apply a simple renderer with your symbol:
ApplySimple(geoLayer, CType(sym, ISymbol)

Navigate to the ApplySimple sub procedure.


Question 1: Which object (or interface) has the Symbol property? Which has the
Renderer property?
______________________________________________________________________

Step 3: Render vector layers


In this step, you will render using the code you just wrote, and then you will explore the
code for other renderers and test them.
In Design view, open the Properties dialog box for your MapControl and do the
following:

For Map Document, browse to \Student\IPAN\Exercise07 and open


Rendering.mxd.
For Available Maps, choose Feature Rendering.

Click OK.

In code view, navigate to the AddLayersToComboBox sub procedure and uncomment it.

7-4

Copyright 2001-2009 ESRI

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

Question 3: Which ArcGIS reference do you need to add to your project?


______________________________________________________________________

Copyright 2001-2009 ESRI

7-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Add the necessary reference.


Build and run your project.
To apply a class breaks renderer, do the following in your application:

In the table of contents, turn on the Counties layer.


From the Feature Layer drop-down list, choose Counties.
Choose the Class Breaks option, then choose any field from the drop-down list.
Click Render to apply your class breaks renderer to the field.

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.

Step 4: Apply an RGB renderer to raster data


In this step, you will render raster data using an RGB renderer. With a new
RasterRGBRenderer, you can switch the band colors and thus change the display of the
raster.
In Design view, open the Properties dialog box for your MapControl and do the
following:

7-6

For Map Document, browse to \Student\IPAN\Exercise07 and open


Rendering.mxd.
For Available Maps, choose Raster Rendering.
Click OK.

Copyright 2001-2009 ESRI

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

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 sub procedure.
Complete the following code to access the map (data frame) and the first raster layer in
the active map:
Dim map As IMap
map = AxMapControl1.ActiveView.________________
Dim rLayer As ________________________
rLayer = map.Layer(0)

The Raster property on IRasterLayer represents a layer's raster object.


Create and set a variable to store the raster object:
Dim raster As IRaster
raster = rLayer.Raster

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 ______________________________

Copyright 2001-2009 ESRI

7-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Now do a QI from rgbRen to rasRen.


Use the Raster property on the renderer to connect the renderer with the raster, then
update the renderer:
rasRen.____________ = raster
rasRen.____________()

Test your code.


Note that the raster currently displays red in band 1, green in band 2, and blue in band 3.

Close your application.


Change the color displayed in each band using the following code:
rgbRen.RedBandIndex = 2
rgbRen.GreenBandIndex = 1
rgbRen.BlueBandIndex = 0
Note: The band numbers display as 1, 2, and 3, but like layers and maps, bands are
zero-based.

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

Copyright 2001-2009 ESRI

Exercise 7A

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.

Step 5: Save your symbology to a layer file


One advantage to creating symbology is that you can save it to a layer (.lyr) file. The file
can be shared with other users who access the same layers.
You will begin by adding code to select a layer in the table of contents.
Navigate to the OnMouseDown event for your TOCControl.
Insert the snippet IPAN_Ex06_TOC_HitTest (used in the previous exercise).
Read the comments.
Question 4: Which module-level variable do you need to declare?
______________________________________________________________________
______________________________________________________________________
Navigate to the Click event for btnSaveLayer.
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.

Copyright 2001-2009 ESRI

7-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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(______________)

Save the layer file:


layerFile.________()

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.

Save the layer file to your \Student\IPAN\Exercise07 folder.


Click OK on the message box.
Turn off and collapse the layer in the table of contents.
To confirm that your code is working, click the Add Data button
and add your new
layer file to the map. (Hint: In the dialog box that opens, on the left, click Layers.)

7-10

Copyright 2001-2009 ESRI

Exercise 7A

Close your application.


You have finished this exercise; however, you may wish to complete the optional steps:

Step 6 shows you how to create a scale-dependent renderer.


Step 7 shows you how to add a stretch color ramp renderer to symbolize raster
data.

If you want to complete the optional steps, do so now. Otherwise, close Visual Studio.

Step 6: (Optional) Apply a scale-dependent renderer


In ArcMap, you can change the way layers are rendered using the layer properties, or
through code. One example of functionality that can only be done through code is a
scale-dependent renderer, which combines several renderers into one layer. For example,
you can combine a simple renderer and a unique value renderer all within one layer. It is
scale-dependent because you set the scale threshold at which a particular renderer
displays.
Start ArcMap and choose to open an existing map.
Browse to \Student\IPAN\Exercise07 and open Scale_Renderer.mxd.
Note that the map contains three layers: COUNTY1, COUNTY2, and COUNTY3.
One by one, right-click each layer, choose Properties, and view the Source tab in the
Layer Properties dialog box.
Question 5: What feature class is used as the data source for all three layers?
______________________________________________________________________
Close the Layer Properties dialog box.
Expand each layer in the table of contents.
Notice that the same layer has been added three times, each time with different
symbology.

Copyright 2001-2009 ESRI

7-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

On the Tools toolbar, click the Zoom In tool


and drag a box around the
northwestern region of the continental United States.

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

Copyright 2001-2009 ESRI

Exercise 7A

Turn off the COUNTY2 layer.

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.

Copyright 2001-2009 ESRI

7-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 7A

In your code, scroll down a few lines to the IScaleDependentRenderer interface


code and view the portion that sets the scale thresholds for the renderers within the
scale-dependant renderer:
scaleDependentRenderer.Break(0) = 10000000
scaleDependentRenderer.Break(1) = 50000000
scaleDependentRenderer.Break(2) = 500000000

Run your project.


Click the Scale Dependent button.
Close the message boxes that appear.
A new layer named USA is added to the table of contents.

It may take a little time for the new layer to display in the table of
contents.

Turn off all layers except USA.


Click the Full Extent button

to view the map at a smaller map scale.

Click the Fixed Zoom In button


several times to zoom in past 1:10,000,000. (Tip:
Use the Pan tool
to keep your map in view.)
The simple renderer switches to unique values for states at 1:50,000,000, then to unique
values for counties at 1:10,000,000. There are three renderers embedded in the single
USA layer.
You created each renderer by referencing layers in the map document. Then, you added
them into the scale-dependent renderer. If you wanted, you could now save the USA
layer to a layer file and add it to other maps.
Close your application.
To learn how to add a stretch color ramp renderer to symbolize raster data, continue on
to the next step. Otherwise, close Visual Studio.

Step 7: (Optional) Apply a stretch renderer to raster data


In this step, you will apply a stretch color ramp renderer to your raster data. To save time,
you will work with some code that has already been written for you.

Copyright 2001-2009 ESRI

7-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

For Map Document, make sure \Student\IPAN\Exercise07\Rendering.mxd is


selected.
For Available Maps, make sure Raster Rendering is selected.
Click OK.

Run your project.


Click the Stretch Raster button on your form.

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

Copyright 2001-2009 ESRI

Exercise 7A

apply a scale-dependent renderer to vector data and a stretch color ramp renderer to raster
data for more sophisticated data display.

Copyright 2001-2009 ESRI

7-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 7A Questions


Question 1: Which object (or interface) has the Symbol property? Which has the
Renderer property?
Answer: ISimpleRenderer; IGeoFeatureLayer
Question 2: What types of layers are added to the cboLayer combo box?
Answer: Feature layerspoint, polyline, and polygon
Question 3: Which ArcGIS reference do you need to add to your project?
Answer: ESRI.ArcGIS.CartoUI
Question 4: Which module-level variable do you need to declare?
Answer: m_layer as ILayer (or m_layer as ILayer2)
Question 5: What feature class is used as the data source for all three layers?
Answer: USCounties
Question 6: What happens in the display when you zoom?
Answer: When you zoom out past 50,000,000, the simple renderer draws. When you
zoom within 50,000,000, the unique value renderer based on state name draws.
Question 7: What is returned when you use the Renderer property?
Answer: A reference to IFeatureRenderer

7-18

Copyright 2001-2009 ESRI

Exercise 7A

Exercise Solution: Exercise 7A (VB.NET)


Imports
Imports
Imports
Imports
Imports
Imports

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

' Used in AddLayersToComboBox()

ESRI.ArcGIS.CartoUI
ESRI.ArcGIS.DataSourcesRaster
ESRI.ArcGIS.Display
ESRI.ArcGIS.Geodatabase

Public Class MainForm


Private m_mapControl As IMapControl3 = Nothing
Private m_mapDocumentName As String = String.Empty
Private m_strOption As String
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
AddLayersToComboBox()
' Populate the color comboboxes with values 0 to 255
Dim i As Integer
For i = 0 To 255
If i > 1 And i < 11 Then cboBreaks.Items.Add(i)
cboRed.Items.Add(i)
cboGreen.Items.Add(i)
cboBlue.Items.Add(i)
cboRed.Text = "0"
cboGreen.Text = "0"
cboBlue.Text = "0"
Next i
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

Copyright 2001-2009 ESRI

7-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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)
'Make sure that the MapDocument is not readonly
If mapDoc.IsReadOnly(m_mapDocumentName) Then
MessageBox.Show("Map document is read only!")
mapDoc.Close()
Return
End If
'Replace its contents with the current map
mapDoc.ReplaceContents(CType(m_mapControl.Map, IMxdContents))
'save the MapDocument in order to persist it
mapDoc.Save(mapDoc.UsesRelativePaths, False)
'close the MapDocument
mapDoc.Close()
End If
End Sub
Private Sub menuSaveAs_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles menuSaveAs.Click
'execute SaveAs Document command
Dim command As ICommand = New ControlsSaveAsDocCommandClass()
command.OnCreate(m_mapControl.Object)
command.OnClick()
End Sub
Private Sub menuExitApp_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles menuExitApp.Click
'exit the application
Application.Exit()
End Sub
#End Region
'listen to MapReplaced event in order to update the statusbar and the Save menu
Private Sub axMapControl1_OnMapReplaced(ByVal sender As Object, _
ByVal e As IMapControlEvents2_OnMapReplacedEvent) _
Handles axMapControl1.OnMapReplaced
'get the current document name from the MapControl
m_mapDocumentName = m_mapControl.DocumentFilename

7-20

Copyright 2001-2009 ESRI

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

Copyright 2001-2009 ESRI

7-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Find layer in TOC
Long Description:
Find the selected layer in the table of contents
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted into the OnMouseDown
event of the TOC Control.
The code assumes that a module-level variable (m_layer)
has been declared as ILayer

Dim
Dim
Dim
Dim
Dim

map As Map = Nothing


layer As ILayer = Nothing
other As Object = Nothing
item As esriTOCControlItem
index As Object = Nothing

Dim toc As ITOCControl2 = AxTOCControl1.Object


toc.HitTest(e.x, e.y, item, map, layer, other, index)
If item = esriTOCControlItem.esriTOCControlItemLayer Then
m_layer = CType(layer, ILayer)
Me.Text = "Selected layer is: " & m_layer.Name
End If
End Sub
Public Sub ApplySimple(ByVal geoLayer As IGeoFeatureLayer, _
ByVal aSymbol As ISymbol)
Dim simpleRenderer As ISimpleRenderer
simpleRenderer = New SimpleRenderer
simpleRenderer.Symbol = CType(aSymbol, ISymbol)
geoLayer.Renderer = CType(simpleRenderer, IFeatureRenderer)
AxMapControl1.ActiveView.Refresh()
AxTOCControl1.Update()
End Sub
Public Sub ApplyUniqueValue(ByVal geoLayer As IGeoFeatureLayer, _
ByVal aFieldName As String)
Dim uniqueRenderer As IUniqueValueRenderer
uniqueRenderer = New UniqueValueRenderer
uniqueRenderer.FieldCount = 1
uniqueRenderer.Field(0) = aFieldName

7-22

Copyright 2001-2009 ESRI

Exercise 7A

Dim intFieldIndex As Integer


intFieldIndex = geoLayer.FeatureClass.FindField(aFieldName)
Dim fCursor As IFeatureCursor
Dim qFilter As IQueryFilter
qFilter = New QueryFilter
qFilter.SubFields = aFieldName
fCursor = geoLayer.FeatureClass.Search(qFilter, True)
Dim randomColors As IRandomColorRamp
randomColors = New RandomColorRamp
randomColors.Size = 16
Dim bOK As Boolean
randomColors.CreateRamp(bOK)
If Not bOK Then Exit Sub
Dim enumColor As IEnumColors
enumColor = randomColors.Colors
Dim sym As ISimpleFillSymbol
Dim color As IColor
Dim feature As IFeature
feature = fCursor.NextFeature
Do Until feature Is Nothing
sym = New SimpleFillSymbol
color = enumColor.Next
If color Is Nothing Then
enumColor.Reset()
color = enumColor.Next
End If
sym.Style = esriSimpleFillStyle.esriSFSSolid
sym.Color = color
uniqueRenderer.AddValue(feature.Value(intFieldIndex).ToString(), "", _
CType(sym, ISymbol))
feature = fCursor.NextFeature
Loop
geoLayer.Renderer = CType(uniqueRenderer, IFeatureRenderer)
AxMapControl1.ActiveView.Refresh()
AxTOCControl1.Update()
End Sub
Public Sub ApplyClassBreaks(ByVal geoLayer As IGeoFeatureLayer, _
ByVal aFieldName As String, ByVal numBreaks As Long)
' Create a table from the geo feature layer
Dim table As ITable
table = CType(geoLayer, ITable)
Dim tableHistogram As ITableHistogram
tableHistogram = New TableHistogram
tableHistogram.Table = table 'equivalent to geoLayer.FeatureClass
' Retrieve frequency data from the field
tableHistogram.Field = aFieldName

Copyright 2001-2009 ESRI

7-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

'MessageBox.Show("Field is: " & tableHistogram.Field)


Dim histogram As IHistogram
histogram = CType(tableHistogram, IHistogram)
'histogram = tableHistogram
Dim vValues As Object
Dim vFreqs As Object
histogram.GetHistogram(vValues, vFreqs)
' Classify the data
Dim classify As IClassifyGEN
classify = New EqualInterval
classify.Classify(vValues, vFreqs, CInt(numBreaks))
Dim vBreaks As Object
vBreaks = classify.ClassBreaks
' Create the class breaks renderer
Dim classBreaksRenderer As IClassBreaksRenderer
classBreaksRenderer = New ClassBreaksRenderer
classBreaksRenderer.Field = aFieldName ' passed as a String to the Sub
classBreaksRenderer.BreakCount = CType(numBreaks, Integer)
' Set the begin and end colors
Dim fromColor As IRgbColor = New RgbColor
fromColor.RGB = RGB(255, 255, 0)
Dim toColor As IRgbColor = New RgbColor
toColor.RGB = RGB(255, 0, 0)
Dim colors As IEnumColors
colors = GetColors(fromColor.RGB, toColor.RGB, numBreaks)
' Set up the fill symbol
Dim sym As ISimpleFillSymbol
Dim color As IColor
Dim i As Integer
For i = 0 To UBound(vBreaks) - 1
sym = New SimpleFillSymbol
color = colors.Next
sym.Color = color
classBreaksRenderer.Break(i) = vBreaks(i + 1)
classBreaksRenderer.Symbol(i) = CType(sym, ISymbol)
Next i
geoLayer.Renderer = CType(classBreaksRenderer, IFeatureRenderer)
AxMapControl1.ActiveView.Refresh()
AxTOCControl1.Update()
End Sub
Public Function GetColors(ByVal vbStartColor As Long, _
ByVal vbEndColor As Long, _
ByVal Colors As Long) As IEnumColors

7-24

Copyright 2001-2009 ESRI

Exercise 7A

Dim startColor As IRgbColor


Dim endColor As IRgbColor
startColor = New RgbColor
endColor = New RgbColor
startColor.RGB = CInt(vbStartColor)
endColor.RGB = CInt(vbEndColor)
Dim ramp As IAlgorithmicColorRamp
ramp = New AlgorithmicColorRamp
ramp.Algorithm = esriColorRampAlgorithm.esriHSVAlgorithm
ramp.FromColor = startColor
ramp.ToColor = endColor
ramp.Size = CInt(Colors)
Dim blnIsRampOK As Boolean
ramp.CreateRamp(blnIsRampOK)
If Not blnIsRampOK Then
GetColors = Nothing ' Formerly Exit Function
Else
GetColors = ramp.Colors
End If
End Function
Private Sub btnRender_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnRender.Click
Dim geoLayer As IGeoFeatureLayer
geoLayer = GetLayerByName(cboLayer.Text)
Select Case m_strOption
Case "Simple"
'Step 1: code here to create a new fill symbol and color
'code here to create a new fill symbol and color
Dim sym As ISimpleFillSymbol
sym = New SimpleFillSymbol
sym.Style = esriSimpleFillStyle.esriSFSSolid
Dim color As IRgbColor
color = New RgbColor
color.RGB = RGB(CInt(cboRed.Text), CInt(cboGreen.Text), _
CInt(cboBlue.Text))
sym.Color = color
'pass the layer and symbol to the ApplySimple method
ApplySimple(geoLayer, CType(sym, ISymbol))

Copyright 2001-2009 ESRI

7-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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))

Private Sub cboLayer_Change()


Dim strLayerName As String
strLayerName = cboLayer.Text
Try

If strLayerName <> "" Then


btnRender.Enabled = True
optSimple.Enabled = True
optUnique.Enabled = True
optBreaks.Enabled = True
optSimple.Text = "True"
Else
btnRender.Enabled = False
m_strOption = "NoLayer"
Call OptionEnabler()
Exit Sub
End If
'On Error GoTo LayerNotFound
Dim fLayer As IFeatureLayer
fLayer = GetLayerByName(strLayerName)
FillFieldsComboBox(fLayer)
Exit Sub

Catch noLayer As Exception


btnRender.Enabled = False
m_strOption = "NoLayer"
Call OptionEnabler()
Exit Sub
End Try
End Sub
Private Sub btnClose_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnClose.Click
Me.Close()
End Sub
Private Sub AddLayersToComboBox()
Dim allFLayers As IEnumLayer
Dim uid As New UID 'Dim uid As New esriSystem.UID
uid.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"
allFLayers = AxMapControl1.ActiveView.FocusMap.Layers(uid, True)

7-26

Copyright 2001-2009 ESRI

Exercise 7A

Dim fLayer As IFeatureLayer


fLayer = CType(allFLayers.Next(), IFeatureLayer)
Do Until fLayer Is Nothing
If fLayer.FeatureClass.ShapeType = _
esriGeometryType.esriGeometryPolygon Then
cboLayer.Items.Add(fLayer.Name)
ElseIf fLayer.FeatureClass.ShapeType = _
esriGeometryType.esriGeometryPolyline Then
cboLayer.Items.Add(fLayer.Name)
ElseIf fLayer.FeatureClass.ShapeType = _
esriGeometryType.esriGeometryPoint Then
cboLayer.Items.Add(fLayer.Name)
End If
fLayer = CType(allFLayers.Next(), IFeatureLayer)
Loop
End Sub
Private Function GetLayerByName(ByVal LayerName As String) As IGeoFeatureLayer
Dim uid As UID = New UID
'This is the ID for layers supporting the IGeoFeatureLayer interface
uid.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}"
'Get all the FeatureLayers from the map using the UID
Dim allFLayers As IEnumLayer
allFLayers = AxMapControl1.ActiveView.FocusMap.Layers(uid, True)
'Loop thru all FeatureLayers until LayerName is found
Dim layer As ILayer
layer = allFLayers.Next
Do Until layer Is Nothing
If layer.Name = LayerName Then
Exit Do
End If
layer = allFLayers.Next
Loop
'Pass back the requested layer
GetLayerByName = CType(layer, IGeoFeatureLayer)
End Function
Private Sub OptionEnabler()
Dim cntrl As Windows.Forms.Control
For Each cntrl In Me.Controls
If cntrl.Tag Is "CheckEnable" Then cntrl.Enabled = False
Next cntrl

Copyright 2001-2009 ESRI

7-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Select Case m_strOption


Case "Simple"
lblR.Enabled = True
lblG.Enabled = True
lblB.Enabled = True
cboRed.Enabled = True
cboGreen.Enabled = True
cboBlue.Enabled = True
Case "Unique"
cboUniqueVals.Enabled = True
Case "Breaks"
cboNumericVals.Enabled = True
cboBreaks.Enabled = True
lblBreaks.Enabled = True
Case "NoLayer"
optSimple.Enabled = False
optUnique.Enabled = False
optBreaks.Enabled = False
End Select
End Sub
Private Sub FillFieldsComboBox(ByVal geoLayer As IFeatureLayer)
Dim pFClass As IFeatureClass
pFClass = geoLayer.FeatureClass
Dim pFields As IFields
pFields = pFClass.Fields
cboNumericVals.Items.Clear()
cboUniqueVals.Items.Clear()
Dim pFld As IField
Dim i As Integer
For i = 0 To pFields.FieldCount - 1
pFld = pFields.Field(i)
If pFld.Type <= 3 Then cboNumericVals.Items.Add(pFld.Name) 'numeric
If pFld.Type <= 5 Then cboUniqueVals.Items.Add(pFld.Name)
'not shape, OID, or BLOB
Next i
End Sub
Private Sub cboLayer_SelectedValueChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles cboLayer.SelectedValueChanged

7-28

Copyright 2001-2009 ESRI

Exercise 7A

Dim strLayerName As String


strLayerName = cboLayer.Text
Try
If strLayerName <> "" Then
btnRender.Enabled = True
optSimple.Enabled = True
optUnique.Enabled = True
optBreaks.Enabled = True
optSimple.Equals(True)
Else
btnRender.Enabled = False
m_strOption = "NoLayer"
Call OptionEnabler()
Exit Sub
End If
Dim fLayer As IFeatureLayer
fLayer = GetLayerByName(strLayerName)
FillFieldsComboBox(fLayer)
Catch excGeneric As Exception
btnRender.Enabled = False
btnSaveLayer.Enabled = False
m_strOption = "NoLayer"
Call OptionEnabler()
MessageBox.Show("No layer selected")
End Try
End Sub
Private Sub btnChangeRGBRenderer_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnChangeRGBRenderer.Click
''ChangeRGBRenderer()
''RGB Raster rendering:
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
Dim bandCol As IRasterBandCollection
bandCol = CType(raster, IRasterBandCollection)
If bandCol.Count < 3 Then Exit Sub
' Create RGBValue renderer and QI RasterRenderer
Dim rgbRen As IRasterRGBRenderer = New RasterRGBRenderer
Dim rasRen As IRasterRenderer
rasRen = CType(rgbRen, IRasterRenderer)
' Connect the renderer and the raster
rasRen.Raster = raster
rasRen.Update()

Copyright 2001-2009 ESRI

7-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Save Layer File
Long Description:
Display save dialog
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted into the
Click event of a Visual Studio button
The code assumes that a module-level variable (m_layer)
has been declared as ILayer.

Dim saveFileDialog As SaveFileDialog = New SaveFileDialog()


saveFileDialog.Filter = "Layer File|*.lyr|All Files|*.*"
saveFileDialog.Title = "Create Layer File"
saveFileDialog.RestoreDirectory = True
saveFileDialog.FileName = _
System.IO.Path.Combine _
(saveFileDialog.InitialDirectory, _
m_layer.Name & ".lyr")
'Show the dialog.
saveFileDialog.ShowDialog()
Dim path As String
path = saveFileDialog.FileName
'Create a new LayerFile instance.
Dim layerFile As ILayerFile = New LayerFile
'Create a new layer file.
layerFile.[New] (path)
'Bind the layer file with the layer from the map.
layerFile.ReplaceContents(CType(m_layer))
layerFile.Save()
MessageBox.Show(m_layer.Name & " has been saved to " & path)

7-30

Copyright 2001-2009 ESRI

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)

Copyright 2001-2009 ESRI

7-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

'Plug this colorramp into renderer and select a band


stretchRen.BandIndex = 0
stretchRen.ColorRamp = ramp
'Update the renderer with new settings and plug into layer
rasRen.Update()
rLayer.Renderer = CType(stretchRen, IRasterRenderer)
AxMapControl1.ActiveView.Refresh()
AxTOCControl1.Update()
End Sub
Private Sub btnScale_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnScale.Click
'This code creates a scale dependent renderer with three scale thresholds
'The code creates pointers to the three existing layers
'plus the new layer that is
'created with the scale dependent renderer.
Dim map As IMap
map = AxMapControl1.ActiveView.FocusMap
'Reference IFeatureLayer
Dim fLayer1 As IFeatureLayer
Dim fLayer2 As IFeatureLayer
Dim fLayer0 As IFeatureLayer
'Instantiate your feature layers to current map layers
fLayer0 = CType(map.Layer(2), IFeatureLayer)
fLayer1 = CType(map.Layer(1), IFeatureLayer)
fLayer2 = CType(map.Layer(0), IFeatureLayer)
'MessageBox.Show("Layer 0 is " & fLayer0.Name)
'MessageBox.Show("Layer 1 is " & fLayer1.Name)
'MessageBox.Show("Layer 2 is " & fLayer2.Name)
fLayer2.MinimumScale = 500000000
MessageBox.Show("Layer2 max scale: " & fLayer2.Name & " " & _
fLayer2.MaximumScale.ToString())
MessageBox.Show("Layer2 min scale: " & fLayer2.MinimumScale.ToString())
Dim newFLayer As IFeatureLayer
newFLayer = New FeatureLayer
newFLayer.Name = "USA"
'Set the feature class of the new Layer to be the same as that of one of the
'existing layers.
Dim featureClass As IFeatureClass
featureClass = fLayer1.FeatureClass
newFLayer.FeatureClass = featureClass

7-32

Copyright 2001-2009 ESRI

Exercise 7A

'QI to the IGeofeatureLayer interface to work with the renderers.


Dim geoFLayer0 As IGeoFeatureLayer
Dim geoFLayer1 As IGeoFeatureLayer
Dim geoFLayer2 As IGeoFeatureLayer
Dim newGeoFLayer As IGeoFeatureLayer
geoFLayer0 = CType(fLayer0, IGeoFeatureLayer)
geoFLayer1 = CType(fLayer1, IGeoFeatureLayer)
geoFLayer2 = CType(fLayer2, IGeoFeatureLayer)
newGeoFLayer = CType(newFLayer, IGeoFeatureLayer)
'Create a new scale dependent renderer
Dim scaleDependentRenderer As IScaleDependentRenderer
scaleDependentRenderer = New ScaleDependentRenderer
'Grab the renderers from the existing layers
Dim renderer0 As IFeatureRenderer
Dim renderer1 As IFeatureRenderer
Dim renderer2 As IFeatureRenderer
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
'Associate the scale dependent renderer with the new layer
'Add the scale dependent renderer to the map
newGeoFLayer.Renderer = CType(scaleDependentRenderer, IFeatureRenderer)
map.AddLayer(newGeoFLayer)
End Sub
End Class

Copyright 2001-2009 ESRI

7-33

Exercise 7B

Exercise 7B: Display layers (C#)


Estimated time: 90 minutes
In this exercise, you will display data in different ways by rendering a feature layer and a
raster layer. In addition, you will save symbology to a layer file, which can then be used
by others who access the same data.
In this exercise, you will:

Create a simple renderer


Create a raster renderer
Save symbology to a layer file

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

3. Apply an RGB renderer to render raster data.


4. Save the symbology you created to a layer (.lyr) file.
** (Optional) Apply a scale-dependent renderer to set a scale threshold to the layers.
** (Optional) Apply a stretch color ramp renderer to render your raster data.

Step 1: Open a Visual Studio project


To save time, you will begin by opening a project that has already been started for you.
Start Visual Studio.
From the File menu, choose Open Project.
Browse to your \Student\IPAN\Exercise07\CSharp\DisplayingData folder and open the
DisplayingData solution.

Copyright 2001-2009 ESRI

7-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

View MainForm in code view.


Notice that the project contains many lines of pre-written code.
To reduce the code that you need to scroll through, by right-click anywhere in the code
window and choose Outlining > Collapse to Definitions.
View MainForm in Design view.
This project is based on the ArcGIS Engine MapControl Application template and
contains four ArcGIS Engine controls: a ToolbarControl, TOCControl, MapControl, and
LicenseControl. In addition, several Visual Studio controls have been added for choosing
renderer properties at run time.
Using the Properties window, note the names of some of the controls.
You will use these names in the code later.
Before continuing, decide which type of data you want to work with in this exercise.
Choose one of the following options:

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.

Step 2: Create a fill symbol for vector polygons


In this step, you will create a new fill symbol, set properties on it, and then apply it to a
polygon layer with a simple renderer.
Navigate to the btnRender_Click method in the code view.
When a user clicks this button, a new renderer will be applied to the layer that the user
specifies.
Examine the first two lines of code.
This code creates a reference to the chosen layer by passing the selected name in the
cboLayer combo box to the GetLayerByName function, which has been written for you.
You will browse the code in the function to learn how it works.

7-36

Copyright 2001-2009 ESRI

Exercise 7B

Right-click the GetLayerByName and choose Go To Definition, as shown below.

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.

You are now ready to create a simple renderer.


Return to the Click event for the Render button.
After the selected layer is referenced, a switch structure constructs the feature renderer.
The switch structure is based on the m_strOption variable, which is set every time the
combo boxes are changed.
Under the case "Simple" statement, complete the following code to create a new
simple fill symbol:
__________________________________ sym = new _____________________________();

Now set the style to a solid fill for your symbol by completing the following code:
sym.__________

= esriSimpleFillStyle.________________________;

Complete the following code to create a new RgbColor object:


__________________ color = ______ ________________();

Copyright 2001-2009 ESRI

7-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Define the color using the following code:


color.Red = Convert.ToInt32(cboRed.Text);

The Convert.ToInt32 function converts the specified string representation of a number


to an equivalent 32-bit signed integer.
Repeat for Green and Blue.
Assign the new color to your new symbol.
Call the ApplySimple method to create and apply a simple renderer with your symbol:
ApplySimple(geoLayer, sym as ISymbol);
break;

Navigate to the ApplySimple method.


Question 1: Which object (or interface) has the Symbol property? Which has the
Renderer property?
______________________________________________________________________

Step 3: Render vector layers


In this step, you will render using the code you just wrote, and then you will explore the
code for other renderers and test them.
In Design view, open the Properties dialog box for your MapControl and do the
following:

7-38

For Map Document, browse to \Student\IPAN\Exercise07 and open


Rendering.mxd.
For Available Maps, choose Feature Rendering.

Copyright 2001-2009 ESRI

Exercise 7B

Click OK.

In code view, navigate to the AddLayersToComboBox method and uncomment it.


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.
Click Render to apply your single color, simple renderer 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.

Copyright 2001-2009 ESRI

7-39

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Navigate to the following MainForm methods and functions, and uncomment the code
in each:

ApplyUniqueValue
ApplyClassBreaks
GetColors

Be sure to uncomment the GetColors argument list.

FillFieldsComboBox

Question 3: Which ArcGIS references do you need to add to your project?


______________________________________________________________________
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.

Add the necessary references. (Hint: Be sure to add Microsoft.VisualBasic.)


Build and run your project.
To apply a class breaks renderer, do the following in your application:

In the table of contents, turn on the Counties layer.


From the Feature Layer drop-down list, choose Counties.
Choose the Class Breaks option, then choose any field from the drop-down list.
Click Render to apply your class breaks renderer to the field.

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

Copyright 2001-2009 ESRI

Exercise 7B

Step 4: Apply an RGB renderer to raster data


In this step, you will render raster data using an RGB renderer. With a new
RasterRGBRenderer, you can switch the band colors and thus change the display of the
raster.
In Design view, open the Properties dialog box for your MapControl and do the
following:

For Map Document, browse to \Student\IPAN\Exercise07 and open


Rendering.mxd.
For Available Maps, choose Raster Rendering.
Click OK.

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;

The Raster property on IRasterLayer represents a layer's raster object.


Create and set a variable to store the raster object:
IRaster raster;
raster = rLayer.Raster;

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.

Copyright 2001-2009 ESRI

7-41

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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;

Now cast from rgbRen to rasRen.


Use the Raster property on the renderer to connect the renderer with the raster, then
update the renderer:
rasRen.___________ = raster;
rasRen.____________();

Test your code.


Note that the raster currently displays red in band 1, green in band 2, and blue in band 3.

Close your application.


Change the color displayed in each band using the following code:
rgbRen.RedBandIndex = 2;
rgbRen.GreenBandIndex = 1;
rgbRen.BlueBandIndex = 0;
Note: The band numbers display as 1, 2, and 3, but like layers and maps, bands are
zero-based.

Update the renderer to reflect the new properties and tie it to the layer:

7-42

Copyright 2001-2009 ESRI

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.

Step 5: Save your symbology to a layer file


One advantage to creating symbology is that you can save it to a layer (.lyr) file. The file
can be shared with other users who access the same layers.
You will begin by adding code to select a layer in the table of contents.
Navigate to the OnMouseDown event for your TOCControl.
Insert the snippet IPAN_Ex06_TOC_HitTest (used in the previous exercise).
Read the comments.
Question 4: Which module-level variable do you need to declare?
______________________________________________________________________
______________________________________________________________________
Navigate to the click event for btnSaveLayer.

Copyright 2001-2009 ESRI

7-43

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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(______________);

Save the layer file:


layerFile.________();

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.

Save the layer file to your \Student\IPAN\Exercise07 folder.


Click OK on the message box.

7-44

Copyright 2001-2009 ESRI

Exercise 7B

Turn off and collapse the layer in the table of contents.


To confirm that your code is working, click the Add Data button
and add your new
layer file to the map. (Hint: In the dialog box that opens, on the left, click Layers.)
Close your application.
You have finished this exercise; however, you may wish to complete the optional steps:

Step 6 shows you how to create a scale-dependent renderer.


Step 7 shows you how to add a stretch color ramp renderer to symbolize raster
data.

If you want to complete the optional steps, do so now. Otherwise, close Visual Studio.

Step 6: (Optional) Apply a scale-dependent renderer


In ArcMap, you can change the way layers are rendered using the layer properties, or
through code. One example of functionality that can only be done through code is a
scale-dependent renderer, which combines several renderers into one layer. For example,
you can combine a simple renderer and a unique value renderer all within one layer. It is
scale-dependent because you set the scale threshold at which a particular renderer
displays.
Start ArcMap and choose to open an existing map.
Browse to \Student\IPAN\Exercise07 and open Scale_Renderer.mxd.
Note that the map contains three layers: COUNTY1, COUNTY2, and COUNTY3.
One by one, right-click each layer, choose Properties, and view the Source tab in the
Layer Properties dialog box.
Question 5: What feature class is used as the data source for all three layers?
______________________________________________________________________
Close the Layer Properties dialog box.
Expand each layer in the table of contents.
Notice that the same layer has been added three times, each time with different
symbology.

Copyright 2001-2009 ESRI

7-45

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

On the Tools toolbar, click the Zoom In tool


and drag a box around the
northwestern region of the continental United States.

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

Copyright 2001-2009 ESRI

Exercise 7B

Turn off the COUNTY2 layer.

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.

Copyright 2001-2009 ESRI

7-47

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

In the btnScale_Click method, 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-48

Copyright 2001-2009 ESRI

Exercise 7B

In your code, scroll down a few lines to the IScaleDependentRenderer interface


code and view the portion that sets the scale thresholds for the renderers within the
scale-dependant renderer:
scaleDependentRenderer.set_Break(0) = 10000000
scaleDependentRenderer.set_Break(1) = 50000000
scaleDependentRenderer.set_Break(2) = 500000000

Run your project.


Click the Scale Dependent button.
Close the message boxes that appear.
A new layer named USA is added to the table of contents.

It may take a little time for the new layer to display in the table of
contents.

Turn off all layers except USA.


Click the Full Extent button

to view the map at a smaller map scale.

Click the Fixed Zoom In button


several times to zoom in past 1:10,000,000. (Tip:
Use the Pan tool
to keep your map in view.)
The simple renderer switches to unique values for states at 1:50,000,000, then to unique
values for counties at 1:10,000,000. There are three renderers embedded in the single
USA layer.
You created each renderer by referencing layers in the map document. Then, you added
them into the scale-dependent renderer. If you wanted, you could now save the USA
layer to a layer file and add it to other maps.
Close your application.
To learn how to add a stretch color ramp renderer to symbolize raster data, continue on
to the next step. Otherwise, close Visual Studio.

Step 7: (Optional) Apply a stretch renderer to raster data


In this step, you will apply a stretch color ramp renderer to your raster data. To save time,
you will work with some code that has already been written for you.

Copyright 2001-2009 ESRI

7-49

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

For Map Document, make sure \Student\IPAN\Exercise07\Rendering.mxd is


selected.
For Available Maps, make sure Raster Rendering is selected.
Click OK.

Run your project.


Click the Stretch Raster button on your form.

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

Copyright 2001-2009 ESRI

Exercise 7B

apply a scale-dependent renderer to vector data and a stretch color ramp renderer to raster
data for more sophisticated data display.

Copyright 2001-2009 ESRI

7-51

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 7B Questions


Question 1: Which object (or interface) has the Symbol property? Which has the
Renderer property?
Answer: ISimpleRenderer; IGeoFeatureLayer
Question 2: What types of layers are added to the cboLayer combo box?
Answer: Feature layerspoint, polyline, and polygon
Question 3: Which ArcGIS references do you need to add to your project?
Answer: ESRI.ArcGIS.Geodatabase and ESRI.ArcGIS.CartoUI
Question 4: Which module-level variable do you need to declare?
Answer: m_layer as ILayer (or m_layer as ILayer2)
Question 5: What feature class is used as the data source for all three layers?
Answer: USCounties
Question 6: What happens in the display when you zoom?
Answer: When you zoom out past 50,000,000, the simple renderer draws. When you
zoom within 50,000,000, the unique value renderer based on state name draws.
Question 7: What is returned when you use the Renderer property?
Answer: A reference to IFeatureRenderer

7-52

Copyright 2001-2009 ESRI

Exercise 7B

Exercise Solution: Exercise 7B (C#)


using
using
using
using
using
using
using
using

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();

Copyright 2001-2009 ESRI

7-53

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

for (int i = 0; (i < 255); i++)


{
if (((i > 1)
&& (i < 11)))
{
cboBreaks.Items.Add(i);
}
cboRed.Items.Add(i);
cboGreen.Items.Add(i);
cboBlue.Items.Add(i);
cboRed.Text = "0";
cboGreen.Text = "0";
cboBlue.Text = "0";
}
}
#region Main Menu event handlers
private void menuNewDoc_Click(object sender, EventArgs e)
{
//execute New Document command
ICommand command = new CreateNewDocument();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuOpenDoc_Click(object sender, EventArgs e)
{
//execute Open Document command
ICommand command = new ControlsOpenDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuSaveDoc_Click(object sender, EventArgs e)
{
//execute Save Document command
if (m_mapControl.CheckMxFile(m_mapDocumentName))
{
//create a new instance of a MapDocument
IMapDocument mapDoc = new MapDocumentClass();
mapDoc.Open(m_mapDocumentName, string.Empty);
//Make sure that the MapDocument is not readonly
if (mapDoc.get_IsReadOnly(m_mapDocumentName))
{
MessageBox.Show("Map document is read only!");
mapDoc.Close();
return;
}
//Replace its contents with the current map
mapDoc.ReplaceContents((IMxdContents)m_mapControl.Map);
//save the MapDocument in order to persist it
mapDoc.Save(mapDoc.UsesRelativePaths, false);

7-54

Copyright 2001-2009 ESRI

Exercise 7B

//close the MapDocument


mapDoc.Close();

private void menuSaveAs_Click(object sender, EventArgs e)


{
//execute SaveAs Document command
ICommand command = new ControlsSaveAsDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuExitApp_Click(object sender, EventArgs e)
{
//exit the application
Application.Exit();
}
#endregion
//listen to MapReplaced event in order to
//update the statusbar and the Save menu
private void axMapControl1_OnMapReplaced(
object sender, IMapControlEvents2_OnMapReplacedEvent e)
{
//get the current document name from the MapControl
m_mapDocumentName = m_mapControl.DocumentFilename;

//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);
}

public void ApplySimple(IGeoFeatureLayer geoLayer, ISymbol aSymbol)


{
ISimpleRenderer simpleRenderer;
simpleRenderer = new SimpleRenderer();
simpleRenderer.Symbol = aSymbol as ISymbol;
geoLayer.Renderer = simpleRenderer as IFeatureRenderer;
axMapControl1.ActiveView.Refresh();
axTOCControl1.Update();
}

Copyright 2001-2009 ESRI

7-55

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

public void ApplyUniqueValue(IGeoFeatureLayer geoLayer, string aFieldName)


{
IUniqueValueRenderer uniqueRenderer;
uniqueRenderer = new UniqueValueRenderer();
uniqueRenderer.FieldCount = 1;
uniqueRenderer.set_Field(0, aFieldName);
int intFieldIndex;
intFieldIndex = geoLayer.FeatureClass.FindField(aFieldName);
IFeatureCursor fCursor;
IQueryFilter qFilter;
qFilter = new QueryFilter();
qFilter.SubFields = aFieldName;
fCursor = geoLayer.FeatureClass.Search(qFilter, true);
IRandomColorRamp randomColors;
randomColors = new RandomColorRamp();
randomColors.Size = 16;
bool bOK;
randomColors.CreateRamp(out bOK);
if (!bOK)
{
return;
}
IEnumColors enumColor;
enumColor = randomColors.Colors;
ISimpleFillSymbol sym;
IColor color;
IFeature feature;
feature = fCursor.NextFeature();
while (feature != null)
{
sym = new SimpleFillSymbol();
color = enumColor.Next();
if ((color == null))
{
enumColor.Reset();
color = enumColor.Next();
}
sym.Style = esriSimpleFillStyle.esriSFSSolid;
sym.Color = color;
Console.WriteLine(feature.get_Value(intFieldIndex).ToString());
uniqueRenderer.AddValue(
feature.get_Value(intFieldIndex).ToString(), "",
((ISymbol)(sym)));
feature = fCursor.NextFeature();
}
geoLayer.Renderer = ((IFeatureRenderer)(uniqueRenderer));
axMapControl1.ActiveView.Refresh();
axTOCControl1.Update();
}

7-56

Copyright 2001-2009 ESRI

Exercise 7B

public void ApplyClassBreaks(IGeoFeatureLayer geoLayer,


string aFieldName, long numBreaks)
{
// Create a table from the geo feature layer
ITable table;
table = geoLayer as ITable;
ITableHistogram tableHistogram;
tableHistogram = new TableHistogramClass();
tableHistogram.Table = table;
// equivalent to geoLayer.FeatureClass
// Retrieve frequency data from the field
tableHistogram.Field = aFieldName;
// MessageBox.Show("Field is: " & tableHistogram.Field)
IHistogram histogram;
histogram = tableHistogram as IHistogram;
object vValues;
object vFreqs;
histogram.GetHistogram(out vValues, out vFreqs);
// Classify the data
IClassifyGEN classifyGEN = new EqualInterval(); //Class
int intBreaks;
intBreaks = Convert.ToInt32(numBreaks);
classifyGEN.Classify(vValues, vFreqs, ref intBreaks);
double[] vBreaks = (double[])classifyGEN.ClassBreaks; // need an array
// Create the class breaks renderer
IClassBreaksRenderer classBreaksRenderer;
classBreaksRenderer = new ClassBreaksRenderer(); //Class
classBreaksRenderer.Field = aFieldName;
// passed as a String to the sub routine
classBreaksRenderer.BreakCount = (int)(numBreaks);
IRgbColor fromColor = new RgbColor(); //Class
fromColor.UseWindowsDithering = true;
fromColor.RGB = Microsoft.VisualBasic.Information.RGB(255, 255, 0);
IRgbColor toColor = new RgbColor(); //Class
toColor.UseWindowsDithering = true;
toColor.RGB = Microsoft.VisualBasic.Information.RGB(255, 0, 0);
// Set up the fill symbol
ISimpleFillSymbol sym = new SimpleFillSymbolClass();
IColor fillColor;
int i;
IEnumColors colors;
colors = GetColors(fromColor.RGB, toColor.RGB, numBreaks);
// Set up the fill symbol
ISimpleFillSymbol sym = new SimpleFillSymbol(); //Class
IColor fillColor;
MessageBox.Show("vBreaks.Length: " + vBreaks.Length.ToString());
IEnumColors colors;
colors = GetColors(fromColor.RGB, toColor.RGB, numBreaks);

Copyright 2001-2009 ESRI

7-57

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

for (int i = 0; (i <= vBreaks.Length - 2); i++) // Length = 6; subtracted 2


{
fillColor = colors.Next();
sym.Color = fillColor;
classBreaksRenderer.set_Break(i, vBreaks[(i + 1)]);
classBreaksRenderer.set_Symbol(i, sym as ISymbol);

geoLayer.Renderer = classBreaksRenderer as IFeatureRenderer;


axMapControl1.ActiveView.Refresh();
axTOCControl1.Update();

public IEnumColors GetColors(long lngStartColor, long lngEndColor, long Colors)


{
IRgbColor startColor = new RgbColor();
IRgbColor endColor = new RgbColor();
startColor.RGB = Convert.ToInt32(lngStartColor);
endColor.RGB = Convert.ToInt32(lngEndColor);

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;
}

private void axMapControl1_OnMouseMove(


object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
statusBarXY.Text = string.Format(
"{0}, {1} {2}", e.mapX.ToString("#######.##"),
e.mapY.ToString("#######.##"),
axMapControl1.MapUnits.ToString().Substring(4));
}
private void btnRender_Click(object sender, EventArgs e)
{
IGeoFeatureLayer geoLayer;
geoLayer = GetLayerByName(cboLayer.Text);
switch (m_strOption)
{
case "Simple":

7-58

Copyright 2001-2009 ESRI

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;

Copyright 2001-2009 ESRI

7-59

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private void cboLayer_SelectedIndexChanged(object sender, EventArgs e)


{
string strLayerName;
strLayerName = cboLayer.Text;
try
{
if ((strLayerName != ""))
{
btnRender.Enabled = true;
optSimple.Enabled = true;
optUnique.Enabled = true;
optBreaks.Enabled = true;
optSimple.Equals(true); //"True";
}
else
{
btnRender.Enabled = false;
m_strOption = "NoLayer";
OptionEnabler();
return;
}
// On Error GoTo LayerNotFound
IFeatureLayer fLayer;
fLayer = GetLayerByName(strLayerName);
FillFieldsComboBox(fLayer);
return;
}
catch (Exception error)
{
btnRender.Enabled = false;
m_strOption = "NoLayer";
OptionEnabler();
MessageBox.Show("Error : " + error.Message);
return;
}
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void AddLayersToComboBox()
{
//UID uidLayer = new UIDClass();
//uidLayer.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}";
//IMap map = axMapControl1.ActiveView.FocusMap;

7-60

Copyright 2001-2009 ESRI

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;
//}

private IGeoFeatureLayer GetLayerByName(string LayerName)


{
UID uid = new UID();
// This is the ID for layers supporting the IGeoFeatureLayer interface
uid.Value = "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}";
IEnumLayer allFLayers;
allFLayers = axMapControl1.ActiveView.FocusMap.get_Layers(uid, true);
// Loop thru all FeatureLayers until LayerName is found
ILayer layer;
layer = allFLayers.Next();
while (layer != null)
{
if ((layer.Name == LayerName))
{
// Pass back the requested layer
return ((IGeoFeatureLayer)(layer));
//break;
}
layer = allFLayers.Next();
}
return null;
}

Copyright 2001-2009 ESRI

7-61

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private void OptionEnabler() {


//Windows.Forms.Control cntrl;
foreach (System.Windows.Forms.Control cntrl in this.Controls)
{
Console.WriteLine(cntrl.ToString());
//Console.WriteLine(cntrl.Tag.ToString());
//if ((cntrl.Tag.ToString() == "CheckEnable"))
//{
//
cntrl.Enabled = false;
//
//next cntrl;
//}
}
switch (m_strOption)
{
case "Simple":
lblR.Enabled = true;
lblG.Enabled = true;
lblB.Enabled = true;
cboRed.Enabled = true;
cboGreen.Enabled = true;
cboBlue.Enabled = true;
break;
case "Unique":
cboUniqueVals.Enabled = true;
break;
case "Breaks":
cboNumericVals.Enabled = true;
cboBreaks.Enabled = true;
lblBreaks.Enabled = true;
break;
case "NoLayer":
optSimple.Enabled = false;
optUnique.Enabled = false;
optBreaks.Enabled = false;
break;
}

}
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

Copyright 2001-2009 ESRI

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

private void btnChangeRGBRenderer_Click(object sender, EventArgs e)


{
IMap map;
map = axMapControl1.ActiveView.FocusMap;
IRasterLayer rLayer;
rLayer = map.get_Layer(0) as IRasterLayer;
IRaster raster;
raster = rLayer.Raster;
IRasterBandCollection bandCol;
bandCol = raster as IRasterBandCollection;
if (bandCol.Count < 3)
{
return;
}
IRasterRGBRenderer rgbRen = new RasterRGBRenderer();
IRasterRenderer rasRen;
rasRen = rgbRen as IRasterRenderer;
rasRen.Raster = raster;
rasRen.Update();
rgbRen.RedBandIndex = 2;
rgbRen.GreenBandIndex = 1;
rgbRen.BlueBandIndex = 0;

// Update renderer and refresh layer


rasRen.Update();
rLayer.Renderer = rgbRen as IRasterRenderer;
axMapControl1.ActiveView.Refresh();
axTOCControl1.Update();

private void btnSaveLayer_Click(object sender, EventArgs e)


{

Copyright 2001-2009 ESRI

7-63

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

ArcGIS Snippet Title:


Save Layer File
Long Description:
Display save dialog
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted into the OnMouseDown event
of the TOC Control
The code assumes that a module-level variable (m_layer)
has been declared as ILayer

SaveFileDialog saveFileDialog = new SaveFileDialog();


saveFileDialog.Filter = "Layer File|*.lyr|All Files|*.*";
saveFileDialog.Title = "Create Layer File";
saveFileDialog.RestoreDirectory = true;
saveFileDialog.FileName =
System.IO.Path.Combine(saveFileDialog.InitialDirectory,
(m_layer.Name + ".lyr"));
saveFileDialog.ShowDialog();
string path;
path = saveFileDialog.FileName;

ILayerFile layerFile = new LayerFile();


layerFile.New(path);
layerFile.ReplaceContents(m_layer as ILayer);
layerFile.Save();
MessageBox.Show(String.Format("Layer file location: {0}\r\n", path));

private void optBreaks_CheckedChanged(object sender, EventArgs e)


{
m_strOption = "Breaks";
OptionEnabler();
}
private void optSimple_CheckedChanged(object sender, EventArgs e)
{
m_strOption = "Simple";
OptionEnabler();
}
private void optUnique_CheckedChanged(object sender, EventArgs e)
{
m_strOption = "Unique";
OptionEnabler();
}

7-64

Copyright 2001-2009 ESRI

Exercise 7B

private void btnStretch_Click(object sender, EventArgs e)


{
IMap map;
map = axMapControl1.ActiveView.FocusMap;
IRasterLayer rLayer;
rLayer = ((IRasterLayer)(map.get_Layer(0)));
IRaster raster;
raster = rLayer.Raster;
IRasterStretchColorRampRenderer stretchRen;
stretchRen = new RasterStretchColorRampRendererClass();
IRasterRenderer rasRen;
rasRen = ((IRasterRenderer)(stretchRen));
rasRen.Raster = raster;
rasRen.Update();
IRgbColor fromColor = new RgbColor();
fromColor.Red = 255;
fromColor.Green = 0;
fromColor.Blue = 0;
IRgbColor toColor;
toColor = new RgbColor();
toColor.Red = 0;
toColor.Green = 255;
toColor.Blue = 0;
IAlgorithmicColorRamp ramp;
ramp = new AlgorithmicColorRamp();
ramp.Size = 255;
ramp.FromColor = fromColor;
ramp.ToColor = toColor;
bool bTrue = true;
ramp.CreateRamp(out bTrue);
// Plug this colorramp into renderer and select a band
stretchRen.BandIndex = 0;
stretchRen.ColorRamp = ramp;
// Update the renderer with new settings and plug into layer
rasRen.Update();
rLayer.Renderer = ((IRasterRenderer)(stretchRen));
axMapControl1.ActiveView.Refresh();
axTOCControl1.Update();
}
}

Copyright 2001-2009 ESRI

7-65

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private void axTOCControl1_OnMouseDown(object sender,


ITOCControlEvents_OnMouseDownEvent e)
{
// ArcGIS Snippet Title:
// Find layer in TOC
//
// Long Description:
// Find the selected layer in the table of contents
//
// Intended ArcGIS Products for this snippet:
// ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
// ArcGIS Engine
//
// Applicable ArcGIS Product Versions:
// 9.2
// 9.3
//
// Notes:
// This snippet is intended to be inserted into the OnMouseDown event
// of the TOC Control
// The code assumes that a module-level variable (m_layer)
// has been declared as ILayer
IBasicMap map = null;
ILayer layer = null;
object other = null;
object index = null;
esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;
axTOCControl1.HitTest(e.x, e.y,
ref item, ref map, ref layer, ref other, ref index);
if ((item == esriTOCControlItem.esriTOCControlItemLayer))
{
m_layer = ((ILayer)(layer));
this.Text = ("Selected layer is: " + m_layer.Name);
}
}
private void btnScale_Click(object sender, EventArgs e)
{
IMap map;
map = axMapControl1.ActiveView.FocusMap;
IFeatureLayer fLayer1;
IFeatureLayer fLayer2;
IFeatureLayer fLayer0;
// Instantiate your feature layers to current map layers
fLayer0 = ((IFeatureLayer)(map.get_Layer(2)));
fLayer1 = ((IFeatureLayer)(map.get_Layer(1)));
fLayer2 = ((IFeatureLayer)(map.get_Layer(0)));
fLayer2.MinimumScale = 500000000;
MessageBox.Show(("Layer2 max scale: "
+ (fLayer2.Name
+ (" " + fLayer2.MaximumScale.ToString()))));
MessageBox.Show(("Layer2 min scale: "
+ fLayer2.MinimumScale.ToString()));

7-66

Copyright 2001-2009 ESRI

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

// Associate the scale dependent renderer with the new layer


// Add the scale dependent renderer to the map
newGeoFLayer.Renderer = ((IFeatureRenderer)(scaleDependentRenderer));
map.AddLayer(newGeoFLayer);

private void btnStretch_Click(object sender, EventArgs e)


{
IMap map;
map = axMapControl1.ActiveView.FocusMap;
IRasterLayer rLayer;
rLayer = map.get_Layer(0) as IRasterLayer;
IRaster raster;
raster = rLayer.Raster;
IRasterStretchColorRampRenderer stretchRen;
stretchRen = new RasterStretchColorRampRenderer();
IRasterRenderer rasRen;
rasRen = stretchRen as IRasterRenderer;
rasRen.Raster = raster;
rasRen.Update();

Copyright 2001-2009 ESRI

7-67

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

IRgbColor fromColor = new RgbColor();


fromColor.Red = 255;
fromColor.Green = 0;
fromColor.Blue = 0;
IRgbColor toColor;
toColor = new RgbColor();
toColor.Red = 0;
toColor.Green = 255;
toColor.Blue = 0;
IAlgorithmicColorRamp ramp;
ramp = new AlgorithmicColorRamp();
ramp.Size = 255;
ramp.FromColor = fromColor;
ramp.ToColor = toColor;
bool bTrue = true;
ramp.CreateRamp(out bTrue);
// Plug this colorramp into renderer and select a band
stretchRen.BandIndex = 0;
stretchRen.ColorRamp = ramp;
// Update the renderer with new settings and plug into layer
rasRen.Update();
rLayer.Renderer = stretchRen as IRasterRenderer;
axMapControl1.ActiveView.Refresh();
axTOCControl1.Update();
}
} // end class
} // end namespace DisplayingData

7-68

Copyright 2001-2009 ESRI

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 8A: Queries and selections (VB.NET)


Estimated time: 45 minutes
In this exercise, you will work with query filters, spatial filters, and feature cursors. You
will most often use these objects to work with data that meets certain criteria. As you will
see, you can also use a query filter to display a selection set.
In this exercise, you will:

Create query filters


Loop through records in a cursor
Create a spatial filter
Display a query filter as a selection

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.

Step 1: Apply a query filter and loop through a subset of records


In this step, you will use a query filter to select landlocked countries from a feature class
of world countries. You will access each of these records from a feature cursor in order to
calculate basic statistics for records matching the criteria of the query filter.
You will begin by previewing a feature class of world countries.
Start ArcMap and open QueryFilters.mxd from your \Student\IPAN\Exercise08 folder.

Copyright 2001-2009 ESRI

8-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 8A

Declare the variable fClass to hold your feature class.


Set fClass equal to the FeatureClass property on fLayer.
Next, you need to create a query filter and a feature cursor.
Create a new instance of QueryFilter and store it in the variable qFilter.
Declare the variable fCursor as IFeatureCursor.
Open the Visual Studio Object Browser, if necessary.
Search for IQueryFilter and examine its members.
Question 2: Which property will you use to set up the query filter?
______________________________________________________________________
Complete the following code to create the query filter:
qFilter.______________________ = "LANDLOCKED = 'Y'"

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:

Copyright 2001-2009 ESRI

8-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Dim feat As IFeature


Dim dblArea As Double
Dim lngCountries As Long

Determine the value for lngCountries by setting it equal to the FeatureCount


property on fClass.
Question 4: What is the argument that you need to pass to the FeatureCount property?
______________________________________________________________________
Complete the following code to pull the first record out of the cursor:
feat = fCursor.______________________
Note: Remember that a cursor is initialized with the pointer above the first item. The
first time NextFeature (or NextRow) is called, the first item in the cursor is returned.

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)

'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 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.

Build your project, then run it.

8-4

Copyright 2001-2009 ESRI

Exercise 8A

Click the Open button


QueryFilters.mxd.

, browse to \Student\IPAN\Exercise08, and open

If necessary, turn on the Country layer.


Click your Landlocked button.
Question 5: How many countries are landlocked?
______________________________________________________________________
Click OK to close the message box.
Close your application.
In your code, collapse the btnLandlocked_Click event.
In the next step, you will create a subset of features based on spatial and attribute criteria.

Step 2: Work with spatial and query filters


In this step, you will summarize a subset of features based on both spatial and attribute
criteria. You will write code to report the number of cities within the currently selected
country that have a population greater than 2 million.
Your code will produce a feature cursor of cities that fall within the selected country in
the Country layer. To accomplish this, you will make a spatial filter that uses the selected
country's shape as the Geometry property. Your code will reference the selected country
by getting the layer's selection and storing it in a cursor.
In Design view, double-click the Spatial Filter button (btnSpatialFilter) for its
Click event.
Within the sub procedure, declare the following variables to reference the layer
containing the selection, the selection set itself, and the feature cursor, respectively:
Dim cntryLyr As IFeatureSelection
Dim cntrySel As ISelectionSet
Dim cntryCursor As IFeatureCursor = Nothing

Complete the following code to set the required object variables (Hint: Country is the
third layer):

Copyright 2001-2009 ESRI

8-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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 ________________

Access the first feature in the feature cursor:


country = cntryCursor._________________

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:

One will point to the ISpatialFilter interface.


The other will point to the IQueryFilter interface.

Create the variable spatFilt as a new SpatialFilter.


Complete the following code to declare a QueryFilter object, then use QI to point
your qFilt variable to the spatial filter you just created:

8-6

Copyright 2001-2009 ESRI

Exercise 8A

Dim qFilt As ________________________


qFilt = __________________________
Note: Because SpatialFilter is a type of QueryFilter, it inherits all interfaces
defined on QueryFilter. By using both the ISpatialFilter interface and the
IQueryFilter interface on the same object, it is possible to define an attribute
expression (WhereClause property) and spatial criteria (Geometry and
SpatialRel properties) for a single filter.

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

Complete the following code to set the variables:


cityLyr = axMapControl1.ActiveView.________.Layer(0)
cityFClass = cityLyr.____________

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.________________________(________________)

Create the message box:


MessageBox.Show(intCities.ToString & " cities with population more than 2 million")

Build your project, then run it.


Open QueryFilters.mxd and turn on the Country layer, if necessary.

Copyright 2001-2009 ESRI

8-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Zoom to South America.


Select Brazil with the Select Features tool

Click your Spatial Filter button.


Question 6: 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:

Step 3 shows you how to display a query as a selection set.


The Challenge tests your ability to make the Landlocked button open a feature
class from a feature workspace.

If you want to complete one or both of these, do so now. Otherwise, close Visual
Studio.

8-8

Copyright 2001-2009 ESRI

Exercise 8A

Step 3: (Optional) Display a query filter as a selection


As you have learned, query filters and cursors do not display in the interface by default.
As a developer, you can choose to use query filters and cursors to perform operations on
your data, or you can use them to display a selection.
Open the ESRI Object Browser, if necessary.
Search for the FeatureLayer coclass by coclass name.
Double-click the result and view its interfaces.
So far, you have used the popular IFeatureLayer and ILayer interfaces on this class.
Next, you will use an interface that works with the selection set of a feature layer.
Locate IFeatureSelection and expand it.

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.

The SelectFeatures method expects three arguments:

Query filter
Selection method, as an enumeration
Boolean

Next, you will explore these arguments in more detail.


Under the Search For box, choose the Contains option.

Copyright 2001-2009 ESRI

8-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Search for esriSelection by enumeration name.


Double-click the esriSelectionResultEnum result and expand it in the lower pane.

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.

Now you are ready to write code to select features.


In Visual Studio, navigate to the Click event for the Select Cities button
(btnSelectCities).
Within the method, declare the variable map to reference IMap.
Set map equal to the FocusMap property of the active view of your MapControl.
Declare a variable to make feature selections:
Dim featSel As IFeatureSelection

8-10

Copyright 2001-2009 ESRI

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.__________________________________________, __________)

Report the number of selected cities in a message box.


Refresh the active view.
Build and run your project.
Open QueryFilters.mxd.
In the table of contents, click the Cities layer.
Click the Select Cities button.
Question 8: How many cities meet the query filter's criteria and are selected in the map?
______________________________________________________________________
Close the message box.

Copyright 2001-2009 ESRI

8-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Build and run your project.

8-12

Copyright 2001-2009 ESRI

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.

Challenge: Open a feature class from a feature workspace


Estimated time: 10 minutes

In an earlier lesson, you learned how to access workspaces from WorkspaceFactory


objects. One advantage to this approach is that you can run the code from an application
that does not contain a MapControl.
To complete this Challenge, apply that same knowledge to revise the code for your
Landlocked button so that it opens the Country feature class from a feature workspace.
(Hint: The Country feature class is contained in the Selections.gdb file geodatabase in the
\Student\IPAN\Database folder.)

Copyright 2001-2009 ESRI

8-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 8A Questions


Question 1: What two values does this field contain?
Answer: Y and N
Question 2: Which property will you use to set up the query filter?
Answer: WhereClause
Question 3: How did you set memory recycling?
Answer: By setting a value of True; this is a search cursor, so it is read-only and can
reuse memory.
Question 4: What is the argument that you need to pass to the FeatureCount property?
Answer: qFilter
Question 5: How many countries are landlocked?
Answer: 43
Question 6: How many cities in Brazil have a population greater than 2 million?
Answer: Six
Question 7: Which variable holds the map's selected layer? (Hint: The variable is
populated in the OnMouseDown event of your TOCControl.)
Answer: m_layer
Question 8: How many cities meet the query filter's criteria and are selected in the map?
Answer: 11

8-14

Copyright 2001-2009 ESRI

Exercise 8A

Exercise Solution: Exercise 8A (VB.NET)


Imports
Imports
Imports
Imports
Imports
Imports

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)

Copyright 2001-2009 ESRI

8-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

'Make sure that the MapDocument is not readonly


If mapDoc.IsReadOnly(m_mapDocumentName) Then
MessageBox.Show("Map document is read only!")
mapDoc.Close()
Return
End If
'Replace its contents with the current map
mapDoc.ReplaceContents(CType(m_mapControl.Map, IMxdContents))
'save the MapDocument in order to persist it
mapDoc.Save(mapDoc.UsesRelativePaths, False)
'close the MapDocument
mapDoc.Close()
End If
End Sub
Private Sub menuSaveAs_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles menuSaveAs.Click
'execute SaveAs Document command
Dim command As ICommand = New ControlsSaveAsDocCommandClass()
command.OnCreate(m_mapControl.Object)
command.OnClick()
End Sub
Private Sub menuExitApp_Click(ByVal sender As Object, ByVal e As EventArgs) _
Handles menuExitApp.Click
'exit the application
Application.Exit()
End Sub
#End Region
'listen to MapReplaced event in order to update the statusbar and the Save menu
Private Sub axMapControl1_OnMapReplaced(ByVal sender As Object, _
ByVal e As IMapControlEvents2_OnMapReplacedEvent) _
Handles axMapControl1.OnMapReplaced
'get the current document name from the MapControl
m_mapDocumentName = m_mapControl.DocumentFilename
'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 menu 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

8-16

Copyright 2001-2009 ESRI

Exercise 8A

Private Sub axTOCControl1_OnMouseDown(ByVal sender As Object, _


ByVal e As ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent) _
Handles axTOCControl1.OnMouseDown
Dim map As Map = Nothing
Dim layer As ILayer = Nothing
Dim other As Object = Nothing
Dim item As esriTOCControlItem
Dim index As Object = Nothing
'When querying interface to ITOCControl in Visual Basic .NET or
'Visual C# .NET the Object property or container specific code
'must be used. This is because .NET contains the real control
'inside a wrapper object known as an host.
'Dim tocControl As ITOCControl = axTOCControl1.Object
Dim toc As ITOCControl2 = axTOCControl1.Object
toc.HitTest(e.x, e.y, item, map, layer, other, index)
If item = esriTOCControlItem.esriTOCControlItemLayer Then
m_layer = layer
End If
End Sub
Private Sub btnLandLocked_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnLandLocked.Click
Dim fLayer As IFeatureLayer
fLayer = axMapControl1.ActiveView.FocusMap.Layer(2)
Dim fClass As IFeatureClass
fClass = fLayer.FeatureClass
Dim qFilter As IQueryFilter
qFilter = New QueryFilter
Dim fCursor As IFeatureCursor
qFilter.WhereClause = "LANDLOCKED = 'Y'"
fCursor = fClass.Search(qFilter, True)
Dim lngCountries As Long
lngCountries = fClass.FeatureCount(qFilter)
Dim feat As IFeature
Dim dblArea As Double
feat = fCursor.NextFeature
Do Until feat Is Nothing
dblArea = dblArea + feat.Value(10) ' Area in square km is the 11th field
feat = fCursor.NextFeature
Loop
MessageBox.Show("Number of landlocked countries: " _
& lngCountries & vbCrLf & _
"Average area: " & Math.Round(dblarea / lngCountries, 0))
End Sub

Copyright 2001-2009 ESRI

8-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Private Sub btnSpatialFilter_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) _
Handles btnSpatialFilter.Click
Dim cntryLyr As IFeatureSelection
Dim cntrySel As ISelectionSet
Dim cntryCursor As IFeatureCursor = Nothing
cntryLyr = axMapControl1.ActiveView.FocusMap.Layer(2)
cntrySel = cntryLyr.SelectionSet
cntrySel.Search(Nothing, True, cntryCursor)
Dim country As IFeature
country = cntryCursor.NextFeature
If country Is Nothing Then
MessageBox.Show("Please select a country")
Exit Sub
End If
Dim spatFilt As ISpatialFilter
spatFilt = New SpatialFilter
Dim qFilt As IQueryFilter
qFilt = spatFilt
spatFilt.WhereClause = "Population > 2000000"
spatFilt.Geometry = country.Shape
spatFilt.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains
Dim cityLyr As IFeatureLayer
Dim cityFClass As IFeatureClass
cityLyr = axMapControl1.ActiveView.FocusMap.Layer(0)
cityFClass = cityLyr.FeatureClass
Dim intCities As Integer
intCities = cityFClass.FeatureCount(spatFilt)
MessageBox.Show(intCities.ToString & _
" cities with population greater than 2 million")
End Sub
Private Sub btnSelectCities_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles btnSelectCities.Click
Dim map As IMap
map = axMapControl1.ActiveView.FocusMap
Dim featSel As IFeatureSelection
featSel = CType(m_layer, IFeatureSelection)
Dim qFilt As IQueryFilter
qFilt = New QueryFilter
qFilt.WhereClause = "Population > 10000000"

8-18

Copyright 2001-2009 ESRI

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

Copyright 2001-2009 ESRI

8-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Challenge Solution: Open a feature class from a


feature workspace
Imports ESRI.ArcGIS.DataSourcesGDB
Public Class MainForm
...
Private Sub btnLandLocked_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnLandLocked.Click
' Dim fLayer As IFeatureLayer
' fLayer = axMapControl1.ActiveView.FocusMap.Layer(2)
' Dim fClass As IFeatureClass
' fClass = fLayer.FeatureClass
Dim wFactory As IWorkspaceFactory
wFactory = New FileGDBWorkspaceFactory
Dim wksp As IWorkspace
wksp = wFactory.OpenFromFile("\Student\IPAN\Database\Selections.gdb", 0)
Dim fWS As IFeatureWorkspace
fWS = CType(wksp, IFeatureWorkspace)
Dim fClass As IFeatureClass
fClass = fWS.OpenFeatureClass("Country")
Dim qFilter As IQueryFilter
qFilter = New QueryFilter
Dim fCursor As IFeatureCursor
qFilter.WhereClause = "LANDLOCKED = 'Y'"
fCursor = fClass.Search(qFilter, True)
Dim lngCountries As Long
lngCountries = fClass.FeatureCount(qFilter)
Dim feat As IFeature
Dim dblArea As Double
feat = fCursor.NextFeature
Do Until feat Is Nothing
dblArea = dblArea + feat.Value(10) ' Area in square km is the 11th field
feat = fCursor.NextFeature
Loop
MessageBox.Show("Number of landlocked countries: " & _
lngCountries & vbCrLf & _
"Average area: " & Math.Round(dblArea / lngCountries, 0))
End Sub

8-20

Copyright 2001-2009 ESRI

Exercise 8B

Exercise 8B: Queries and selections (C#)


Estimated time: 45 minutes
In this exercise, you will work with query filters, spatial filters, and feature cursors. You
will most often use these objects to work with data that meets certain criteria. As you will
see, you can also use a query filter to display a selection set.
In this exercise, you will:

Create query filters


Loop through records in a cursor
Create a spatial filter
Display a query filter as a selection

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.

Step 1: Apply a query filter and loop through a subset of records


In this step, you will use a query filter to select landlocked countries from a feature class
of world countries. You will access each of these records from a feature cursor in order to
calculate basic statistics for records matching the criteria of the query filter.
You will begin by previewing a feature class of world countries.
Start ArcMap and open QueryFilters.mxd from your \Student\IPAN\Exercise08 folder.

Copyright 2001-2009 ESRI

8-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 8B

Declare the variable fClass to hold your feature class.


Set fClass equal to the FeatureClass property on fLayer.
Next, you need to create a query filter and a feature cursor.
Create a new instance of QueryFilter and store it in the variable qFilter.
Declare the variable fCursor as IFeatureCursor.
Build your project.
Open the Visual Studio Object Browser, if necessary.
Search for IQueryFilter and examine its members.
Question 2: Which property will you use to set up the query filter?
______________________________________________________________________
Complete the following code to create the query filter:
qFilter.______________________ = "LANDLOCKED = \'Y\'";

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:

Copyright 2001-2009 ESRI

8-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

double dblArea = 0;
long lngCountries = 0;

Determine the value for lngCountries by setting it equal to the FeatureCount


property on fClass.
Question 4: What is the argument that you need to pass to the FeatureCount property?
______________________________________________________________________
Complete the following code to pull the first record out of the cursor:
IFeature feat = fCursor.______________________();
Note: Remember that a cursor is initialized with the pointer above the first item. The
first time NextFeature (or NextRow) is called, the first item in the cursor is returned.

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.

, browse to \Student\IPAN\Exercise08, and open

If necessary, turn on the Country layer.

8-24

Copyright 2001-2009 ESRI

Exercise 8B

Click your Landlocked button.


Question 5: How many countries are landlocked?
______________________________________________________________________
Click OK to close the message box.
Close your application.
In your code, collapse the btnLandlocked_Click method.
In the next step, you will create a subset of features based on spatial and attribute criteria.

Step 2: Work with spatial and query filters


In this step, you will summarize a subset of features based on both spatial and attribute
criteria. You will write code to report the number of cities within the currently selected
country that have a population greater than 2 million.
Your code will produce a feature cursor of cities that fall within the selected country in
the Country layer. To accomplish this, you will make a spatial filter that uses the selected
country's shape as the Geometry property. Your code will reference the selected country
by getting the layer's selection and storing it in a cursor.
In Design view, double-click the Spatial Filter button (btnSpatialFilter) for its
Click event.
Within the method, declare the following variables to reference the layer containing
the selection, the selection set itself, and the feature cursor, respectively:
IFeatureSelection cntryLyr;
ISelectionSet cntrySel;
ICursor cntryCursor;

Complete the following code to return the layer (Hint: Country is the third layer):
cntryLyr = axMapControl1.get_Layer(2) as __________________________________;

Question 6: Because cntryLyr was declared with the IFeatureSelection interface,


which property can you use to access selected features?
______________________________________________________________________

Copyright 2001-2009 ESRI

8-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Use your answer to complete the following code:


cntrySel = cntryLyr.__________________;

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;

Access the first feature in the feature cursor:


country = featCursor._________________();

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

Copyright 2001-2009 ESRI

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:

One will point to the ISpatialFilter interface.


The other will point to the IQueryFilter interface.

Create the variable spatFilt as a new SpatialFilter.


Complete the following code to declare a QueryFilter object, then cast to point your
qFilt variable to the spatial filter you just created:
____________________________ qFilt;
qFilt = ____________________;
Note: Because SpatialFilter is a type of QueryFilter, it inherits all interfaces
defined on QueryFilter. By using both the ISpatialFilter interface and the
IQueryFilter interface on the same object, it is possible to define an attribute
expression (WhereClause property) and spatial criteria (Geometry and
SpatialRel properties) for a single filter.

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;

Complete the following code to set the variables:


cityLyr = axMapControl1.get_Layer(0) as __________________________;
cityFClass = cityLyr.____________;

Build your project.


Declare the following variable to work with the feature cursor:

Copyright 2001-2009 ESRI

8-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Click your Spatial Filter button.

8-28

Copyright 2001-2009 ESRI

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:

Step 3 shows you how to display a query as a selection set.


The Challenge tests your ability to make the Landlocked button open a feature
class from a feature workspace.

If you want to complete one or both of these, do so now. Otherwise, close Visual
Studio.

Step 3: (Optional) Display a query filter as a selection


As you have learned, query filters and cursors do not display in the interface by default.
As a developer, you can choose to use query filters and cursors to perform operations on
your data, or you can use them to display a selection.
Open the ESRI Object Browser, if necessary.
Search for the FeatureLayer coclass by coclass name.
Double-click the result and view its interfaces.
So far, you have used the popular IFeatureLayer and ILayer interfaces on this class.
Next, you will use an interface that works with the selection set of a feature layer.
Locate IFeatureSelection and expand it.

Copyright 2001-2009 ESRI

8-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

The SelectFeatures method expects three arguments:

Query filter
Selection method, as an enumeration
Boolean

Next, you will explore these arguments in more detail.


Under the Search For box, choose the Contains option.
Search for esriSelection by enumeration name.
Double-click the esriSelectionResultEnum result and expand it in the lower pane.

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.

Copyright 2001-2009 ESRI

Exercise 8B

Now you are ready to write code to select features.


In Visual Studio, navigate to the Click event for the Select Cities button
(btnSelectCities).
Within the method, declare the variable map to reference IMap.
Set map equal to the FocusMap property of the active view of your MapControl.
Declare a variable to make feature selections:
IFeatureSelection featSel;

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.__________________________________________, __________);

Report the number of selected cities in a message box.

Copyright 2001-2009 ESRI

8-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Refresh the active view.


Build and run your project.
Open QueryFilters.mxd.
In the table of contents, click the Cities layer.
Click the Select Cities button.
Question 9: How many cities meet the query filter's criteria and are selected in the map?
______________________________________________________________________
Close the message box.
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.

8-32

Copyright 2001-2009 ESRI

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.

Challenge: Open a feature class from a feature workspace


Estimated time: 10 minutes

In an earlier lesson, you learned how to access workspaces from WorkspaceFactory


objects. One advantage to this approach is that you can run the code from an application
that does not contain a MapControl.
To complete this Challenge, apply that same knowledge to revise the code for your
Landlocked button so that it opens the Country feature class from a feature workspace.
(Hint: The Country feature class is contained in the Selections.gdb file geodatabase in the
\Student\IPAN\Database folder.)

Copyright 2001-2009 ESRI

8-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 8B Questions


Question 1: What two values does this field contain?
Answer: Y and N
Question 2: Which property will you use to set up the query filter?
Answer: WhereClause
Question 3: How did you set memory recycling?
Answer: By setting a value of true; this is a search cursor, so it is read-only and can
reuse memory
Question 4: What is the argument that you need to pass to the FeatureCount property?
Answer: qFilter
Question 5: How many countries are landlocked?
Answer: 43
Question 6: Because cntryLyr was declared with the IFeatureSelection interface,
which property can you use to access selected features?
Answer: SelectionSet
Question 7: How many cities in Brazil have a population greater than 2 million?
Answer: Six
Question 8: Which variable holds the map's selected layer? (Hint: The variable is
populated in the OnMouseDown event of your TOCControl.)
Answer: m_layer
Question 9: How many cities meet the query filter's criteria and are selected in the map?
Answer: 11

8-34

Copyright 2001-2009 ESRI

Exercise 8B

Exercise Solution: Exercise 8B (C#)


using
using
using
using
using
using
using
using

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;

//disable the Save menu (since there is no document yet)


menuSaveDoc.Enabled = false;

#region Main Menu event handlers


private void menuNewDoc_Click(object sender, EventArgs e)
{
//execute New Document command
ICommand command = new CreateNewDocument();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}

Copyright 2001-2009 ESRI

8-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private void menuOpenDoc_Click(object sender, EventArgs e)


{
//execute Open Document command
ICommand command = new ControlsOpenDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuSaveDoc_Click(object sender, EventArgs e)
{
//execute Save Document command
if (m_mapControl.CheckMxFile(m_mapDocumentName))
{
//create a new instance of a MapDocument
IMapDocument mapDoc = new MapDocumentClass();
mapDoc.Open(m_mapDocumentName, string.Empty);
//Make sure that the MapDocument is not readonly
if (mapDoc.get_IsReadOnly(m_mapDocumentName))
{
MessageBox.Show("Map document is read only!");
mapDoc.Close();
return;
}
//Replace its contents with the current map
mapDoc.ReplaceContents((IMxdContents)m_mapControl.Map);
//save the MapDocument in order to persist it
mapDoc.Save(mapDoc.UsesRelativePaths, false);

//close the MapDocument


mapDoc.Close();

private void menuSaveAs_Click(object sender, EventArgs e)


{
//execute SaveAs Document command
ICommand command = new ControlsSaveAsDocCommandClass();
command.OnCreate(m_mapControl.Object);
command.OnClick();
}
private void menuExitApp_Click(object sender, EventArgs e)
{
//exit the application
Application.Exit();
}
#endregion
//listen to MapReplaced event in order to
update the statusbar and the Save menu
private void axMapControl1_OnMapReplaced(
object sender, IMapControlEvents2_OnMapReplacedEvent e)
{
//get the current document name from the MapControl
m_mapDocumentName = m_mapControl.DocumentFilename;

8-36

Copyright 2001-2009 ESRI

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);
}

private void axMapControl1_OnMouseMove(


object sender, IMapControlEvents2_OnMouseMoveEvent e)
{
statusBarXY.Text = string.Format("{0}, {1} {2}",
e.mapX.ToString("#######.##"),
e.mapY.ToString("#######.##"),
axMapControl1.MapUnits.ToString().Substring(4));
}
private void btnLandlocked_Click(object sender, EventArgs e)
{
IFeatureLayer fLayer;
fLayer = axMapControl1.get_Layer(2) as IFeatureLayer;
IFeatureClass fClass;
fClass = fLayer.FeatureClass;
IQueryFilter qFilter = new QueryFilter();
IFeatureCursor fCursor;
qFilter.WhereClause = "LANDLOCKED = \'Y\'";
fCursor = fClass.Search(qFilter, true);
double dblArea = 0;
long lngCountries = 0;
lngCountries = fClass.FeatureCount(qFilter);
IFeature feat = fCursor.NextFeature();
while (feat != null)
{
dblArea += Convert.ToDouble(feat.get_Value(10));
// Area in square km is the 11th field
feat = fCursor.NextFeature();
}

MessageBox.Show(String.Format("Number of landlocked countries:


{0}\r\n Area: {1:#} sq km", lngCountries, dblArea));

Copyright 2001-2009 ESRI

8-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private void btnSpatialFilter_Click(object sender, EventArgs e)


{
IFeatureSelection cntryLyr;
ISelectionSet cntrySel;
ICursor cntryCursor;
cntryLyr = axMapControl1.get_Layer(2) as IFeatureSelection;
cntrySel = cntryLyr.SelectionSet;
cntrySel.Search(null, true, out cntryCursor);
IFeatureCursor featCursor = cntryCursor as IFeatureCursor;
IFeature country;
country = featCursor.NextFeature();
if ((country == null))
{
MessageBox.Show("Please select a country");
return;
}
ISpatialFilter spatFilt;
spatFilt = new SpatialFilter();
IQueryFilter qFilt;
qFilt = spatFilt;
spatFilt.WhereClause = "Population > 2000000";
spatFilt.Geometry = country.Shape;
spatFilt.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
IFeatureLayer cityLyr;
IFeatureClass cityFClass;
cityLyr = axMapControl1.get_Layer(0) as IFeatureLayer;
cityFClass = cityLyr.FeatureClass;
IFeatureCursor cityCursor;
cityCursor = cityFClass.Search(spatFilt, true);
long lngCities = 0;
lngCities = cityFClass.FeatureCount(spatFilt);

MessageBox.Show("This country has" + "\r\n"


+ lngCities + " cities with population > 2,000,000");

private void btnSelectCities_Click(object sender, EventArgs e)


{
IMap map;
map = axMapControl1.ActiveView.FocusMap;
IFeatureSelection featSel;
featSel = m_layer as IFeatureSelection;
IQueryFilter qFilt = new QueryFilter();
qFilt.WhereClause = "Population > 10000000";
if (featSel != null)
featSel.Clear();
else
return;
featSel.SelectFeatures(qFilt,
esriSelectionResultEnum.esriSelectionResultNew, false);
MessageBox.Show(featSel.SelectionSet.Count + " features selected");

8-38

Copyright 2001-2009 ESRI

Exercise 8B

IRgbColor grn = new RgbColor();


grn.Green = 255;
featSel.SelectionColor = grn;
axMapControl1.ActiveView.Refresh();

private void axTOCControl1_OnMouseDown(object sender,


ITOCControlEvents_OnMouseDownEvent e)
{
IBasicMap map = null;
ILayer layer = null;
object other = null;
object index = null;
esriTOCControlItem item = esriTOCControlItem.esriTOCControlItemNone;

axTOCControl1.HitTest(
e.x, e.y, ref item, ref map, ref layer, ref other, ref index);
if ((item == esriTOCControlItem.esriTOCControlItemLayer))
{
m_layer = layer;
}

}
}

Copyright 2001-2009 ESRI

8-39

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Challenge Solution: Open a feature class from a


feature workspace
using ESRI.ArcGIS.DataSourcesGDB;
private void btnLandlocked_Click(object sender, EventArgs e)
{
//IFeatureLayer fLayer;
//fLayer = axMapControl1.ActiveView.FocusMap.get_Layer(2) as IFeatureLayer;
//IFeatureClass fClass;
//fClass = fLayer.FeatureClass;
IWorkspaceFactory wFactory = new FileGDBWorkspaceFactory();
IWorkspace wksp;
wksp = wFactory.OpenFromFile("\\Student\\IPAN\\Database\\Selections.gdb", 0);
IFeatureWorkspace fWS;
fWS = wksp as IFeatureWorkspace;
IFeatureClass fClass;
fClass = fWS.OpenFeatureClass("Country");
IQueryFilter qFilter = new QueryFilter();
IFeatureCursor fCursor;
qFilter.WhereClause = "LANDLOCKED = \'Y\'";
fCursor = fClass.Search(qFilter, true);
double dblArea = 0;
long lngCountries = 0;
lngCountries = fClass.FeatureCount(qFilter);
IFeature feat = fCursor.NextFeature();
while (feat != null)
{
dblArea = (dblArea + Convert.ToDouble(feat.get_Value(10)));
// Area in square km is the 11th field
feat = fCursor.NextFeature();
}

8-40

MessageBox.Show(String.Format("Number of landlocked countries:


{0}\r\n Area: {1:#} sq km", lngCountries, dblArea));

Copyright 2001-2009 ESRI

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

Exercise 9A: Create a parcel proximity tool (VB.NET)


Estimated time: 45 minutes
Scenario: As the GIS analyst for an oil company, you are responsible for notifying
neighboring residents whenever your company builds a new gas station. Each
municipality defines a different radius for determining which residents to notify. In some
cities, you must notify residents within 30 meters, while in others, you must contact
residents within 150 meters. To accomplish this task efficiently, you will create a tool to
select parcels within a specified distance of the gas station parcel under development.
In this exercise, you will:

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.

Copyright 2001-2009 ESRI

9-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following as a guide:

Property

Value

Language

Visual Basic

Project type

ArcGIS > Engine

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

Copyright 2001-2009 ESRI

Exercise 9A

Assign the following properties to your controls:

Control

(Name)

Text

Label

lblProj

Projection:

TextBox

txtProj

Label

lblLU

TextBox

txtLU

Land Use:

Switch to code view.


Right-click anywhere in the code window and choose Outlining > Collapse to
Definitions.

Step 2: Create a new point when the map is clicked


The most basic geometry type is the point. In this step, you will create a point that will
represent a new gas station based on a location that the user clicks. To begin, you will
make your code recognize when your user has used your "tool" to click the map.
Navigate to the axMapControl1_OnMouseDown method.
Scroll to the right and note the second of the two parameters passed to the
OnMouseDown event.
The properties of the parameter e vary depending on the event to which it is passed. You
will first use a property of e to determine whether the right mouse button has been
clicked.
Complete the following If statement to test for a mouse button right-click:
If e.____________ = 2 Then

In addition to button, other properties for e display in the code completer.


Question 1: Which properties return map units and which properties return display units?
______________________________________________________________________
______________________________________________________________________

Copyright 2001-2009 ESRI

9-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.________

Repeat the process for the y coordinate.


Your variable aPoint now contains a point with coordinates stored in map units based on
the user's mouse click. This point will represent the location of a new gas station. Next,
you will find the proposed parcel where the new gas station will be built.

Step 3: Create a spatial filter


A spatial filter retrieves features based on their spatial relationship with a geometric
search feature, such as a point, area, or line. In this step, you will use a spatial filter to
select the parcel that intersects the point you created in the previous step.
Below the assignment statement for aPoint, instantiate a new instance of
ISpatialFilter in the variable spatFilt.

9-4

Copyright 2001-2009 ESRI

Exercise 9A

The Geometry property on SpatialFilter is used to specify the geometric search


features, and the SpatialRel property is used to define the spatial relationship to apply
to the search feature.
You will begin by selecting the parcel where the gas station is located.
Set the Geometry property of spatFilt equal to aPoint.
Assign a value for the SpatialRel property of spatFilt that will identify the parcel
intersected by the point.
You have now defined the spatial criterion needed to identify the parcel where the new
gas station will be built.

Step 4: Create a cursor and return a feature from it


In this step, you will use the spatial filter to create a cursor containing the parcel on which
the new gas station is located.
Just before the End If line, insert the IPAN_Ex09_Cursor snippet.
Review the code in the snippet.
Notice that the code uses a TypeOf statement to test whether the layer supports the
IFeatureLayer interface.
You now have a cursor object with the gas station's parcel. You will fetch a single feature
from the cursor. Once you have the feature, you will use it to search for neighboring
parcels so you can contact the residents of those parcels.
The variable feat will store each feature in the cursor and has already been set to the first
feature in the cursor.
Next, you will test whether the user has actually clicked a feature and report the result in
the projection text box.
Complete the following code to test and report if you have selected a valid feature; if
not, then exit:

Copyright 2001-2009 ESRI

9-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

If feat _______ ___________ Then


txtProj.Text = "No feature selected"
txtLU.Text = ""
________ Sub
Else
txtProj.Text = "Feature selected"
End If

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()

Build your project.


Note: If you haven't done so yet, resolve the conflict in the namespaces.

Run your project.

Step 5: Test your project


In this step, you will test whether your tool can distinguish between an x,y location that is
located within a parcel and one that is not located within a parcel.
To test your tool, you will add a gas station close to a major interstate access area near
the northwestern corner of the Redlands city limit.
Pan and zoom to the northwestern corner of your map.

Right-click anywhere on the map.

9-6

Copyright 2001-2009 ESRI

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.

Step 6: Determine the spatial reference for a geodataset


Before you can buffer the selected feature, you need to determine the buffer distance in
the parcel layer's native map units. To find these units, you will return the
SpatialReference object from the Parcels feature class.
After the code that populates txtLU, insert the IPAN_Ex09_SpatialRef snippet.
Read through the code.
Question 2: What does the code do when spatRef has the
IProjectedCoordinateSystem interface?
______________________________________________________________________
Build and run your project.
Test your tool.

Because the feature class now has a projection, the name of the projection appears in the
text box.
Close the application.

Copyright 2001-2009 ESRI

9-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 7: Buffer the gas station parcel and select neighboring


parcels
In this step, you will modify your tool to dynamically accept a user-input buffer distance.
You will then divide that distance by the number of meters that are in a unit for this
feature layer. This will convert the value provided (meters) into the native map units for
the Parcels layer.
At the end of your current code, declare the variable buffDist as Double to store the
buffer distance.
Complete the following code to create an input box for the user to enter a distance and
divide the result by meters per unit:
buffDist = CDbl(InputBox("Enter buffer distance in
meters", "", "100")) / lnrUnit._______________
Note: CDbl converts an expression to type Double.

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

is supported by many types of geometry, polygons included.

Copyright 2001-2009 ESRI

Exercise 9A

Question 3: Which variable holds the distance?


______________________________________________________________________
Complete the following code to return the feature's shape and then buffer it:
topoOp = CType(feat.__________, ITopologicalOperator)
buffPoly = CType(topoOp.____________(________________), IPolygon)

Next, you will select the neighboring parcels.


Instantiate a new instance of ISelectionEnvironment in the variable selEnv.
Question 4: What does the ISelectionEnvironment::DefaultColor property return?
______________________________________________________________________
Complete the following code to set the default color for displaying the selected
features and to set the search tolerance in pixels:
selEnv.________________________.______ = RGB(0, 255, 255)
selEnv.______________________________ = 3

Next, you will call IMap::SelectByShape.


Complete the following code, making sure that you choose the option to select more
than one feature:
axMapControl1.ActiveView.FocusMap.SelectByShape(_____________, ____________, __________)

Insert a few blank lines into your code.


You will insert code into this empty area in the next step.
Enter the following code to refresh the display:
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, _
Nothing, Nothing)

Build and run your project.


Right-click different parcels to test your tool.

To avoid potential conflict with tools on your ToolbarControl, press


Enter to accept a value from your InputBox.

Copyright 2001-2009 ESRI

9-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 8: Remove the gas station parcel from the selection


You only need to notify residents in the parcels surrounding the gas station, not in the gas
station parcel itself. In this step, you will create a new selection environment to remove
the gas station parcel from the selection.
Here is some pseudo code for the process you will code in this step:

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, ________)

Build and run your project.


Zoom to the northwestern corner of your map and test your tool with two or three
different parcels.
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.

9-10

Copyright 2001-2009 ESRI

Exercise 9A

Below the code you just wrote, complete the following the code to programmatically
restore a new selection:
selEnv.CombinationMethod = esriSelectionResultEnum._____________________________

Your code should look something like the following:


Dim selEnv As ISelectionEnvironment = New SelectionEnvironment
selEnv.DefaultColor.RGB = RGB(0, 255, 255)
selEnv.SearchTolerance = 3
axMapControl1.ActiveView.FocusMap.SelectByShape(buffPoly, selEnv, False)
selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultSubtract
axMapControl1.ActiveView.FocusMap.SelectByShape(aPoint, selEnv, True)
selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultNew
axMapControl1.ActiveView.PartialRefresh( _
esriViewDrawPhase.esriViewGeoSelection, Nothing, Nothing)
End Sub

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.

Copyright 2001-2009 ESRI

9-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

These operations are very powerful on their own; you learned here that they can be
combined to do exactly what you want.

Challenge: Draw the polygon buffer


Estimated time: 10 minutes

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:

Set your buffer polygon to the Geometry property of a polygon element


Set the FocusMap property of your axMapControl1.ActiveView to a
GraphicsContainer object
Add your buffer polygon element to the graphics container

Test your tool.


When you are finished, use the SelectFeatures tool to clear the selection.
Use the Select Elements tool

to select the buffer graphic, then delete it.

Challenge: Use DisplayTransformation


Estimated time: 2 minutes

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

Copyright 2001-2009 ESRI

Exercise 9A

Answers to Exercise 9A Questions


Question 1: Which properties return map units and which properties return display units?
Answer: mapx and mapy return map units, x and y return display units
Question 2: What does the code do when spatRef has the
IProjectedCoordinateSystem interface?
Answer: It displays the projCoordSys name in a text box
Question 3: Which variable holds the distance?
Answer: buffDist
Question 4: What does the ISelectionEnvironment::DefaultColor property return?
Answer: IColor

Copyright 2001-2009 ESRI

9-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 9A (VB.NET)


Imports
Imports
Imports
Imports
Imports
Imports

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
+

Private Sub axMapControl1_OnMapReplaced ...

Private Sub axMapControl1_OnMouseMove ...

Private Sub axMapControl1_OnMouseDown( _


ByVal sender As System.Object, _
ByVal e As ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent) _
Handles axMapControl1.OnMouseDown
If e.button = 2 Then
Dim activeView As IActiveView
activeView = axMapControl1.ActiveView
Dim aPoint As IPoint = New Point
aPoint.X = e.mapX
aPoint.Y = e.mapY
Dim spatFilt As ISpatialFilter = New SpatialFilter
spatFilt.Geometry = aPoint
spatFilt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects

9-14

Copyright 2001-2009 ESRI

Exercise 9A

'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Cursor
Long Description:
Access the first layer in the map
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted into the OnMouseDown
event of a map that contains atleast one layer

Dim lyr As ILayer


Dim fLayer As IFeatureLayer
Dim fCursor As IFeatureCursor
lyr = axMapControl1.ActiveView.FocusMap.Layer(0)
If TypeOf lyr Is IFeatureLayer Then
fLayer = CType(lyr, IFeatureLayer)
Else
txtProj.Text = "No feature layer found"
Exit Sub
End If
fCursor = fLayer.Search(spatFilt, True)
Dim feat As IFeature
feat = fCursor.NextFeature
If feat Is Nothing Then
txtProj.Text = "No feature selected"
txtLU.Text = ""
Exit Sub
Else
txtProj.Text = "Feature selected"
End If
txtLU.Text = feat.Value(fCursor.FindField("Landuse")).ToString()

Copyright 2001-2009 ESRI

9-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Spatial reference
Long Description:
Report the spatial reference of the layer
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:

This snippet requires a feature layer

Dim geoDataset As IGeoDataset


Dim spatRef As ISpatialReference
geoDataset = CType(fLayer.FeatureClass, IGeoDataset)
spatRef = geoDataset.SpatialReference
Dim projCoordSys As IProjectedCoordinateSystem
Dim lnrUnit As ILinearUnit
If TypeOf spatRef Is IProjectedCoordinateSystem Then
projCoordSys = CType(spatRef, IProjectedCoordinateSystem)
lnrUnit = projCoordSys.CoordinateUnit
txtProj.Text = projCoordSys.Name
Else
txtProj.Text = "Feature layer is not projected"
Exit Sub
End If
Dim buffDist As Double
buffDist = _
CDbl(InputBox("Buffer distance in meters", "", "100")) / lnrUnit.MetersPerUnit
' or, for testing
' buffDist = 60 / lnrUnit.MetersPerUnit
Dim topoOp As ITopologicalOperator
Dim buffPoly As IPolygon
topoOp = CType(feat.Shape, ITopologicalOperator)
buffPoly = CType(topoOp.Buffer(buffDist), IPolygon)
Dim selEnv As ISelectionEnvironment = New SelectionEnvironment
selEnv.DefaultColor.RGB = RGB(0, 255, 255)
axMapControl1.ActiveView.FocusMap.SelectByShape(buffPoly, selEnv, False)
selEnv.CombinationMethod = _
esriSelectionResultEnum.esriSelectionResultSubtract
axMapControl1.ActiveView.FocusMap.SelectByShape(aPoint, selEnv, True)
selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultNew

9-16

Copyright 2001-2009 ESRI

Exercise 9A

Dim elem As IElement = New PolygonElement


elem.Geometry = buffPoly
Dim gCont As IGraphicsContainer
gCont = CType(axMapControl1.ActiveView.FocusMap, IGraphicsContainer)
gCont.AddElement(elem, 0)
axMapControl1.ActiveView.PartialRefresh( _
esriViewDrawPhase.esriViewGeoSelection, Nothing, Nothing)
End If
End Sub
End Class

Copyright 2001-2009 ESRI

9-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Challenge Solution: Draw the polygon buffer


selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultNew
Dim elem As IElement
elem = New PolygonElement
elem.Geometry = buffPoly
Dim gCont As IGraphicsContainer
gCont = CType(axMapControl1.ActiveView.FocusMap, IGraphicsContainer)
gCont.AddElement(elem, 0)
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, _
Nothing, Nothing)
End Sub

9-18

Copyright 2001-2009 ESRI

Exercise 9A

Challenge Solution: Use DisplayTransformation


Dim activeView As IActiveView
activeView = axMapControl1.ActiveView
Dim aPoint As IPoint
aPoint = activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y)
' Dim aPoint As IPoint = New Point
' aPoint.X = e.mapX
' aPoint.Y = e.mapY

Copyright 2001-2009 ESRI

9-19

Exercise 9B

Exercise 9B: Create a parcel proximity tool (C#)


Estimated time: 45 minutes
Scenario: As the GIS analyst for an oil company, you are responsible for notifying
neighboring residents whenever your company builds a new gas station. Each
municipality defines a different radius for determining which residents to notify. In some
cities, you must notify residents within 30 meters, while in others, you must contact
residents within 150 meters. To accomplish this task efficiently, you will create a tool to
select parcels within a specified distance of the gas station parcel under development.
In this exercise, you will:

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.

Copyright 2001-2009 ESRI

9-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following as a guide:

Property

Value

Language

Visual C#

Project type

ArcGIS > Engine

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

Copyright 2001-2009 ESRI

Exercise 9B

Assign the following properties to your controls:

Control

(Name)

Text

Label

lblProj

Projection:

TextBox

txtProj

Label

lblLU

TextBox

txtLU

Land Use:

Switch to code view.


Right-click anywhere in the code window and choose Outlining > Collapse to
Definitions.

Step 2: Create a new point when the map is clicked


The most basic geometry type is the point. In this step, you will create a point that will
represent a new gas station based on a location that the user clicks. To begin, you will
make your code recognize when your user has used your "tool" to click the map.
Navigate to the axMapControl1_OnMouseDown method.
Scroll to the right and note the second of the two parameters passed to the
OnMouseDown event.
The properties of the parameter e vary depending on the event to which it is passed. You
will first use a property of e to determine whether the right mouse button has been
clicked.
Complete the following if statement to test for a mouse button right-click:
if (e.button == 2)
{
}

In addition to button, other properties for e display in the code completer.


Question 1: Which properties return map units and which properties return display units?
______________________________________________________________________
______________________________________________________________________

Copyright 2001-2009 ESRI

9-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.________;

Repeat the process for the y coordinate.


Your variable aPoint now contains a point with coordinates stored in map units based on
the user's mouse click. This point will represent the location of a new gas station. Next,
you will find the proposed parcel where the new gas station will be built.

Step 3: Create a spatial filter


A spatial filter retrieves features based on their spatial relationship with a geometric
search feature, such as a point, area, or line. In this step, you will use a spatial filter to
select the parcel that intersects the point you created in the previous step.
Below the assignment statement for aPoint, instantiate a new instance of
ISpatialFilter in the variable spatFilt.

9-24

Copyright 2001-2009 ESRI

Exercise 9B

The Geometry property on SpatialFilter is used to specify the geometric search


features, and the SpatialRel property is used to define the spatial relationship to apply
to the search feature.
You will begin by selecting the parcel where the gas station is located.
Set the Geometry property of spatFilt equal to aPoint.
Assign a value for the SpatialRel property of spatFilt that will identify the parcel
intersected by the point.
You have now defined the spatial criterion needed to identify the parcel where the new
gas station will be built.

Step 4: Create a cursor and return a feature from it


In this step, you will use the spatial filter to create a cursor containing the parcel on which
the new gas station is located.
Just before the end of your if statement, insert the IPAN_Ex09_Cursor snippet.
Review the code in the snippet.
Notice that the code uses the is operator to test whether the layer supports the
IFeatureLayer2 interface.
You now have a cursor object with the gas station's parcel. You will fetch a single feature
from the cursor. Once you have the feature, you will use it to search for neighboring
parcels so you can contact the residents of those parcels.
The variable feat will store each feature in the cursor and has already been set to the first
feature in the cursor.
Next, you will test whether the user has actually clicked a feature and report the result in
the projection text box.
Complete the following code to test and report if you have selected a valid feature; if
not, then exit:

Copyright 2001-2009 ESRI

9-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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();

Build your project.


Note: If you haven't done so yet, resolve the conflict in the namespaces.

Run your project.

Step 5: Test your project


In this step, you will test whether your tool can distinguish between an x,y location that is
located within a parcel and one that is not located within a parcel.
To test your tool, you will add a gas station close to a major interstate access area near
the northwestern corner of the Redlands city limit.
Pan and zoom to the northwestern corner of your map.

9-26

Copyright 2001-2009 ESRI

Exercise 9B

Right-click anywhere on the map.


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.

Step 6: Determine the spatial reference for a geodataset


Before you can buffer the selected feature, you need to determine the buffer distance in
the parcel layer's native map units. To find these units, you will return the
SpatialReference object from the Parcels feature class.
After the code that populates txtLU, insert the IPAN_Ex09_SpatialRef snippet.
Read through the code.
Question 2: What does the code do when spatRef has the
IProjectedCoordinateSystem interface?
______________________________________________________________________
Build and run your project.
Test your tool.

Because the feature class now has a projection, the name of the projection appears in the
text box.

Copyright 2001-2009 ESRI

9-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Close the application.

Step 7: Buffer the gas station parcel and select neighboring


parcels
In this step, you will modify your tool to dynamically accept a user-input buffer distance.
You will then divide that distance by the number of meters that are in a unit for this
feature layer. This will convert the value provided (meters) into the native map units for
the Parcels layer.
Complete the following code to create an input dialog box for the user to enter a
distance and divide the result by meters per unit:
string strDist = Microsoft.VisualBasic.Interaction.InputBox(
"Enter a value", "Buffer Distance", "100", 0, 0);
Note: Notice that this code requires you to add the Microsoft VisualBasic reference.

Convert the user input to store the buffer distance:


double buffDist = Convert.ToDouble(strDist);

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

is supported by many types of geometry, polygons included.

Copyright 2001-2009 ESRI

Exercise 9B

Question 3: Which variable holds the distance?


______________________________________________________________________
Complete the following code to return the feature's shape and then buffer it:
topoOp = feat.__________ as ________________________________________;
buffPoly = topoOp.____________(________________) as IPolygon;

Next, you will select the neighboring parcels.


Create a new instance of ISelectionEnvironment in the variable selEnv.
Question 4: What does the ISelectionEnvironment::DefaultColor property return?
______________________________________________________________________
Complete the following code to set the default color for displaying the selected
features:
IRgbColor selColor = new RgbColor();
selColor.Red = 0;
selColor.Green = 255;
selColor.Blue = 255;
selEnv.DefaultColor.RGB = selColor.______;

Next, you will call IMap::SelectByShape.


Complete the following code, making sure that you choose the option to select more
than one feature:
axMapControl1.ActiveView.FocusMap.SelectByShape(_____________, ___________, _________);

Insert a few blank lines into your code.


You will insert code into this empty area in the next step.
Enter the following code to refresh the display:
axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection,
null, null);

Build and run your project.


Right-click different parcels to test your tool.

Copyright 2001-2009 ESRI

9-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

To avoid potential conflict with tools on your ToolbarControl, press


Enter to accept a value from your InputBox.

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.

Step 8: Remove the gas station parcel from the selection


You only need to notify residents in the parcels surrounding the gas station, not in the gas
station parcel itself. In this step, you will create a new selection environment to remove
the gas station parcel from the selection.
Here is some pseudo code for the process you will code in this step:

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, ________);

Build and run your project.


Zoom to the northwestern corner of your map and test your tool with two or three
different parcels.

9-30

Copyright 2001-2009 ESRI

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.__________________________;

Your code should look something like the following:


ISelectionEnvironment selEnv = new SelectionEnvironment();
IRgbColor selColor = new RgbColor();
selColor.Red = 0;
selColor.Green = 255;
selColor.Blue = 255;
selEnv.DefaultColor.RGB = selColor.RGB;
axMapControl1.ActiveView.FocusMap.SelectByShape(buffPoly, selEnv, false);
selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultSubtract;
axMapControl1.ActiveView.FocusMap.SelectByShape(aPoint, selEnv, true);
selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultNew;
axMapControl1.ActiveView.PartialRefresh(
esriViewDrawPhase.esriViewGeoSelection, null, null);

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.

Copyright 2001-2009 ESRI

9-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Challenge: Draw the polygon buffer


Estimated time: 10 minutes

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:

Set your buffer polygon to the Geometry property of a polygon element


Set the FocusMap property of your axMapControl1.ActiveView to a
GraphicsContainer object
Add your buffer polygon element to the graphics container

Test your tool.


When you are finished, use the SelectFeatures tool to clear the selection.
Use the Select Elements tool

to select the buffer graphic, then delete it.

Challenge: Use DisplayTransformation


Estimated time: 2 minutes

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

Copyright 2001-2009 ESRI

Exercise 9B

Answers to Exercise 9B Questions


Question 1: Which properties return map units and which properties return display units?
Answer: mapx and mapy return map units, x and y return display units
Question 2: What does the code do when spatRef has the
IProjectedCoordinateSystem interface?
Answer: It displays the projCoordSys name in a text box.
Question 3: Which variable holds the distance?
Answer: buffDist
Question 4: What does the ISelectionEnvironment::DefaultColor property return?
Answer: IColor

Copyright 2001-2009 ESRI

9-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 9B (C#)


using
using
using
using
using
using
using
using

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

private void MainForm_Load(object sender, EventArgs e) ...

Main menu event handlers


//listen to MapReplaced event in order to update the statusbar and
//the Save menu

private void axMapControl1_OnMapReplaced(


object sender, IMapControlEvents2_OnMapReplacedEvent e) ...

private void axMapControl1_OnMouseMove(


object sender, IMapControlEvents2_OnMouseMoveEvent e) ...
private void axMapControl1_OnMouseDown(
object sender, IMapControlEvents2_OnMouseDownEvent e)
{
if (e.button == 2)
{
IActiveView activeView = axMapControl1.ActiveView;
IPoint aPoint = new Point();
aPoint.x = e.mapX;
aPoint.y = e.mapY;
ISpatialFilter spatFilt = new SpatialFilter();
spatFilt.Geometry = aPoint;
spatFilt.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

9-34

Copyright 2001-2009 ESRI

Exercise 9B

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

ArcGIS Snippet Title:


Cursor
Long Description:
Access the first layer in the map.
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted into the OnMouseDown
event of a map that contains atleast one layer

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();

Copyright 2001-2009 ESRI

9-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

ArcGIS Snippet Title:


Spatial Reference
Long Description:
Report the spatial reference of the layer
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes: This snippet requires a feature layer

IGeoDataset geodataset = flayer.FeatureClass as IGeoDataset;


ISpatialReference spatialRef = geodataset.SpatialReference;
geoDataset = fLayer.FeatureClass as IGeoDataset;
IProjectedCoordinateSystem projCoordSys;
ILinearUnit lnrUnit;
geoDataset = fLayer.FeatureClass as IGeoDataset;
spatRef = geoDataset.SpatialReference;
if (spatRef is IProjectedCoordinateSystem)
{
projCoordSys = spatRef as IProjectedCoordinateSystem;
lnrUnit = projCoordSys.CoordinateUnit;
txtProj.Text = projCoordSys.Name;
}
else
{
txtProj.Text = "Feature layer is not projected";
return;
}
//need a reference to Microsoft.VisualBasic
string strDist = Microsoft.VisualBasic.Interaction.InputBox(
"Enter a value", "Buffer Distance", "100", 0, 0);
double buffDist = Convert.ToDouble(strDist);
ITopologicalOperator topoOp;
IPolygon buffPoly;
topoOp = feat.Shape as ITopologicalOperator;
buffPoly = topoOp.Buffer(buffDist) as IPolygon;
IRgbColor selColor = new RgbColor();
selColor.Red = 0;
selColor.Green = 255;
selColor.Blue = 255;
ISelectionEnvironment selEnv = new SelectionEnvironment();
selEnv.DefaultColor.RGB = selColor.RGB;

9-36

Copyright 2001-2009 ESRI

Exercise 9B

Copyright 2001-2009 ESRI

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

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Challenge Solution: Draw the polygon buffer


selEnv.CombinationMethod = esriSelectionResultEnum.esriSelectionResultNew;
IElement elem = new PolygonElement();
elem.Geometry = buffPoly;
IGraphicsContainer gCont;
gCont = axMapControl1.ActiveView.GraphicsContainer;
gCont.AddElement(elem, 0);
axMapControl1.ActiveView.PartialRefresh(
esriViewDrawPhase.esriViewGeoSelection, null, null);

9-38

Copyright 2001-2009 ESRI

Exercise 9B

Challenge Solution: Use DisplayTransformation


IActiveView activeView = axMapControl1.ActiveView;
// IPoint aPoint = new ESRI.ArcGIS.Geometry.Point();
// aPoint.X = e.mapX;
// aPoint.Y = e.mapY;
IPoint aPoint;
aPoint = activeView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);

Copyright 2001-2009 ESRI

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 10A: Create data (VB.NET)


Estimated time: 60 minutes
In this exercise, you will learn how to create new workspaces and datasets. You will
begin by creating a new file geodatabase, then you will use the Workspace object in your
code to create a new table in the geodatabase. Next, you will create a collection of fields
for the table, add records (rows), and provide values for each row. Although you will
only work with a file geodatabase, you can use the same basic procedure with any type of
data.
In this exercise, you will:

Create a new file geodatabase


Create a new table
Add rows and values to a table using the Store method
Calculate field values using an update cursor

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.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following as a guide:

Copyright 2001-2009 ESRI

10-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.)

Step 2: Create a geodatabase


You will begin with the WorkspaceFactory class that you used in a previous lesson to
access a file geodatabase. Remember that several subclasses can be created from
WorkspaceFactory. In this step, you will create a new FileGDBWorkspaceFactory
object in order to create a new file geodatabase.
Below the existing sub procedure in your CreateEdit module, add a new function using
the following code:
Public Function CreateFileGDB(ByVal parentFolder As String, ByVal nameGDB As String) _
As IWorkspace

Inside the CreateFileGDB function, declare the following variables:


Dim
Dim
Dim
Dim

fGDBwsf As IWorkspaceFactory
workName As IWorkspaceName
name As IName
workspace As IWorkspace

Create a new instance of fGDBwsf as FileGDBWorkspaceFactory.

10-2

Copyright 2001-2009 ESRI

Exercise 10A

Open the Visual Studio Object Browser, if necessary.


Locate the IWorkspaceFactory interface.
Earlier, you used the OpenFromFile method to access an existing workspace.
Question 1: Which method or property can be used to make a new workspace? What does
it return?
______________________________________________________________________
Note: Remember, Name objects are lightweight versions of the things they represent and
can be opened to produce the desired object.

In code view, complete the following code to create the new WorkspaceName:
workName = fGDBwsf.____________(parentFolder, nameGDB, Nothing, 0)

The required arguments for the Create method are:

Folder in which to create the new workspace


Name of the new workspace
Connection properties (if connecting to an ArcSDE geodatabase)
Application window handle

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.

Copyright 2001-2009 ESRI

10-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Make sure Show Inherited Members is checked under Object Browser


Settings.

In the list of properties and methods, click the Open method.


Question 2: Which interface on this class contains the Open method?
______________________________________________________________________
Question 3: What does the Open method on IName return?
______________________________________________________________________
Because there are several subtypes of the Name class, any one of a variety of objects can
be returned when the Open method is called. Because IName has no way of anticipating
which class the Open method will be used on, IUnknown is the return value. This simply
means that you will get the default interface of the type of Name object you open.
In your code, set name equal to workName.
This QI gives you access to the IName interface on your WorkspaceName object.
Open the workspace name and store the returned Workspace object in workspace.
Complete the following code to return the new workspace from the CreateFileGDB
function:
CreateFileGDB = _____________________

Build your project.


You now have a function that creates a file geodatabase by specifying the output location
and name.

Step 3: Create a new file geodatabase


In the previous step, you wrote a function to create a new file geodatabase; in this step,
you will write a sub procedure to call it. Your new sub procedure will pass in a path and a
name for the geodatabase, then return a pointer to the IWorkspace interface on the new
workspace.
Add a new sub procedure named MakeSalesGDB with no arguments.

10-4

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

10-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 4: Create a new table


Earlier, you used IFeatureWorkspace to open existing data. Now you will use it to
create new data.
In Visual Studio, return to the MakeSalesGDB sub procedure.
After the call to CreateFileGDB, create a variable named fWS, storing a refrence to
IFeatureWorkspace.
Instantiate fWS by setting it to the Workspace object you created earlier in this sub
procedure.
In the Visual Studio Object Browser, locate IFeatureWorkspace.
Notice that one of the arguments for its CreateTable method is IFields, a collection of
fields. Before you can call CreateTable, you will need to make a fields collection.
In your code, declare the variable fldsEdit as IFieldsEdit.
Instantiate fldsEdit as a new instance of Fields. (Or, optionally, instantiate it as a
new instance of FieldsClass, as you learned during the lecture.)
Note: For the remainder of the course, when you create a new COM object, you can
choose to use either the COM coclass or the .NET class.

Next, you will create three fields in your fields collection.


Declare each of the following variables as an IFieldEdit object:

oidFld
nameFld
salesFld

Instantiate each object as a new Field.


Complete the following With block to set the properties for the oidFld field. Make sure
to set the field type as OID.
With oidFld
.Name_2 = "OID"
.Type_2 = esriFieldType.________________________________
.Length_2 = 8
End With

10-6

Copyright 2001-2009 ESRI

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

Build your project and correct any syntax errors.


Next, you will add the field objects to the fields collection.
Type fldsEdit, then type a period (.) to display the code completer.
Notice that AddField does not display in the code completer. Remember, it is a hidden
member. You will change the Class View settings so that hidden members display as
well.
From the View menu, choose Class View.
The Class View window displays on the right in place of the Solution Explorer.
In the Class View window, expand your project, CreateAndEdit.
Next, expand References > ESRI.ArcGIS.Geodatabase > ESRI > ArcGIS >
Geodatabase.
Scroll down to IFieldsEdit, then click it to display its members. Be sure to click
IFieldsEdit (plural), not IFieldEdit (singular).
A list of members displays in the lower part of the window.
At the top of the window, click the Class View Settings drop-down arrow
click Show Hidden Types and Members.

, then

The AddField method appears as a member of IFieldsEdit even though the code
completer does not display it.

Copyright 2001-2009 ESRI

10-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Close the Class View window.


Although the code completer does not assist you in this case, you are assured that
IFieldsEdit::AddField does exist.
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 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.

Preview the table.


The three fields you created display, but there aren't any rows. This is because you
haven't yet added any.
In the Catalog tree, right-click the table and choose Properties.
Question 4: What are the data types of the three fields? (Hint: Fields tab)
______________________________________________________________________

10-8

Copyright 2001-2009 ESRI

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.

Step 5: Add rows and values to the table


In this step, you will add several new records (rows) to your table. You will also populate
these rows with some values. Although the code you write here will be technically
correct, you probably would not hard code the values into your application. You would
more likely use a Windows application with text boxes on a form, or dynamically read
data stored in a database or file.
In the Visual Studio Object Browser, locate the ITable interface and examine its
properties and methods.
Question 5: Which method returns a reference to IRow?
______________________________________________________________________
In your code, declare the variable row to store a row object.
Set the row variable by calling the CreateRow method on your table object.
There is more than one way to write code to modify the value for a row in a table. You
will create and populate each row, then call the Store method.
For the first row of your table, assign the following values for the store name and the
total sales. (Hint: Refer to your lecture slides for the syntax, and remember that the
Store field is a string field.)

Copyright 2001-2009 ESRI

10-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Build your solution and run your project.


In ArcCatalog, preview your BikeSales table.

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

Copyright 2001-2009 ESRI

Exercise 10A

Step 6: Calculate field values using an update cursor


In this step, you will use an update cursor to modify existing features in a dataset. You
will begin by inserting a snippet written specifically to save some time with this exercise.
In the Visual Studio, collapse your CreateFileGDB and MakeSalesGDB sub
procedures.
Below the MakeSalesGDB sub procedure, add a new sub procedure named CalcField
with no arguments.
Insert the snippet IPAN_Ex10_OpenFeatureClass and examine the code.
Question 6: What type of data is being accessed in this module?
______________________________________________________________________
Question 7: Which feature class will be updated?
______________________________________________________________________
The value for the PopPerMH field represents the population per mobile home, and will be
calculated by dividing the total population by the total number of mobile homes.
Under the comment line 'Step 6 goes here, set feat so it points to the first feature
in the update cursor updFeatures.
Create a Do Until loop that will run until feat is Nothing.
Complete the following code to retrieve the value for the Pop1999 field for the feature
and store it in the variable lngPop:
lngPop = CType(feat.__________(intPopFld), Long)

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.__________________________(________)

Write code to go to the next feature in the cursor.

Copyright 2001-2009 ESRI

10-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

Step 7 shows you two ways of storing changes to a table.

If you want to complete the optional step, do so now. Otherwise, close ArcCatalog and
Visual Studio.

Step 7: (Optional) Compare methods for editing


In this step, you will compare timings for two different ways of storing changes to a
table: by using a cursor and by using the Store method.
In the Sub Main, comment the call to your CalcField sub procedure.
Collapse the CreateFileGDB and MakeSalesGDB sub procedures, if necessary.
Collapse the CalcField sub procedure.

10-12

Copyright 2001-2009 ESRI

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:

Copyright 2001-2009 ESRI

10-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Variable

Value

m_gdb

"\Student\IPAN\Exercise10\AnnualSales.gdb"

m_tblName

"BikeSales"

m_numRecs

100

m_newValue

m_fldName

"Sales"

From Sub Main, call your AccessData sub procedure.


Note: Make sure the AnnualSales geodatabase and the BikesSales table exist inside
\Student\IPAN\Exercise10.

Run your project.


Read the message in the console window to see how much time it took to edit the
records using the Store method.
Press any key to see how long it took to edit the records using the insert cursor.
Note the time difference. The cursor operation took less time than the Store method to
add and update the records. With 100 records, it might not be impressive, but imagine the
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 (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

10-14

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

10-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 10A Questions


Question 1: Which method or property can be used to make a new workspace? What does
it return?
Answer: Create; IWorkspaceName
Question 2: Which interface on this class contains the Open method?
Answer: IName (from the abstract class Name)
Question 3: What does the Open method on IName return?
Answer: Object (In the Geodatabase OMD, the Open method returns IUnknown.)
Question 4: What are the data types of the three fields? (Hint: Fields tab)
Answer: Object ID, Text, Long Integer
Question 5: Which method returns a reference to IRow?
Answer: CreateRow
Question 6: What type of data is being accessed in this module?
Answer: File geodatabase
Question 7: Which feature class will be updated?
Answer: The USCounties feature class in the US_States geodatabase
Question 8: What type of geodatabase will be opened?
Answer: File geodatabase
Question 9: What unit of time is used for the elapsed time calculation?
Answer: Millisecond
Question 10: What type of cursor is used for these edits?
Answer: Insert

10-16

Copyright 2001-2009 ESRI

Exercise 10A

Exercise Solution: Exercise 10A (VB.NET)


Note: Due to space limitations, some formatting might not be syntactically correct.
Imports ESRI.ArcGIS.GeoDatabase
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.DataSourcesGDB
Module CreateEdit
Private
Private
Private
Private
Private
Private
Private

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

Private m_AOLicenseInitializer As LicenseInitializer = _


New CreateAndEdit.LicenseInitializer()
Sub Main()
'ESRI License Initializer generated code.
If (Not m_AOLicenseInitializer.InitializeApplication( _
New esriLicenseProductCode() _
{esriLicenseProductCode.esriLicenseProductCodeArcView}, _
New esriLicenseExtensionCode() {})) Then
Console.WriteLine(m_AOLicenseInitializer.LicenseMessage())
Console.WriteLine( _
"This application could not initialize with the correct
ArcGIS license and will shutdown.")
m_AOLicenseInitializer.ShutdownApplication()
Return
End If
'ESRI License Initializer generated code.
'Do not make any call to ArcObjects after ShutDownApplication()
'MakeSalesGDB()
'CalcField()
AccessData()
m_AOLicenseInitializer.ShutdownApplication()
End Sub
Public Function CreateFileGDB(ByVal parentFolder As String, _
ByVal nameGDB As String) As IWorkspace
Dim
Dim
Dim
Dim

fGDBwsf As IWorkspaceFactory
workName As IWorkspaceName
name As IName
workspace As IWorkspace

fGDBwsf = New FileGDBWorkspaceFactory


'fGDBwsf = New FileGDBWorkspaceFactoryClass
workName = fGDBwsf.Create(parentFolder, nameGDB, Nothing, 0)

Copyright 2001-2009 ESRI

10-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

name = CType(workName, IName) 'QI


workspace = CType(name.Open, IWorkspace)
CreateFileGDB = workspace
End Function
Public Sub MakeSalesGDB()
Dim wksp As IWorkspace
wksp = CreateFileGDB("\Student\IPAN\Exercise10", "AnnualSales")
Dim fWS As IFeatureWorkspace
fWS = CType(wksp, IFeatureWorkspace)
Dim fldsEdit As IFieldsEdit
fldsEdit = New Fields
'fldsEdit = New FieldsClass
Dim oidFld As IFieldEdit = New Field
Dim salesFld As IFieldEdit = New Field
Dim nameFld As IFieldEdit = New Field
'Dim oidFld As IFieldEdit = New FieldClass
'Dim salesFld As IFieldEdit = New FieldClass
'Dim nameFld As IFieldEdit = New FieldClass
With oidFld
.Name_2 = "OID"
.Type_2 = esriFieldType.esriFieldTypeOID
.Length_2 = 8
End With
With nameFld
.Name_2 = "Store"
.Type_2 = esriFieldType.esriFieldTypeString
.Length_2 = 16
End With
With salesFld
.Name_2 = "Sales"
.Type_2 = esriFieldType.esriFieldTypeInteger
.Length_2 = 16
End With
fldsEdit.AddField(oidFld)
fldsEdit.AddField(nameFld)
fldsEdit.AddField(salesFld)
Dim tbl As ITable
tbl = fWS.CreateTable("BikeSales", fldsEdit, Nothing, Nothing, "")
Dim row As IRow
row = tbl.CreateRow
row.Value(tbl.FindField("Store")) = "Full Cycle"
row.Value(tbl.FindField("Sales")) = 300000
row.Store()

10-18

Copyright 2001-2009 ESRI

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()
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

ArcGIS Snippet Title:


Open Geodatabase
Long Description:
Open File Geodatabase
Intended ArcGIS Products for this snippet:
ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
ArcGIS Engine
Applicable ArcGIS Product Versions:
9.2
9.3
Notes:
This snippet is intended to be inserted inside a Function or Sub.
It is not intended to be added to the base level of the Class.

Dim wsf As IWorkspaceFactory


wsf = New FileGDBWorkspaceFactory
' wsf = New FileGDBWorkspaceFactoryClass
Dim wksp As IWorkspace
Try

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)

Copyright 2001-2009 ESRI

10-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Dim updFeatures As IFeatureCursor


updFeatures = fClass.Update(Nothing, False)
'Variables to reference field names
Dim intPopMH As Integer
Dim intPopFld As Integer
Dim intHomeFld As Integer
intPopMH = updFeatures.FindField("PopPerMH")
intPopFld = updFeatures.FindField("Pop1999")
intHomeFld = updFeatures.FindField("Mobilehome")
'Variables for the update cursor to perform calculation
Dim feat As IFeature
Dim lngPop As Long
Dim lngHomes As Long
' Initialize the cursor
' Update the PopPerMH field based on other field values
'Step 6 code goes here
feat = updFeatures.NextFeature
Do Until feat Is Nothing
lngPop = CType(feat.Value(intPopFld), Long)
lngHomes = CType(feat.Value(intHomeFld), Long)
feat.Value(intPopMH) = lngPop / lngHomes
updFeatures.UpdateFeature(feat)
feat = updFeatures.NextFeature
Loop
Console.WriteLine("Update complete - press any key to exit")
Console.ReadKey()
End Sub
'
'
'
'
'
'
'
'
'
'
'
'
'
'
'

10-20

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:

Copyright 2001-2009 ESRI

Exercise 10A

'
'
'
'
'
'
'
'

Declare
Private
Private
Private
Private
Private
Private
Private

the following variables


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

Public Sub AccessData()


m_gdb = "\Student\IPAN\Exercise10\AnnualSales.gdb"
m_tblName = "BikeSales"
m_numRecs = 100
m_newValue = 0
m_fldName = "Sales"
Dim wsf As IWorkspaceFactory
wsf = New FileGDBWorkspaceFactory
' wsf = New FileGDBWorkspaceFactoryClass
Dim ws As IFeatureWorkspace
ws = wsf.OpenFromFile(m_gdb, 0)
m_table = ws.OpenTable(m_tblName)
m_fldNum = m_table.FindField(m_fldName)
StoreEdit()
UpdateEdit()
End Sub
' Begin optional step
Private Sub StoreEdit()
Dim startTime As Double
Dim endTime As Double
Dim totalTime As Double
startTime = Date.Now.Millisecond
Dim row As IRow
Dim i As Long
For i = 1 To m_numRecs
row = m_table.CreateRow
row.Value(m_fldNum) = m_newValue
row.Store()
Next i
endTime = Date.Now.Millisecond
totalTime = endTime - startTime
Console.WriteLine("Time to update Value/Store: " & totalTime & vbNewLine & _
totalTime / m_numRecs & " per record - press any key to continue")
Console.ReadKey()
End Sub
Private Sub UpdateEdit()

Copyright 2001-2009 ESRI

10-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Dim startTime As Double


Dim endTime As Double
Dim totalTime As Double
startTime = Date.Now.Millisecond
Dim row As IRow
row = m_table.CreateRow
Dim cur As ICursor
cur = m_table.Insert(True)
Dim i As Long
For i = 1 To m_numRecs
row.Value(m_fldNum) = m_newValue
cur.InsertRow(row)
Next i
cur = Nothing
endTime = Date.Now.Millisecond
totalTime = endTime - startTime
Console.WriteLine("Time to update Cursor: " & totalTime & vbNewLine & _
totalTime / m_numRecs & " per record - press any key to continue")
Console.ReadKey()
End Sub
' End optional step
End Module

10-22

Copyright 2001-2009 ESRI

Exercise 10B

Exercise 10B: Create data (C#)


Estimated time: 60 minutes
In this exercise, you will learn how to create new workspaces and datasets. You will
begin by creating a new file geodatabase, then you will use the Workspace object in your
code to create a new table in the geodatabase. Next, you will create a collection of fields
for the table, add records (rows), and provide values for each row. Although you will
only work with a file geodatabase, you can use the same basic procedure with any type of
data.
In this exercise, you will:

Create a new file geodatabase


Create a new table
Add rows and values to a table using the Store method
Calculate field values using an update cursor

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.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following as a guide:

Copyright 2001-2009 ESRI

10-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.)

Step 2: Create a geodatabase


You will begin with the WorkspaceFactory class that you used in a previous lesson to
access a file geodatabase. Remember that several subclasses can be created from
WorkspaceFactory. In this step, you will create a new
FileGDBWorkspaceFactoryClass object in order to create a new file geodatabase.
In your CreateEdit class, add a new method, using the following code:
private static IWorkspace CreateFileGDB(string parentFolder, string nameGDB)

Inside the new method, declare the following variables:


IWorkspaceFactory fGDBwsf;
IWorkspaceName workName;
IName name;
IWorkspace workspace;

Create a new instance of fGDBwsf as FileGDBWorkspaceFactoryClass.

10-24

Copyright 2001-2009 ESRI

Exercise 10B

Add the necessary references.


Open the Visual Studio Object Browser, if necessary.
Locate the IWorkspaceFactory interface.
Earlier, you used the OpenFromFile method to access an existing workspace.
Question 1: Which method or property can be used to make a new workspace? What does
it return?
______________________________________________________________________
Note: Remember, Name objects are lightweight versions of the things they represent and
can be opened to produce the desired object.

In code view, complete the following code to create the new WorkspaceName:
workName = fGDBwsf.____________(parentFolder, nameGDB, null, 0);

The required arguments for the Create method are:

Folder in which to create the new workspace


Name of the new workspace
Connection properties (if connecting to an ArcSDE geodatabase)
Application window handle

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

is an interface on the WorkspaceName class.

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.

Copyright 2001-2009 ESRI

10-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Question 2: Which interface on this class contains the Open method?


______________________________________________________________________
Question 3: What does the Open method on IName return?
______________________________________________________________________
Because there are several subtypes of the Name class, any one of a variety of objects can
be returned when the Open method is called. Because IName has no way of anticipating
which class the Open method will be used on, IUnknown is the return value. This simply
means that you will get the default interface of the type of Name object you open.
In your code, set name equal to workName.
This cast gives you access to the IName interface on your WorkspaceName object.
Open the workspace name and store the returned Workspace object in workspace.

Did you remember to cast to IWorkspace? The Open method


returns IUnknown, so you must cast to IWorkspace. IUnknown
objects are returned as type Object.

Complete the following code to return the new workspace from CreateFileGDB:
return ________________________;

Build your project.


You now have a function that creates a file geodatabase by specifying the output location
and name.

Step 3: Create a new file geodatabase


Now that you have written a method that creates a new file geodatabase, you are ready to
call it. You will pass in a path and a name for the geodatabase, then return a pointer to the
IWorkspace interface on the new workspace.
Add a new method named MakeSalesGDB with no arguments.
Begin the new method by declaring the variable wksp as IWorkspace.

10-26

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

10-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Minimize ArcCatalog.

Step 4: Create a new table


Earlier, you used IFeatureWorkspace to open existing data. Now you will use it to
create new data.
In Visual Studio, return to the MakeSalesGDB code.
After the call to CreateFileGDB, create a variable named fWS, storing a refrence to
IFeatureWorkspace.
Instantiate fWS by setting it to the Workspace object you created earlier in this method.
In the Visual Studio Object Browser, locate IFeatureWorkspace.
Notice that one of the arguments for its CreateTable method is IFields, a collection of
fields. Before you can call CreateTable, you will need to make a fields collection.
In your code, declare the variable fldsEdit as IFieldsEdit.
Instantiate fldsEdit as a new instance of FieldsClass.
Note: For the remainder of the course, when you create a new COM object, you can
choose to use either the COM coclass or the .NET class.

Next, you will create three fields in your fields collection.


Declare each of the following variables as an IFieldEdit object and instantiate each
object as a new FieldClass.

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

Copyright 2001-2009 ESRI

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.

Preview the table.


The three fields you created display, but there aren't any rows. This is because you
haven't yet added any.
In the Catalog tree, right-click the table and choose Properties.
Question 4: What are the data types of the three fields? (Hint: Fields tab)
______________________________________________________________________
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.

Copyright 2001-2009 ESRI

10-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the next step, you will add data to your table.


Minimize ArcCatalog.

Step 5: Add rows and values to the table


In this step, you will add several new records (rows) to your table. You will also populate
these rows with some values. Although the code you write here will be technically
correct, you probably would not hard code the values into your application. You would
more likely use a Windows application with text boxes on a form, or dynamically read
data stored in a database or file.
In the Visual Studio Object Browser, locate the ITable interface and examine its
properties and methods.
Question 5: Which method returns a reference to IRow?
______________________________________________________________________
In your code, declare the variable row to store a row object.
Set the row variable by calling the CreateRow method on your table object.
There is more than one way to write code to modify the value for a row in a table. You
will create and populate each row, then call the Store method.
For the first row of your table, assign the following values for the store name and the
total sales. (Hint: Remember that the Store field is a string field.)

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

Copyright 2001-2009 ESRI

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

Build your solution and run your project.


In ArcCatalog, preview your BikeSales table.

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.

Step 6: Calculate field values using an update cursor


In this step, you will use an update cursor to modify existing features in a dataset. You
will begin by inserting a snippet written specifically to save some time with this exercise.
In the Visual Studio, collapse your CreateFileGDB and MakeSalesGDB methods.
Below the MakeSalesGDB method, add a new method named CalcField with no
arguments.
Insert the snippet IPAN_Ex10_OpenFeatureClass and examine the code.

Copyright 2001-2009 ESRI

10-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Question 6: What type of data is being accessed in this module?


______________________________________________________________________
Question 7: Which feature class will be updated?
______________________________________________________________________
The value for the PopPerMH field represents the population per mobile home, and will be
calculated by dividing the total population by the total number of mobile homes.
Under the comment line //Step 6 goes here, set feat so it points to the first feature
in the update cursor updFeatures.
Create a while loop that will run until feat is null.
In the while loop, complete the following code to retrieve the value for the Pop1999
field for the feature and store it in the variable lngPop:
object fldValuePop = feat.get_Value(intPopFld);
lngPop = Convert.ToInt32(fldValuePop.ToString());

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.__________________________(________);

Write code to go to the next feature in the cursor.


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 a key, such as Enter,
to resume the process.
In Main, comment MakeSalesGDB();.

10-32

Copyright 2001-2009 ESRI

Exercise 10B

Call your CalcField(); method.


Build and 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:

Step 7 shows you two ways of storing changes to a table.

If you want to complete the optional step, do so now. Otherwise, close ArcCatalog and
Visual Studio.

Step 7: (Optional) Compare methods for editing


In this step, you will compare timings for two different ways of storing changes to a
table: by using a cursor and by using the Store method.
In the Sub Main, comment the call to your CalcField method.
If necessary, collapse the code to definitions. (Hint: Right-click, choose Outlining >
Collapse to Definitions.)
After the CalcField method, insert the IPAN_Ex10_Timings code snippet.
Navigate to the AccessData method and review its code.
The method 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 method calls two other methods: StoreEdit and UpdateEdit. Each of
these calculates the elapsed time for a series of edits.
Navigate to the StoreEdit method and review its code.

Copyright 2001-2009 ESRI

10-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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"

From Main, call your AccessData method.


Note: Make sure the AnnualSales geodatabase and the BikesSales table exist inside
\Student\IPAN\Exercise10.

Run your project.


Read the message in the console window to see how much time it took to edit the
records using the Store method.
Press any key to see how long it took to edit the records using the insert cursor.
Note the time difference. The cursor operation took less time than the Store method to
add and update the records. With 100 records, it might not be impressive, but imagine the

10-34

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

10-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 10B Questions


Question 1: Which method or property can be used to make a new workspace? What does
it return?
Answer: Create; IWorkspaceName
Question 2: Which interface on this class contains the Open method?
Answer: IName (from the abstract class Name)
Question 3: What does the Open method on IName return?
Answer: Object (In the Geodatabase OMD, the Open method returns IUnknown.)
Question 4: What are the data types of the three fields? (Hint: Fields tab)
Answer: Object ID, Text, Long Integer
Question 5: Which method returns a reference to IRow?
Answer: CreateRow
Question 6: What type of data is being accessed in this module?
Answer: File geodatabase
Question 7: Which feature class will be updated?
Answer: The USCounties feature class in the US_States geodatabase
Question 8: What type of geodatabase will be opened?
Answer: File geodatabase
Question 9: What unit of time is used for the elapsed time calculation?
Answer: Millisecond
Question 10: What type of cursor is used for these edits?
Answer: Insert

10-36

Copyright 2001-2009 ESRI

Exercise 10B

Exercise Solution: Exercise 10B (C#)


using
using
using
using

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

Copyright 2001-2009 ESRI

10-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private static IWorkspace CreateFileGDB(string parentFolder, string nameGDB)


{
IWorkspaceFactory fGDBwsf;
IWorkspaceName workName;
IName name;
IWorkspace workspace;
fGDBwsf = new FileGDBWorkspaceFactoryClass();
workName = fGDBwsf.Create(parentFolder, nameGDB, null, 0);
name = workName as IName;
workspace = name.Open() as IWorkspace;
return workspace;
}
private static void MakeSalesGDB()
{
IWorkspace wksp;
wksp = CreateFileGDB("\\Student\\IPAN\\Exercise10", "AnnualSales");
IFeatureWorkspace fWS;
fWS = wksp as IFeatureWorkspace;
IFieldsEdit fldsEdit = new FieldsClass();
IFieldEdit oidFld = new FieldClass();
oidFld.Name_2 = "OID";
oidFld.Type_2 = esriFieldType.esriFieldTypeOID;
fldsEdit.AddField(oidFld);
IFieldEdit nameFld = new FieldClass();
nameFld.Name_2 = "Store";
nameFld.Type_2 = esriFieldType.esriFieldTypeString;
nameFld.Length_2 = 16; // Length is required for type String
fldsEdit.AddField(nameFld);
IFieldEdit salesFld = new FieldClass();
salesFld.Name_2 = "Sales";
salesFld.Type_2 = esriFieldType.esriFieldTypeInteger;
fldsEdit.AddField(salesFld);
ITable tbl;
tbl = fWS.CreateTable("BikeSales", fldsEdit, null, null, "");
IRow row = tbl.CreateRow();
row.set_Value(tbl.FindField("Store"), "Full Cycle");
row.set_Value(tbl.FindField("Sales"), 300000);
row.Store();
row = tbl.CreateRow();
row.set_Value(tbl.FindField("Store"), "UBikes");
row.set_Value(tbl.FindField("Sales"), 250000);
row.Store();
row = tbl.CreateRow();
row.set_Value(tbl.FindField("Store"), "Pro Peloton");
row.set_Value(tbl.FindField("Sales"), 225000);
row.Store();
}

10-38

Copyright 2001-2009 ESRI

Exercise 10B

private static void CalcField()


{
// ArcGIS Snippet Title:
// Open Geodatabase
//
// Long Description:
// Open File Geodatabase
//
// Intended ArcGIS Products for this snippet:
// ArcGIS Desktop (ArcView, ArcEditor, ArcInfo)
//
// Applicable ArcGIS Product Versions:
// 9.2
// 9.3
//
// 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.
// Variables to reference field names
IWorkspaceFactory wsf;
wsf = new FileGDBWorkspaceFactory();
//wsf = new FileGDBWorkspaceFactoryClass();
//IWorkspace wksp;
//try
//{
IWorkspace wksp;
wksp = wsf.OpenFromFile("\\Student\\IPAN\\Database\\US_States.gdb", 0);
IFeatureWorkspace fWS = wksp as IFeatureWorkspace;
IFeatureClass fClass;
fClass = fWS.OpenFeatureClass("USCounties");
IFieldEdit fldPopMH = new Field() as IFieldEdit;
//IFieldEdit fldPopMH = new FieldClass();
fldPopMH.AliasName_2 = "PopPerMH";
fldPopMH.Name_2 = "PopPerMH";
fldPopMH.Type_2 = esriFieldType.esriFieldTypeInteger;
fClass.AddField(fldPopMH);
IFeatureCursor updFeatures;
updFeatures = fClass.Update(null, false);
int intPopMH = updFeatures.FindField("PopPerMH");
int intPopFld = updFeatures.FindField("Pop1999");
int intHomeFld = updFeatures.FindField("Mobilehome");
IFeature feat;
int lngPop;
int lngHomes;
// Initialize the cursor
// Update the PopPerMH field based on other field values
//Step 6 code goes here
feat = updFeatures.NextFeature();
while (feat != null)
{

Copyright 2001-2009 ESRI

10-39

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

object fldValuePop = feat.get_Value(intPopFld);


lngPop = Convert.ToInt32(fldValuePop.ToString());
object fldValueHome = feat.get_Value(intHomeFld);
lngHomes = Convert.ToInt32(fldValueHome.ToString());
feat.set_Value(intPopMH, (lngPop / lngHomes));
updFeatures.UpdateFeature(feat);
feat = updFeatures.NextFeature();

}
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//

}
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

Copyright 2001-2009 ESRI

Exercise 10B

IWorkspaceFactory wsf = new FileGDBWorkspaceFactory();


//IWorkspaceFactory wsf = new FileGDBWorkspaceFactoryClass();
IFeatureWorkspace wksp;
try
{
wksp = wsf.OpenFromFile(m_gdb, 0) as IFeatureWorkspace;
}
catch
{
Console.WriteLine(m_gdb + " does not exist - press a key to continue");
Console.ReadKey();
return;
}
m_table = wksp.OpenTable(m_tblName);
m_fldNum = m_table.FindField(m_fldName);
StoreEdit(m_fldNum, m_numRecs, m_table, m_newValue);
UpdateEdit(m_fldNum, m_numRecs, m_table, m_newValue);

private static void StoreEdit(


int m_fldNum, long m_numRecs, ITable m_table, long m_newValue)
{
float startTime;
float endTime;
float totalTime;
startTime = DateTime.Now.Millisecond;
IRow row;
for (long = 1; i < m_numRecs; i++)
{
row = m_table.CreateRow();
row.set_Value(m_fldNum, m_newValue);
row.Store();
}
endTime = DateTime.Now.Millisecond;
totalTime = endTime - startTime;
Console.WriteLine("Time to update Value/Store: "
+ (totalTime + ("\r\n"
+ ((totalTime / m_numRecs)
+ " per record
- press any key to continue"))));
Console.ReadKey();
}

Copyright 2001-2009 ESRI

10-41

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

private static void UpdateEdit(


int m_fldNum, long m_numRecs, ITable m_table, long m_newValue)
{
float startTime;
float endTime;
float totalTime;
startTime = DateTime.Now.Millisecond;
IRow row;
row = m_table.CreateRow();
ICursor cur;
cur = m_table.Insert(true);
for (long i = 1; i < m_numRecs; i++)
{
row.set_Value(m_fldNum, m_newValue);
cur.InsertRow(row);
}
cur = null;
endTime = DateTime.Now.Millisecond;
totalTime = endTime - startTime;
Console.WriteLine("Time to update Cursor: "
+ totalTime + ("\r\n"
+ ((totalTime / m_numRecs)
+ " per record
- press any key to continue")));
Console.ReadKey();
}
} // end class CreateEdit
} // end namespace CreateAndEdit

10-42

Copyright 2001-2009 ESRI

11
Geoprocessing

Exercise 11A: Access the GeoProcessor


(VB.NET)
Estimated time: 60 minutes
Challenge: List environments
Estimated time: 5 minutes
Exercise 11B: Access the GeoProcessor
(C#)
Estimated time: 60 minutes
Challenge: List environments
Estimated time: 5 minutes

Exercise 11A

Exercise 11A: Access the GeoProcessor (VB.NET)


Estimated time: 60 minutes
In this exercise, you will use a GeoProcessor object to run system tools, run multiple
tools sequentially in the same process, and run a batch process. You will work with the
GeoProcessor object's methods and properties with your spatial data.
In this exercise, you will:

Work with methods and properties on IGeoProcessor


Run a geoprocessing system tool
Run multiple tools in succession
Run a batch process using a "List" method

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.

Copyright 2001-2009 ESRI

11-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 1: Start ArcCatalog and view your data


Before you write any code, you will explore some settings in ArcCatalog and examine
the data that you will be using.
Start ArcCatalog.
From the Tools menu, choose Options.
On the Options dialog box, click the Geoprocessing tab.
Click the Environments button to open the Environment Settings dialog box.

Expand General Settings.


Explore the general settings. You can specify these settings with code when you use
ArcObjects to perform geoprocessing operations.
Close the Environment Settings and Options dialog boxes.
If necessary, add the Location toolbar to ArcCatalog. (Hint: View menu, Toolbars >
Location.)
In the Catalog tree, expand \Student\IPAN\Database\Geoprocessing.gdb.

11-2

Copyright 2001-2009 ESRI

Exercise 11A

Expand the CityData feature dataset.

You will be working with these feature classes in this exercise.


Select the CityData feature dataset, then copy the path in the Location toolbar.

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.

Step 2: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following as a guide:

Property

Value

Language

Visual Basic

Project type

Windows

Template

Console Application

Name

GPTasks

Location

\Student\IPAN\Exercise11

Solution name

GPTasks

Copyright 2001-2009 ESRI

11-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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)

Step 3: Create and work with a GeoProcessor object


Before you can run any geoprocessing tools, you need to create a GeoProcessor object.
You will begin by exploring the Geoprocessor OMD.
If necessary, open the Desktop Help for .NET (VS2008).
In the table of contents, expand Building solutions with ArcGIS Engine using .NET >
ArcObjects library reference > Geoprocessing > ESRI.ArcGIS.Geoprocessing.
Click Geoprocessing Namespace Object Model Diagram to open
GeoprocessingObjectModel.pdf.
Zoom in on the coclass in the upper left of the diagram.
Question 1: What is the name of the coclass? What interface does it support?
______________________________________________________________________
This interface allows you to run any tool in ArcToolbox, set environments, and run batch
processes on many types of data. You will use it to create your GeoProcessor object.
In the GeoProc module in your code, create a new sub procedure named
Geoprocessing with no arguments.
Create a new instance of a GeoProcessor object and store it in the variable gp.

11-4

Copyright 2001-2009 ESRI

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.__________________________________("__________________", ________)

Then, write the workspace to the console window:


Console.WriteLine(gp.GetEnvironmentValue("Workspace") + " - press any key")
Console.ReadKey()

In Main, after Do not make any call to ArcObjects after


ShutDownApplication(), call your Geoprocessing sub procedure.
Run your project.
The console window opens with the workspace listed in it.

Press any key to close the console window.


In your code, comment the two Console lines.

Copyright 2001-2009 ESRI

11-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Run your project again.

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.

Step 4: Buffer a feature class


In ArcCatalog, click the Show/Hide ArcToolbox Window button
ArcToolbox.

to open

Expand the Analysis Tools toolbox, then expand the Proximity toolset.
Right-click the Buffer tool and choose Help.

11-6

Copyright 2001-2009 ESRI

Exercise 11A

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.
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.

Copyright 2001-2009 ESRI

11-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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)

Run your project.

Wait for the console window to close automatically before continuing.

In ArcCatalog, refresh the CityData feature dataset.


Preview your new GPBuff feature class.
Question 4: How many rows are in the Buildings feature class? How many buffer
features were created?
______________________________________________________________________
Next, you will intentionally overwrite existing data and work with messaging.

11-8

Copyright 2001-2009 ESRI

Exercise 11A

Step 5: Work with messaging and overwriting output


In this step, you will use the GetMessage method on the GeoProcessor object in order to
find out why a tool does not run. The GeoProcessor object usually provides a descriptive
message indicating why an operation has failed. Messages from the GeoProcessor object
are often more helpful than standard .NET messages.
First, you will make sure that an ArcCatalog setting to overwrite output is not enabled.
In ArcCatalog, from the Tools menu, choose Options.
On the Geoprocessing tab, uncheck the Overwrite the outputs of geoprocessing
operations check box, if necessary.
Click OK.
Minimize ArcCatalog.
In Visual Studio, run your project.
Note: Remember that you just ran it in the previous step and created the GPBuff feature
class. By default, when you are geoprocessing in ArcObjects, data that already exists will
not be overwritten. Instead, an error will occur.

An unhandled COM exception displays. Not very friendly, is it?


On the warning message, click View Detail.

Copyright 2001-2009 ESRI

11-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the View Detail window, expand the results.

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.

In the developer resource of your choice, locate the IGeoProcessor::GetMessage


method.
The GetMessage method will report a message directly from the GeoProcessor object
that will be much more descriptive than the message you just saw. A good way to work
with messaging is to create an error handler. Before you do that, you will create a sub
procedure that will report messages from the GeoProcessor object.
Create a new sub procedure named ReturnMessages that accepts the argument gp as
IGeoProcessor.
Complete the following For loop to write each message to the console:

11-10

Copyright 2001-2009 ESRI

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:

Run the Buffer tool, just as you did earlier


Call ReturnMessages

Make sure your code will run the Buffer tool only once.

In the Catch section, call ReturnMessages.


After your Try Catch block, write a line to the console that states your process is
complete.
Then write the following:
Console.ReadKey()

Build and run your project.

Copyright 2001-2009 ESRI

11-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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:

Insert more tests in your code using the Exists method


Rename the output
Tell the GeoProcessor to overwrite existing data

For this situation, you will use the third option.


Close the console window.
In the developer resource of your choice, locate the OverwriteOutput property.
This is a Boolean property that evaluates to either True or False. By default, it is set to
False. If you want to overwrite existing data, it needs to be set to True.
Within your Try statement, just before the line of code that executes the tool, set the
OverwriteOutput property to True to overwrite existing data.
Run your project.
This time, there are no errors and the GPBuff feature class is overwritten.

Step 6: Run multiple tools in the same process


In this step, you will run multiple tools in one geoprocessing operation. You will use the
output from one tool (Buffer) as the input for the next one (Intersect).
Create a new sub procedure called MultipleTools with no arguments.
Within the Geoprocessing sub procedure, copy the lines of code that create the
GeoProcessor object and set the workspace.
Paste the code into your MultipleTools sub procedure.
Instantiate a new VarArray in the variable buffParams.
Add three parameters to buffParams:

11-12

"Buildings"
"BldgsBuff300"
300

Copyright 2001-2009 ESRI

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")

Set the OverwriteOutput property of the GeoProcessor object to True.


Complete the following code to execute both tools:
gp.______________("Buffer_Analysis", ___________, Nothing)
gp.______________("Intersect_Analysis", __________, Nothing)

In Sub Main, comment Geoprocessing().


Call your MultipleTools sub procedure.
Run your project. Wait for the console window to close automatically.
Start ArcMap with a new, empty map.
Add the BldgsBuff300, OverlapAreas, and Buildings feature classes to the map.

Copyright 2001-2009 ESRI

11-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 7: (Optional) Perform a batch process using a "List"


method
In the previous steps, you set up the code and data to run batch processes. Basically, you
executed tasks without user intervention. One of the foremost tasks in a batch processing
program is the ability to iterate through several datasets. In this step, you will work with a
"List" method on IGeoProcessor to perform a batch process on a larger volume of data

11-14

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

11-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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(_________)

Move to the next item in the enumeration.


After your loop, write the following code:
Console.WriteLine("Press any key")
Console.ReadKey()

In Sub Main, comment MultipleTools().


Call your BatchProcessing sub procedure.
Run your project.
Question 9: How many polygon feature classes are listed in the console window?
______________________________________________________________________
Now you know that all of the polygon feature classes are in this list. Next, you will add a
new field to each of these feature classes.
Close the console window.

11-16

Copyright 2001-2009 ESRI

Exercise 11A

Start ArcMap.
In ArcToolbox, click the Search tab.
Enter AddField as the search word, then click Search.

In the Tool column, select Add Field, then click Locate.


Question 10: Which toolbox contains the Add Field tool, and what is its alias?
______________________________________________________________________
Open the help for the Add Field tool.
Question 11: What are the required parameters?
______________________________________________________________________
Close the help window, then minimize ArcMap.
In the Visual Studio, within your Do While loop, comment the line of code that reports
the feature class name.
Before the line of code that sets strFCName to the Next item, instantiate a new
VarArray in the variable fldParams.

Copyright 2001-2009 ESRI

11-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Add each of the following parameters to your array, fldParams:

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

Copyright 2001-2009 ESRI

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.

Challenge: List environments


Estimated time: 5 minutes

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.

Copyright 2001-2009 ESRI

11-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 11A Questions


Question 1: What is the name of the coclass? What interface does it support?
Answer: GeoProcessor; IGeoProcessor
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?
Answer: ESRI.ArcGIS.Geoprocessing; ESRI.ArcGIS.Geoprocessor
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.)
Answer: analysis
Question 4: How many rows are in the Buildings feature class? How many buffer
features were created?
Answer: Nine; nine
Question 5: What are the required parameters?
Answer: Input features (in_features) and output features (out_feature_class)
Question 6: What types of filters does the ListFeatureClasses method accept?
Answer: Wild card, feature type, dataset
Question 7: What does the ListFeatureClasses method return?
Answer: An object reference to IGpEnumList
Question 8: How many polygon feature classes does CityData contain?
Answer: Six
Question 9: How many polygon feature classes are listed in the console window?
Answer: Six

11-20

Copyright 2001-2009 ESRI

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)

Copyright 2001-2009 ESRI

11-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 11A (VB.NET)


Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geoprocessing
Imports ESRI.ArcGIS.esriSystem
Module GeoProc
Private m_AOLicenseInitializer As LicenseInitializer = _
New VB_Win_ConsoleApp.LicenseInitializer()
Sub Main()
'ESRI License Initializer generated code.
m_AOLicenseInitializer.InitializeApplication( _
New esriLicenseProductCode() _
{esriLicenseProductCode.esriLicenseProductCodeArcView}, _
New esriLicenseExtensionCode() {})
'ESRI License Initializer generated code.
'Do not make any call to ArcObjects after ShutDownApplication()
'Geoprocessing()
'MultipleTools()
BatchProcessing()
m_AOLicenseInitializer.ShutdownApplication()
End Sub
Sub Geoprocessing()
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)
'Console.WriteLine(gp.GetEnvironmentValue("Workspace") + " = press any key")
'Console.ReadKey()
'If gp.Exists("Buildings", Nothing) Then
'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
Dim param As IVariantArray = New VarArray
'Dim param As IVariantArray = New VarArrayClass
param.Add("Buildings")
param.Add("GPBuff")
param.Add(300)

11-22

Copyright 2001-2009 ESRI

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)

Copyright 2001-2009 ESRI

11-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Dim gpEnumList As IGpEnumList


gpEnumList = gp.ListFeatureClasses("*", "Polygon", "")
Dim strFCName As String
strFCName = gpEnumList.Next()
Do While strFCName <> ""
'Console.WriteLine(strFCName)
Dim fldParams As IVariantArray = New VarArray
'Dim fldParams As IVariantArray = New VarArrayClass
fldParams.Add(strFCName)
fldParams.Add("Acreage")
fldParams.Add("Double")
gp.Execute("AddField_Management", fldParams, Nothing)
strFCName = gpEnumList.Next()
Loop
Console.WriteLine("Press any key")
Console.ReadKey()
End Sub
End Module

11-24

Copyright 2001-2009 ESRI

Exercise 11A

Challenge Solution: List environments


There is usually more than one way to solve a problem or to write code. Here is one
possible solution:
Sub Main()
...
'Geoprocessing()
'MultipleTools()
'BatchProcessing()
ListEnvironments()
m_AOLicenseInitializer.ShutdownApplication()
End Sub
Sub ListEnvironments()
'Create the geoprocessor
Dim gp As IGeoProcessor = New GeoProcessor
'Dim gp As IGeoProcessor = New GeoProcessorClass
Dim strEnv As String ' Environment property
Dim i As Integer ' Number of environment properties
Dim enumEnvList As IGpEnumList
enumEnvList = gp.ListEnvironments("*") ' Use * for all
strEnv = enumEnvList.Next()
i = 0
Do While strEnv <> ""
i = i + 1
Console.WriteLine(strEnv)
strEnv = enumEnvList.Next()
Loop
Console.WriteLine(i & " environment properties")
Console.ReadKey()
End Sub

Copyright 2001-2009 ESRI

11-25

Exercise 11B

Exercise 11B: Access the GeoProcessor (C#)


Estimated time: 60 minutes
In this exercise, you will use a GeoProcessor object to run system tools, run multiple
tools sequentially in the same process, and run a batch process. You will work with the
GeoProcessor object's methods and properties with your spatial data.
In this exercise, you will:

Work with methods and properties on IGeoProcessor


Run a geoprocessing system tool
Run multiple tools in succession
Run a batch process using a "List" method

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.

Copyright 2001-2009 ESRI

11-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 1: Start ArcCatalog and view your data


Before you write any code, you will explore some settings in ArcCatalog and examine
the data that you will be using.
Start ArcCatalog.
From the Tools menu, choose Options.
On the Options dialog box, click the Geoprocessing tab.
Click the Environments button to open the Environment Settings dialog box.

Expand General Settings.


Explore the general settings. You can specify these settings with code when you use
ArcObjects to perform geoprocessing operations.
Close the Environment Settings and Options dialog boxes.
If necessary, add the Location toolbar to ArcCatalog. (Hint: View menu, Toolbars >
Location.)
In the Catalog tree, expand \Student\IPAN\Database\Geoprocessing.gdb.

11-28

Copyright 2001-2009 ESRI

Exercise 11B

Expand the CityData feature dataset.

You will be working with these feature classes in this exercise.


Select the CityData feature dataset, then copy the path in the Location toolbar.

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.

Step 2: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following as a guide:

Property

Value

Language

Visual C#

Project type

Windows

Template

Console Application

Name

GPTasks

Location

\Student\IPAN\Exercise11

Solution name

GPTasks

Copyright 2001-2009 ESRI

11-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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)

Step 3: Create and work with a GeoProcessor object


Before you can run any geoprocessing tools, you need to create a GeoProcessor object.
You will begin by exploring the Geoprocessor OMD.
If necessary, open the Desktop Help for .NET (VS2008).
In the table of contents, navigate to:

Building solutions with ArcGIS Engine using .NET >


ArcObjects library reference >
Geoprocessing >
ESRI.ArcGIS.Geoprocessing

Click Geoprocessing Namespace Object Model Diagram to open


GeoprocessingObjectModel.pdf.
Zoom in on the coclass in the upper left of the diagram.
Question 1: What is the name of the coclass? What interface does it support?
______________________________________________________________________
This interface allows you to run any tool in ArcToolbox, set environments, and run batch
processes on many types of data. You will use it to create your GeoProcessor object.
In the GeoProc class in your code, create a new method named Geoprocessing with
no arguments.
Create a new instance of a GeoProcessor object and store it in the variable gp.

11-30

Copyright 2001-2009 ESRI

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", ________);

Then, write the workspace to the console window:


Console.WriteLine(gp.GetEnvironmentValue("Workspace") + " - press any key");
Console.ReadKey();

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.

Press any key to close the console window.

Copyright 2001-2009 ESRI

11-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In your code, comment the two Console lines.


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.
Question 3: What data type is the second argument, and how is it passed?
______________________________________________________________________
Complete the following if statement to check whether the Buildings feature class
exists and report your findings:
object missingType = Type.Missing;
bool bExists = gp.____________("__________________", ref ______________________);
if (bExists)
{
Console.WriteLine("The data is present - press any key");
Console.ReadKey();
}
else
{
Console.WriteLine("The data is missing - press any key");
Console.ReadKey();
return;
} // end if / else

Build and run your project.

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

Copyright 2001-2009 ESRI

Exercise 11B

Next, you will run a system tool to buffer a feature class.

Step 4: Buffer a feature class


In ArcCatalog, click the Show/Hide ArcToolbox Window button
ArcToolbox.

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.

Copyright 2001-2009 ESRI

11-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.
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);

Build and run your project.

11-34

Copyright 2001-2009 ESRI

Exercise 11B

Wait for the console window to close automatically before continuing.

In ArcCatalog, refresh the CityData feature dataset.


Preview your new GPBuff feature class.
Question 5: How many rows are in the Buildings feature class? How many buffer
features were created?
______________________________________________________________________
Next, you will intentionally overwrite existing data and work with messaging.

Step 5: Work with messaging and overwriting output


In this step, you will use the GetMessage method on the GeoProcessor object in order to
find out why a tool does not run. The GeoProcessor object usually provides a descriptive
message indicating why an operation has failed. Messages from the GeoProcessor object
are often more helpful than standard .NET messages.
First, you will make sure that an ArcCatalog setting to overwrite output is not enabled.
In ArcCatalog, from the Tools menu, choose Options.
On the Geoprocessing tab, uncheck the Overwrite the outputs of geoprocessing
operations check box, if necessary.
Click OK.
Minimize ArcCatalog.
In Visual Studio, run your project.
Note: Remember that you just ran it in the previous step and created the GPBuff feature
class. By default, when you are geoprocessing in ArcObjects, data that already exists will
not be overwritten. Instead, an error will occur.

An unhandled COM exception displays. Not very friendly, is it?


On the warning message, click View Detail.
In the View Detail window, expand the results.

Copyright 2001-2009 ESRI

11-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

In the developer resource of your choice, locate the IGeoProcessor::GetMessage


method.
The GetMessage method will report a message directly from the GeoProcessor object
that will be much more descriptive than the message you just saw. A good way to work
with messaging is to create an error handler. Before you do that, you will create a method
that will report messages from the GeoProcessor object.
Create a new method named returnMessages that accepts the argument gp as
IGeoProcessor.
Complete the following for loop to write each message to the console:
if (gp.________________________ > 0)
{
for (int i = 0; i < gp.MessageCount; i++)
{
Console.WriteLine(gp.GetMessage(__));
}
}

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

Run the Buffer tool, just as you did earlier


Call returnMessages

Make sure your code will run the Buffer tool only once.

Copyright 2001-2009 ESRI

Exercise 11B

In the Catch section, call ReturnMessages.


After your try catch block, write a line to the console that states your process is
complete.
Then write the following:
Console.ReadKey();

Build and run your project.

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:

Insert more tests in your code using the Exists method


Rename the output
Tell the GeoProcessor to overwrite existing data

Close the console window.


In the developer resource of your choice, locate the OverwriteOutput property.
This is a Boolean property that evaluates to either true or false. By default, it is set to
false. If you want to overwrite existing data, it needs to be set to true.
Within your try statement, just before the line of code that executes the tool, set the
OverwriteOutput property to true to overwrite existing data.
Run your project.
This time, there are no errors and the GPBuff feature class is overwritten.

Copyright 2001-2009 ESRI

11-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 6: Run multiple tools in the same process


In this step, you will run multiple tools in one geoprocessing operation. You will use the
output from one tool (Buffer) as the input for the next one (Intersect).
Create a new method called MultipleTools with no arguments.
Within the Geoprocessing method, copy the lines of code that create the
GeoProcessor object and set the workspace.
Paste the code into your MultipleTools method.
Instantiate a new VarArray in the variable buffParams.
Add three parameters to buffParams:

"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

Copyright 2001-2009 ESRI

Exercise 11B

Set the OverwriteOutput property of the GeoProcessor object to true.


Complete the following code to execute both tools:
gp.______________("Buffer_Analysis", ___________, null);
gp.______________("Intersect_Analysis", __________, null);

In Main, comment Geoprocessing().


Call your MultipleTools method.
Build and run your project. Wait for the console window to close automatically.
Start ArcMap with a new, empty map.
Add the BldgsBuff300, OverlapAreas, and Buildings feature classes to the map.
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.

Copyright 2001-2009 ESRI

11-39

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 7: (Optional) Perform a batch process using a "List"


method
In the previous steps, you set up the code and data to run batch processes. Basically, you
executed tasks without user intervention. One of the foremost tasks in a batch processing
program is the ability to iterate through several datasets. In this step, you will work with a
"List" method on IGeoProcessor to perform a batch process on a larger volume of data
and add a field to each feature class in the CityData feature dataset. You will begin by
creating a GeoProcessor object.
Create a new method named BatchProcessing with no arguments.
Create the GeoProcessor object and set the workspace. Tip: Copy existing code from
the MultipleTools method.
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 7: What types of filters does the ListFeatureClasses method accept?
______________________________________________________________________

11-40

Copyright 2001-2009 ESRI

Exercise 11B

Question 8: 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.

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(_________);

Copyright 2001-2009 ESRI

11-41

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Move to the next item in the enumeration.


After your loop, write the following code:
Console.WriteLine("Press any key");
Console.ReadKey();

In Sub Main, comment MultipleTools().


Call your BatchProcessing method.
Run your project.
Question 10: How many polygon feature classes are listed in the console window?
______________________________________________________________________
Now you know that all of the polygon feature classes are in this list. Next, you will add a
new field to each of these feature classes.
Close the console window.
Start ArcMap.
In ArcToolbox, click the Search tab.
Enter AddField as the search word, then click Search.

11-42

Copyright 2001-2009 ESRI

Exercise 11B

In the Tool column, select Add Field, then click Locate.


Question 11: Which toolbox contains the Add Field tool, and what is its alias?
______________________________________________________________________
Open the help for the Add Field tool.
Question 12: What are the required parameters?
______________________________________________________________________
Close the help window, then minimize ArcMap.
In the Visual Studio, within your while loop, comment the line of code that reports the
feature class name.
Before the line of code that sets strFCName to the Next item, instantiate a new
VarArray in the variable fldParams.
Add each of the following parameters to your array, fldParams:

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.

Copyright 2001-2009 ESRI

11-43

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Challenge: List environments


Estimated time: 5 minutes

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

Copyright 2001-2009 ESRI

Exercise 11B

Write code to list each property, report its name in the console window, and report the
total number of environments.

Copyright 2001-2009 ESRI

11-45

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 11B Questions


Question 1: What is the name of the coclass? What interface does it support?
Answer: GeoProcessor;IGeoProcessor
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?
Answer: ESRI.ArcGIS.Geoprocessing; ESRI.ArcGIS.Geoprocessor
Question 3: What data type is the second argument, and how is it passed?
Answer: variant; passed by ref
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.)
Answer: analysis
Question 5: How many rows are in the Buildings feature class? How many buffer
features were created?
Answer: Nine; nine
Question 6: What are the required parameters?
Answer: Input features (in_features) and output features (out_feature_class)
Question 7: What types of filters does the ListFeatureClasses method accept?
Answer: Wild card, feature type, dataset
Question 8: What does the ListFeatureClasses method return?
Answer: An object reference to IGpEnumList
Question 9: How many polygon feature classes does CityData contain?
Answer: Six

11-46

Copyright 2001-2009 ESRI

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)

Copyright 2001-2009 ESRI

11-47

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 11B (C#)


using
using
using
using
using

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();

private static void Geoprocessing()


{
IGeoProcessor gp = new GeoProcessorClass();
string path = "\\Student\\IPAN\\Database\\Geoprocessing.gdb\\CityData";
gp.SetEnvironmentValue("Workspace", path);
//Console.WriteLine(gp.GetEnvironmentValue("Workspace") +
" - press any key");
//Console.ReadKey();

11-48

Copyright 2001-2009 ESRI

Exercise 11B

//object missingType = Type.Missing;


//bool bExists = gp.Exists("Buildings", ref missingType);
//if (bExists)
//{
//Console.WriteLine("The data is present - press any key.");
//Console.ReadKey();
//}
//else
//{
//Console.WriteLine("The data is missing - press any key.");
//Console.ReadKey();
//return;
//}
IVariantArray param = new VarArrayClass();
param.Add("Buildings");
param.Add("GPBuff");
param.Add(300);
try
{

gp.OverwriteOutput = true;
gp.Execute("Buffer_analysis", param, null);
returnMessages(gp);

}
catch
{
returnMessages(gp);
}

Console.WriteLine("Process complete. Press any key.");


Console.ReadKey();
}
private static void returnMessages(IGeoProcessor gp)
{
if (gp.MessageCount > 0)
{
for (int i = 0; i < gp.MessageCount; i++)
{
Console.WriteLine(gp.GetMessage(i));
}
}
}
private static void MultipleTools()
{
IGeoProcessor gp = new GeoProcessorClass();
string path = "\\Student\\IPAN\\Database\\Geoprocessing.gdb\\CityData";
gp.SetEnvironmentValue("Workspace", path);
IVariantArray buffParams = new VarArrayClass();
buffParams.Add("Buildings");
buffParams.Add("BldgsBuff300");
buffParams.Add(300);

Copyright 2001-2009 ESRI

11-49

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

IVariantArray intParams = new VarArrayClass();


intParams.Add("BldgsBuff300");
intParams.Add("OverlapAreas");
gp.OverwriteOutput = true;
gp.Execute("Buffer_analysis", buffParams, null);
gp.Execute("Intersect_analysis", intParams, null);
} // end MultipleTools
private static void BatchProcessing()
{
IGeoProcessor gp = new GeoProcessorClass();
string path = "\\Student\\IPAN\\Database\\Geoprocessing.gdb\\CityData";
gp.SetEnvironmentValue("Workspace", path);
IGpEnumList gpEnumList = gp.ListFeatureClasses("*", "Polygon", "");
string strFCName = gpEnumList.Next();

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();

} // end class GeoProc


} // end namespace GPTasks

11-50

Copyright 2001-2009 ESRI

Exercise 11B

Challenge Solution: List environments


There is usually more than one way to solve a problem or to write code. Here is one
possible solution:
static void Main(string[] args)
...
//Geoprocessing();
//MultipleTools();
//BatchProcessing();
ListEnvironments();
m_AOLicenseInitializer1.ShutdownApplication();
+ private static void BatchProcessing()
public static void ListEnvironments()
{
IGeoProcessor gp = new GeoProcessor();
//IGeoProcessor gp = new GeoProcessorClass();
string path = "\\Student\\IPAN\\Database\\Geoprocessing.gdb\\CityData";
gp.SetEnvironmentValue("Workspace", path);
IGpEnumList gpEnumList = gp.ListEnvironments("*");
int environmentsCount = 0;
string envName = gpEnumList.Next();
while (!envName.Equals(""))
{
++environmentsCount;
Console.WriteLine(envName);
envName = gpEnumList.Next();
}

Console.WriteLine("Total number of environments: " + environmentsCount);


Console.WriteLine("Press any key.");
Console.ReadKey();

} // end class GeoProc


} // end namespace GPTasks

Copyright 2001-2009 ESRI

11-51

12
Working with layouts

Exercise 12A: Update and export a layout


(VB.NET)
Estimated time: 60 minutes
Challenge: Modify the second text element
Estimated time: 15 minutes
Challenge: Create layouts for all maps
Estimated time: 15 minutes
Exercise 12B: Update and export a layout
(C#)
Estimated time: 60 minutes
Challenge: Modify the second text element
Estimated time: 15 minutes
Challenge: Create layouts for all maps in the
map document
Estimated time: 15 minutes

Exercise 12A

Exercise 12A: Update and export a layout (VB.NET)


Estimated time: 60 minutes
In this exercise, you will add a template to the PageLayoutControl in an ArcGIS Engine
application. Using ArcObjects, you will modify some of the elements in the layout and
then export it to PDF format.
In this exercise, you will:

Add a template to the PageLayoutControl


Modify elements on the layout
Export the layout to a PDF file

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.

Copyright 2001-2009 ESRI

12-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 1: Explore a map template in ArcMap


To get started with this exercise, you will examine the map template that you will modify
with code.
Start ArcMap with a new, empty map.
Switch to layout view. (Click the Layout View button

below the map display area.)

On the Layout toolbar, click the Change Layout button

In the Select Template wizard, do the following:

Click the My Templates tab, if necessary.


Click the Browse button, navigate to your \Student\IPAN\Database\Templates
folder, and open PortraitClassic.mxt.
Click Finish.

On the Tools toolbar, click the Select Elements tool

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.

on the Layout toolbar, zoom to the small white box in the

Note: Be sure to use the tool on the Layout toolbar, not the Tools toolbar.

This box represents the location of your map.


Scroll or use the Pan tool
layout page.

12-2

on the Layout toolbar to navigate to the lower right of the

Copyright 2001-2009 ESRI

Exercise 12A

Using the Select Elements tool

, double-click the text element below the scale bar.

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.

Copyright 2001-2009 ESRI

12-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

In the Save As dialog box, specify the following:

Save in: \Student\IPAN\Database\Templates


File name: MyTemplate.mxt
Save as type: ArcMap Template (*.mxt)

Close ArcMap.
Now that your are familiar with your template, you can begin writing code for it.

Step 2: Create a new project in Visual Studio


Start Visual Studio.
Create a new project, using the following as a guide:

Property

Value

Language

Visual Basic

Project type

Windows

Template

Windows Forms Application

Name

PageLayout

Location

\Student\IPAN\Exercise12

Solution name

PageLayout

Make sure the box for Create directory for solution is checked.

In Design view, click Form1.


Change its Text property to Layout in the Properties window.
Add the following controls to your form, resizing your form and/or controls as needed:

12-4

PageLayoutControl
ToolbarControl
LicenseControl

Copyright 2001-2009 ESRI

Exercise 12A

Open the Properties dialog box for the ToolbarControl and do the following:

Designate the PageLayoutControl as the ToolbarControl's buddy control.


Click the Items tab.
Click Add.

On the Controls Commands dialog box, do the following:

Click the Toolsets tab.


In the Toolsets list, double-click PageLayout to add all its commands to your
ToolbarControl.
Click Close.

Click OK on the Properties dialog box.

Step 3: Load a map template


In this step, you will load a map template into your PageLayoutControl.
In code view, navigate to the Form1_Load event.
Declare the variable fName as String.
Set it equal to MyTemplate.mxt in your \Student\IPAN\Database\Templates
folder. Tip: To avoid typographical errors, copy the path from the Location toolbar in
ArcCatalog.
Pass fName as the argument to the LoadMxFile method on the PageLayoutControl.
Run your project.
Your layout displays on the form at run time.
Close your application.
In Visual Studio, return to Design view.
If you would like, resize your form and layout.

Copyright 2001-2009 ESRI

12-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 4: Load your map document


Now that your template has been loaded, you are ready to customize the template. You
will begin by loading your map, then modifying elements that are already found on the
template.
Add a Button control to your form.
In the Properties window, set the following properties for the button:

Property

Value

Text

Add Map

(Name)

btnAddMap

Navigate to your new button's Click event.


Declare the variable mName as String.
Set mName equal to MapsAndLayers.mxd in your \Student\IPAN\Exercise12 folder.
Declare the variable mapDoc as IMapDocument and instantiate a New MapDocument.
Use the developer resource of your choice to answer the following question.
Question 2: What is the data type passed as the argument to the Open method on
IMapDocument? Which variable will you pass as the argument?
______________________________________________________________________
Write the code to open your map document.
Because the elements on your layout reside in the graphics container, you will need to
work with a GraphicsContainer object in code.
Declare the variable gc as IGraphicsContainer and set it equal to
AxPageLayoutControl1.PageLayout.

12-6

Copyright 2001-2009 ESRI

Exercise 12A

Declare the following variables, which you will populate later:

Dim map As IMap


Dim mFrame As IMapFrame
Dim mapCopy As IObjectCopy

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.

Step 5: Add your map template to the layout


In this step, you will add your map to the layout. You will begin by calling a custom
function that will loop through all the elements and find the map frame.
In your class, create a new function called returnMapFrame that will accept the
variable gc as the input argument IGraphicsContainer and return a reference to
IMapFrame.
All of the map elements on the PageLayout control reside in the graphics container. You
need to locate the map frame within that graphics container.
Open the Carto OMD.
Question 3: What is the relationship between IPageLayout and IGraphicsContainer?
______________________________________________________________________
______________________________________________________________________
______________________________________________________________________
Inside your function, call the Reset method on gc to reinitialize the internal cursor so
that the Next method will return the first element.
Complete the following code to determine whether the current element is a map frame
element. When the map frame element is found, set it as the return value for your
returnMapFrame function.

Copyright 2001-2009 ESRI

12-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Dim elem As ________________


elem = gc.________ ' Move to the first element
Do Until elem ____ ______________
If ____________ elem Is __________________ Then
Return ________
End If
elem = gc.________
Loop

Navigate to the Click event of your btnAddMap.


After the code that assigns the first map, complete the following code to call your
custom function:
mFrame = ____________________________(gc)

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.

Step 6: Tag your elements with a unique type


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

12-8

Copyright 2001-2009 ESRI

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?
______________________________________________________________________
______________________________________________________________________

Copyright 2001-2009 ESRI

12-9

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 7: Modify the map title


You are now ready to update other elements on your map, starting with the map's title
text.
Create a new sub procedure named UpdateTitle that accepts the following
arguments:

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

Copyright 2001-2009 ESRI

Exercise 12A

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

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.________)

To display your changes, enter the following code:


AxPageLayoutControl1.Refresh()

Build and run your project.


Test the Add Map button.
The title updates to Kauai, HI.
Close your application.

Copyright 2001-2009 ESRI

12-11

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 8: Export your layout to a file


After you have added or modified layout elements, you can create a digital or hard-copy
version of your map. In this step, you will export your map to a file. You will begin by
reading about the interface that you will use for exporting.
Add a new sub procedure named Export that accepts the string mapName as its only
argument.
In your new sub procedure, declare the variable activeView as IActiveView.
Set activeView to the ActiveView property of your PageLayoutControl.
Next, you will set up the device rectangle to be exported.
In the Desktop Help for .NET (VS2008), view the help for the IActiveView interface
and its members.
Click the ExportFrame property.
Question 6: What data type does ExportFrame return?
______________________________________________________________________
Click tagRECT.
Question 7: Where is its origin (XMin, YMin)?
______________________________________________________________________
Question 8: In which library will you find the tagRECT structure?
______________________________________________________________________
Complete the following code to create the export frame that will be exported:
Dim expFrame As tagRECT
expFrame = activeView.______________________

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

Copyright 2001-2009 ESRI

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

Set the following properties on expPDF:


C:\Student\IPAN\Exercise12\" & mapname & ".pdf"

Copyright 2001-2009 ESRI

12-13

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Property

Value

ExportFileName

"\Student\IPAN\Exercise12\" & mapName &


".PDF"

PixelBounds

env

Resolution

300

Now you are ready to perform the export.


Declare the variable hDC as Long.
hDC

represents the device context handle of the export object, expPDF.

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

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

12-15

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Insert a message box to display the name of your scale bar.


In the Click event of your btnAddMap, call UpdateUnits immediately after the call to
UpdateTitle.
Verify that your code matches the following:
TagTheElements(gc)
UpdateTitle(gc, map.Name)
UpdateUnits(gc, map)
AxPageLayoutControl1.Refresh()
Export(map.Name)

Run your project and test your button.


Question 10: What type of scale bar is in the map surround frame?
______________________________________________________________________
The units now display.
Close your application.
You have finished this step.
If you will be completing either of the Challenges, comment your message box.
Save your project.
Continue on to the Challenges, if you wish. Otherwise, close Visual Studio.

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

Copyright 2001-2009 ESRI

Exercise 12A

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.

Challenge: Modify the second text element


Estimated time: 15 minutes

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.

Challenge: Create layouts for all maps


Estimated time: 15 minutes

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.

Copyright 2001-2009 ESRI

12-17

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 12A Questions


Question 1: On the Scale and Units tab, how many times do you see "Unknown Units"?
What units does this refer to?
Answer: Twice; division units and label units
Question 2: What is the data type passed as the argument to the Open method on
IMapDocument? Which variable will you pass as the argument?
Answer: String; mName
Question 3: What is the relationship between IPageLayout and IGraphicsContainer?
Answer: IPageLayout and IGraphicsContainer are both interfaces on the
PageLayout coclass. You can QI to access one of these interfaces from the other.
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?
Answer: Two; Overwrite
Question 5: Is the assignment statement txtElem = elem a QI? Why or why not?
Answer: No, it illustrates "type of" inheritanceITextElement is a type of
IElement.
Question 6: What data type does ExportFrame return?
Answer: tagRECT structure
Question 7: Where is its origin (XMin, YMin)?
Answer: Left, top
Question 8: In which library will you find the tagRECT structure?
Answer: ESRI.ArcGIS.Display

12-18

Copyright 2001-2009 ESRI

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

Copyright 2001-2009 ESRI

12-19

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Exercise Solution: Exercise 12A (VB.NET)


Imports
Imports
Imports
Imports
Imports

ESRI.ArcGIS.Carto
ESRI.ArcGIS.esriSystem
ESRI.ArcGIS.Display
ESRI.ArcGIS.Geometry
ESRI.ArcGIS.Output

Public Class Form1


Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim fName As String
fName = "\Student\IPAN\Database\Templates\MyTemplate.mxt"
AxPageLayoutControl1.LoadMxFile(fName)
End Sub
Private Sub btnAddMap_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnAddMap.Click
Dim mName As String
mName = "\Student\IPAN\Exercise12\MapsAndLayers.mxd"
Dim mapDoc As IMapDocument = New MapDocument
'Dim mapDoc As IMapDocument = New MapDocumentClass
mapDoc.Open(mName)
Dim gc As IGraphicsContainer = AxPageLayoutControl1.PageLayout
Dim map As IMap
Dim mFrame As IMapFrame
Dim mapCopy As IObjectCopy
map = mapDoc.Map(0)
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
AxPageLayoutControl1.Refresh()
Export(map.Name)
End Sub
Private Sub UpdateTitle(ByVal gc As IGraphicsContainer, ByVal mapName As String)
gc.Reset()

12-20

Copyright 2001-2009 ESRI

Exercise 12A

Dim elem As IElement


Dim txtElem As ITextElement
Dim elemProps As IElementProperties3
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
If TypeOf elem Is ITextElement Then
txtElem = elem
elemProps = elem
If elemProps.Type = "Title" Then
txtElem.Text = mapName
gc.UpdateElement(txtElem)
Exit Do
End If
End If
elem = gc.Next
Loop
End Sub
Private Function returnMapFrame(ByVal gc As IGraphicsContainer) As IMapFrame
gc.Reset()
Dim elem As IElement
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
If TypeOf elem Is IMapFrame Then
Return elem
End If
elem = gc.Next
Loop
End Function
Private Sub TagTheElements(ByVal gc As IGraphicsContainer)
gc.Reset()
Dim elem As IElement
Dim txtElem As ITextElement
Dim elemProps As IElementProperties3
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
If TypeOf elem Is ITextElement Then
txtElem = elem
If txtElem.Text Like "*title*" Then
elemProps = elem
elemProps.Type = "Title"
ElseIf txtElem.Text Like "*text*" Then
elemProps = elem
elemProps.Type = "Cartographer"
End If
End If
elem = gc.Next
Loop
End Sub

Copyright 2001-2009 ESRI

12-21

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Private Sub Export (ByVal mapName As String)


Dim activeView As IActiveView
activeView = AxPageLayoutControl1.ActiveView
Dim expFrame As tagRECT
expFrame = activeView.ExportFrame
Dim env As IEnvelope
env = New Envelope
'env = New EnvelopeClass
env.PutCoords(expFrame.left, expFrame.top, expFrame.right, expFrame.bottom)
mapName = Replace(mapName, ",", "")
Dim expPDF As IExport = New ExportPDF
'Dim expPDF As IExport = New ExportPDFClass
expPDF.ExportFileName = "\Student\IPAN\Exercise12\" & mapName & ".PDF"
expPDF.PixelBounds = env
expPDF.Resolution = 300
Dim hDC As Long
hDC = expPDF.StartExporting()
activeView.Output(hDC, 300, expFrame, Nothing, Nothing)
expPDF.FinishExporting()
MessageBox.Show("Export complete!")
End Sub
' Begin optional step
Private Sub UpdateUnits(ByVal gc As IGraphicsContainer, ByVal map As IMap)
gc.Reset()
Dim elem As IElement
Dim surFrame As IMapSurroundFrame
Dim sBar As IScaleBar
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
If TypeOf elem Is IMapSurroundFrame Then
surFrame = elem
If surFrame.MapSurround.Name Like "*Scale Bar*" Then
'MessageBox.Show(surFrame.MapSurround.Name)
sBar = surFrame.MapSurround
sBar.Units = map.MapUnits
gc.UpdateElement(surFrame)
Exit Do
End If
End If
elem = gc.Next
Loop
End Sub
' End optional step
End Class

12-22

Copyright 2001-2009 ESRI

Exercise 12A

Challenge Solution: Modify the second text


element
btnAddMap_Click
TagTheElements(gc)
UpdateTitle(gc, map.Name)
UpdateUnits(gc, map) ' Optional step
UpdateElement(gc, map.Name)
AxPageLayoutControl1.Refresh()
Export(map.Name)
New sub procedure
Private Sub UpdateElement(ByVal gc As IGraphicsContainer, ByVal mapName As String)
gc.Reset()
Dim elem As IElement
Dim txtElem As ITextElement
Dim elemProps As IElementProperties3
elem = gc.Next ' Move to the first element
Do Until elem Is Nothing
If TypeOf elem Is ITextElement Then
txtElem = elem
elemProps = elem
If elemProps.Type = "Cartographer" Then
txtElem.Text = "J.K. Smith, Map Technician"
gc.UpdateElement(txtElem)
End If
End If
elem = gc.Next
Loop
End Sub

Copyright 2001-2009 ESRI

12-23

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Challenge Solution: Create layouts for all maps


Private Sub btnAddMap_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnAddMap.Click
Dim mName As String
mName = "\Student\IPAN\Exercise12\MapsAndLayers.mxd"
Dim mapDoc As IMapDocument = New MapDocument
mapDoc.Open(mName)
Dim
Dim
Dim
Dim

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

Copyright 2001-2009 ESRI

Exercise 12B

Exercise 12B: Update and export a layout (C#)


Estimated time: 60 minutes
In this exercise, you will add a template to the PageLayoutControl in an ArcGIS Engine
application. Using ArcObjects, you will modify some of the elements in the layout and
then export it to PDF format.
In this exercise, you will:

Add a template to the PageLayoutControl


Modify elements on the layout
Export the layout to a PDF file

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.

Copyright 2001-2009 ESRI

12-25

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 1: Explore a map template in ArcMap


To get started with this exercise, you will examine the map template that you will modify
with code.
Start ArcMap with a new, empty map.
Switch to layout view. (Click the Layout View button

below the map display area.)

On the Layout toolbar, click the Change Layout button

On the wizard that appears, do the following:

Select the My Templates tab, if necessary.


Click the Open
button, browse to your \Student\IPAN\Database\Templates
folder, and open PortraitClassic.mxt.
Click Finish.

On the Tools toolbar, click the Select Elements tool

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.

on the Layout toolbar, zoom to the small white box in the

Note: Be sure to use the tool on the Layout toolbar, not the Tools toolbar.

This box represents the location of your map.


Scroll or use the Pan tool
layout page.

12-26

on the Layout toolbar to navigate to the lower right of the

Copyright 2001-2009 ESRI

Exercise 12B

Using the Select Elements tool

, double-click the text element below the scale bar.

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:

Save in: \Student\IPAN\Database\Templates


File name: MyTemplate.mxt
Save as type: ArcMap Template (*.mxt)

Copyright 2001-2009 ESRI

12-27

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Close ArcMap.
Now that your are familiar with your template, you can begin writing code for it.

Step 2: Create a new project in Visual Studio


Start Visual Studio.
Create a new project, using the following as a guide:

Property

Value

Language

Visual C#

Project type

Windows

Template

Windows Forms Application

Name

PageLayout

Location

\Student\IPAN\Exercise12

Solution name

PageLayout

Make sure the box for Create directory for solution is checked.

In Design view, click Form1.


Change its Text property to Layout in the Properties window.
Add the following controls to your form, resizing your form and/or controls as needed:

PageLayoutControl
ToolbarControl
LicenseControl

Open the Properties dialog box for the ToolbarControl and do the following:

12-28

Designate the PageLayoutControl as the ToolbarControl's buddy control.


Click the Items tab.
Click Add.

Copyright 2001-2009 ESRI

Exercise 12B

On the Controls Commands dialog box, do the following:

Click the Toolsets tab.


In the Toolsets list, double-click PageLayout to add all its commands to your
ToolbarControl.
Click Close.

Click OK on the Properties dialog box.

Step 3: Load a map template


In this step, you will load a map template into your PageLayoutControl.
Navigate to the Form1_Load method.
Inside the method, declare the variable fName as String.
Set it equal to MyTemplate.mxt in your \Student\IPAN\Database\Templates folder.
Tip: To avoid typographical errors, copy the path from the Location toolbar in
ArcCatalog.
Pass fName as the argument to the LoadMxFile method on the PageLayoutControl.
Run your project.
Your layout displays on the form at run time.
Close your application.
In Visual Studio, return to Design view.
If you would like, resize your form and layout.

Step 4: Load your map document


Now that your template has been loaded, you are ready to customize the template. You
will begin by loading your map, then modifying elements that are already found on the
template.
Add a Button control to your form.
In the Properties window, set the following properties for the button:

Copyright 2001-2009 ESRI

12-29

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Property

Value

Text

Add Map

(Name)

btnAddMap

Navigate to your new button's Click event.


Declare the variable mName as String.
Set mName equal to MapsAndLayers.mxd in your \Student\IPAN\Exercise12 folder.
Declare the variable mapDoc as IMapDocument and instantiate a new MapDocument.
Build your project.
Use the developer resource of your choice to answer the following question.
Question 2: What is the data type passed as the argument to the Open method on
IMapDocument? What will you pass as the arguments?
______________________________________________________________________
Write the code to open your map document.
Because the elements on your layout reside in the graphics container, you will need to
work with a GraphicsContainer object in code.
Declare the variable gc as IGraphicsContainer and set it equal to
axPageLayoutControl1.PageLayout.
Declare the following variables, which you will populate later:

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

Copyright 2001-2009 ESRI

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.

Step 5: Add your map template to the layout


In this step, you will add your map to the layout. You will begin by calling a custom
function that will loop through all the elements and find the map frame.
In your class, create a new method called returnMapFrame that will accept the
variable gc as the input argument IGraphicsContainer and return a reference to
IMapFrame.
All of the map elements on the PageLayout control reside in the graphics container. You
need to locate the map frame within that graphics container.
Open the Carto OMD.
Question 3: What is the relationship between IPageLayout and IGraphicsContainer?
______________________________________________________________________
______________________________________________________________________
______________________________________________________________________
Inside your returnMapFrame method, call the Reset method on gc to reinitialize the
internal cursor so that the Next method will return the first element.
Complete the following code to determine whether the current element is a map frame
element. When the map frame element is found, set it as the return value for your
returnMapFrame function.
________________ elem = gc.Next(); // Move to the first element
while (________ != null)
{
if (elem ____ __________________)
return ________ as IMapFrame;
elem = gc.________();
}
return null;

Navigate to the Click event of your btnAddMap .

Copyright 2001-2009 ESRI

12-31

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 6: Tag your elements with a unique type


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 text and search for a unique
keyword. The default title on the template is "< Double-click to enter map title >". You
will need to search for a unique keyword, such as "title," such as in the following code:
if (txtElem.Text.Contains("title"))

12-32

Copyright 2001-2009 ESRI

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;

Complete the following code to test for the string "title":


if (txtElem.Text.Contains(______________))
{
}

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".

Copyright 2001-2009 ESRI

12-33

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Step 7: Modify the map title


You are now ready to update other elements on your map, starting with the map's title
text.
Create a new method named UpdateTitle that accepts the following arguments:

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"))

Before the while statement, declare txtElem as ITextElement and elemProps as


IElementProperties.
Complete the following code after the line that checks for ITextElement:

12-34

Copyright 2001-2009 ESRI

Exercise 12B

while (elem != null)


{
if (elem is ITextElement)
{
txtElem = ________ as ITextElement;
elemProps = ________ as IElementProperties3;
if (elemProps.Type.Equals("Title"))
txtElem._________ = mapName;
}
elem = gc.Next();
}

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.________);

To display your changes, enter the following code:


axPageLayoutControl1.Refresh();

Run your project and test the Add Map button.


The title updates to Kauai, HI.
Close your application.

Step 8: Export your layout to a file


After you have added or modified layout elements, you can create a digital or hard-copy
version of your map. In this step, you will export your map to a file. You will begin by
reading about the interface that you will use for exporting.
Add a new private method named Export that accepts the string mapName as its only
argument.
In your Export method, declare the variable activeView as IActiveView.
Set activeView to the ActiveView property of your PageLayoutControl.

Copyright 2001-2009 ESRI

12-35

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Next, you will set up the device rectangle to be exported.


In the Desktop Help for .NET (VS2008), view the help for the IActiveView interface
and its members.
Click the ExportFrame property.
Question 5: What data type does ExportFrame return?
______________________________________________________________________
Click tagRECT.
Question 6: Where is its origin (XMin, YMin)?
______________________________________________________________________
Complete the following code to create the export frame that will be exported:
tagRECT expFrame = activeView.______________________;

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

Copyright 2001-2009 ESRI

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 ______________;

Set the following properties on expPDF:

Property

Value

ExportFileName

"\\Student\\IPAN\\Exercise12\\" + mapName +
".PDF"

PixelBounds

env

Resolution

300

Now you are ready to perform the export.


Declare the variable hDC as int.
hDC

represents the device context handle of the export object, expPDF.

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.

Copyright 2001-2009 ESRI

12-37

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

Exercise 12B

while (elem != null)


{
elem = gc.Next();
}

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;
}

Insert a message box to display the name of your scale bar.


In the Click event of your btnAddMap, call UpdateUnits immediately after you call
UpdateTitle.
Verify that your code matches the following:
tagTheElements(gc);
UpdateTitle(gc, map.Name);
UpdateUnits(gc, map);
axPageLayoutControl1.Refresh();
Export(map.Name);

Build and run your project.


Test your button.
Question 8: What type of scale bar is in the map surround frame?
______________________________________________________________________

Copyright 2001-2009 ESRI

12-39

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

The units now display.


Close your application.
You have finished this step.
If you will be completing either of the Challenges, comment your message box.
Save your project.
Continue on to the Challenges, if you wish. Otherwise, close Visual Studio.

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.

Challenge: Modify the second text element


Estimated time: 15 minutes

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.

Challenge: Create layouts for all maps in the map document


Estimated time: 15 minutes

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

Copyright 2001-2009 ESRI

Exercise 12B

Tip: To make your code more efficient and less cluttered, begin your loop after all the
variable declarations.

Copyright 2001-2009 ESRI

12-41

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Answers to Exercise 12B Questions


Question 1: On the Scale and Units tab, how many times do you see "Unknown Units"?
What units does this refer to?
Answer: Twice; division units and label units
Question 2: What is the data type passed as the argument to the Open method on
IMapDocument? What will you pass as the arguments?
Answer: String; (mName, "")
Question 3: What is the relationship between IPageLayout and IGraphicsContainer?
Answer: IPageLayout and IGraphicsContainer are both interfaces on the
PageLayout coclass. You can cast to access one of these interfaces from the other.
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?
Answer: Two; Overwrite; with the ref keyword
Question 5: What data type does ExportFrame return?
Answer: tagRECT structure
Question 6: Where is its origin (XMin, YMin)?
Answer: Left, top
Question 7: On which OMD will you find this interface? How many export formats does
IExport support?
Answer: ESRI.ArcGIS.Output (OutputObjectModel.pdf); 10
Question 8: What type of scale bar is in the map surround frame?
Answer: Double alternating scale bar

12-42

Copyright 2001-2009 ESRI

Exercise 12B

Exercise Solution: Exercise 12B (C#)


using
using
using
using
using
using
using

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

Copyright 2001-2009 ESRI

12-43

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

axPageLayoutControl1.Refresh();
}

Export(map.Name);

public static IMapFrame returnMapFrame(IGraphicsContainer gc)


{
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
while (elem != null)
{
if (elem is IMapFrame)
return elem as IMapFrame;
elem = gc.Next();
}
return null;
}
public static void tagTheElements(IGraphicsContainer gc)
{
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
ITextElement txtElem;
IElementProperties3 elemProps;

while (elem != null)


{
if (elem is ITextElement)
{
txtElem = elem as ITextElement;
if (txtElem.Text.Contains("title"))
{
elemProps = elem as IElementProperties3;
elemProps.Type = "Title";
}
else if(txtElem.Text.Contains("text"))
{
elemProps = elem as IElementProperties3;
elemProps.Type = "Cartographer";
}
}
elem = gc.Next();
}

public static void UpdateTitle(IGraphicsContainer gc, string mapName)


{
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
ITextElement txtElem;
IElementProperties3 elemProps;

12-44

Copyright 2001-2009 ESRI

Exercise 12B

while (elem != null)


{
if (elem is ITextElement)
{
txtElem = elem as ITextElement;
elemProps = elem as IElementProperties3;
if (elemProps.Type.Equals("Title"))
txtElem.Text = mapName;
gc.UpdateElement(txtElem as IElement);
}
elem = gc.Next();
}

private void Export(string mapName)


{
IActiveView activeView = axPageLayoutControl1.ActiveView;
tagRECT expFrame = activeView.ExportFrame;
IEnvelope env = new EnvelopeClass();
env.PutCoords(
expFrame.left, expFrame.top, expFrame.right, expFrame.bottom);
mapName = mapName.Replace(", ", "");
IExport expPDF = new ExportPDFClass();
expPDF.ExportFileName =
"\\Student\\IPAN\\Exercise12\\" + mapName + ".pdf";
expPDF.PixelBounds = env;
expPDF.Resolution = 300;

int hDC = expPDF.StartExporting();


activeView.Output(hDC, 300, ref expFrame, null, null);
expPDF.FinishExporting();
MessageBox.Show("Export complete!");

// Begin optional step


private static void UpdateUnits(IGraphicsContainer gc, IMap map)
{
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
IMapSurroundFrame surFrame;
IScaleBar sbar;

Copyright 2001-2009 ESRI

12-45

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

while (elem != null)


{
if (elem is IMapSurroundFrame)
{
surFrame = elem as IMapSurroundFrame;
sBar = surFrame.Object as IScaleBar;
sBar.Units = map.MapUnits;
//MessageBox.Show(surFrame.MapSurround.Name);
gc.UpdateElement(surFrame as IElement);
break;
}
elem = gc.Next();
}

}
// End optional step
}

12-46

Copyright 2001-2009 ESRI

Exercise 12B

Challenge Solution: Modify the second text


element
tagTheElements(gc);
UpdateTitle(gc, map.Name);
UpdateUnits(gc, map); // Optional step
UpdateElement(gc); // Challenge
axPageLayoutControl1.Refresh();
Export(map.Name);
public static void UpdateElement(IGraphicsContainer gc)
{
gc.Reset();
IElement elem = gc.Next(); // Move to the first element
ITextElement txtElem;
IElementProperties3 elemProps;

while (elem != null)


{
if (elem is ITextElement)
{
txtElem = elem as ITextElement;
elemProps = elem as IElementProperties3;
if (elemProps.Type.Equals("Cartographer"))
txtElem.Text = "J.K. Smith, Map Technician";
gc.UpdateElement(txtElem as IElement);
}
elem = gc.Next();
}

Copyright 2001-2009 ESRI

12-47

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Challenge Solution: Create layouts for all maps in


the map document
for (int i = 0; i < mapDoc.MapCount; i++)
{
map = mapDoc.get_Map(i);
mFrame = returnMapFrame(gc);
mapCopy = new ObjectCopy();
//mapCopy = new ObjectCopyClass();
param = mFrame.Map;
mapCopy.Overwrite(map, ref param);
tagTheElements(gc);
UpdateTitle(gc, map.Name);
UpdateUnits(gc, map); // Optional step
UpdateElement(gc); // Challenge
axPageLayoutControl1.Refresh();
}

12-48

Export(map.Name);

Copyright 2001-2009 ESRI

A
ESRI data license
agreement

Appendix A

IMPORTANT READ CAREFULLY


BEFORE OPENING THE SEALED MEDIA PACKAGE
ENVIRONMENTAL SYSTEMS RESEARCH INSTITUTE, INC. (ESRI), IS WILLING TO LICENSE THE
ENCLOSED ELECTRONIC VERSION OF THIS TRAINING COURSE TO YOU ONLY UPON THE
CONDITION THAT YOU ACCEPT ALL OF THE TERMS AND CONDITIONS CONTAINED IN THIS
ESRI DATA LICENSE AGREEMENT. PLEASE READ THE TERMS AND CONDITIONS CAREFULLY
BEFORE OPENING THE SEALED MEDIA PACKAGE. BY OPENING THE SEALED MEDIA
PACKAGE, YOU ARE INDICATING YOUR ACCEPTANCE OF THE ESRI DATA LICENSE
AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS AS STATED, THEN
ESRI IS UNWILLING TO LICENSE THE TRAINING COURSE TO YOU. IN SUCH EVENT, YOU
SHOULD RETURN THE MEDIA PACKAGE WITH THE SEAL UNBROKEN AND ALL OTHER
COMPONENTS (E.G., THE CD-ROM, TRAINING COURSE MATERIALS, TRAINING DATABASE, AS
APPLICABLE) TO ESRI OR ITS AUTHORIZED INSTRUCTOR FOR A REFUND. NO REFUND WILL
BE GIVEN IF THE MEDIA PACKAGE SEAL IS BROKEN OR THERE ARE ANY MISSING
COMPONENTS.

ESRI DATA LICENSE AGREEMENT


This is a license agreement, and not an agreement for sale, between you (Licensee) and ESRI. This ESRI data
license agreement (Agreement) gives Licensee certain limited rights to use the electronic version of the
training course materials, training database, software, and related materials (hereinafter collectively referred
to as the "Training Course"). All rights not specifically granted in this Agreement are reserved to ESRI and its
licensor(s).
Reservation of Ownership and Grant of License: ESRI and its licensor(s) retain exclusive rights, title,
and ownership to the copy of the Training Course licensed under this Agreement and hereby grant to Licensee
a personal, nonexclusive, nontransferable license to use the Training Course as a single package for
Licensee's own personal use only pursuant to the terms and conditions of this Agreement. Licensee agrees to
use reasonable efforts to protect the Training Course from unauthorized use, reproduction, distribution, or
publication.
Proprietary Rights and Copyright: Licensee acknowledges that the Training Course is proprietary and
confidential property of ESRI and its licensor(s) and is protected by United States copyright laws and
applicable international copyright treaties and/or conventions.

Copyright 2001-2009 ESRI

A-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Uses Not Permitted:

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

Copyright 2001-2009 ESRI

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

Copyright 2001-2009 ESRI

A-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

B
Suggested reading

Appendix B

Reading list

1.

C# & VB.NET Conversion Pocket Reference


Jose Mojica. O'Reilly Media, Inc.

2.

C# How to Program
H.M. Deitel, P. J. Deitel, J. Listfield, T.R. Nieto, C. Yaeger, M. Zlatkina. Prentice
Hall.

3.

Getting to Know ArcObjects: Programming ArcObjects with VBA


Robert Burke. ESRI Press.

4.

Microsoft Press books about developer tools


Available from Microsoft at
www.microsoft.com/learning/books/devtools/default.mspx.

5.

Microsoft Press books about Microsoft .NET


Available from Microsoft at www.microsoft.com/learning/books/net/default.mspx.

6.

Professional Visual Studio 2008


Nick Randolph, David Gardner. John Wiley & Sons, Incorporated (2008)

Copyright 2001-2009 ESRI

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.

Tools in the ...\ArcGIS\DeveloperKit folder


ESRI Object Browser
Library Locator
Object model diagrams
COM samples
.NET samples
ArcGIS developer resources (Start menu > All Programs > ArcGIS > Developer
Help)
Desktop Help for .NET (VS2008)
Engine Help for .NET (VS2008)
Visual Studio resources
Help
MSDN Forums
Samples
Visual Studio Object Browser
Online resources
ESRI Resource Center (http://resources.esri.com)
ESRI Support Center (http://support.esri.com)
Use the search engine of your choice to search for VB versus C#.

Copyright 2001-2009 ESRI

C-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Working with snippets

With the ArcGIS Snippet Finder, you can find and insert ArcGIS snippets into a Visual
Studio 2008 project using keyword searches.

ESRI-written snippets reside in the following folders:


...\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets
...\Program Files\Microsoft Visual Studio 9.0\VB\Snippets
An index of snippets is available in the Desktop or Engine Help for .NET
(VS2008):
Visual Studio Integration Tools >
Snippet Index

Shortcut keys for Visual Basic 2008

To find lists of useful keyboard shortcuts, search the Microsoft Download Center for:

Visual Basic 2008 Keybinding Reference Poster


Visual C# 2008 Keybinding Reference Poster

Unregistering your command

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.

For example: regasm MySample.dll/unregister

Regasm.exe is located in: %windir%\Microsoft.NET\Framework\v2.0.xxxx (where xxxx


is the build number of the .NET framework you are using).

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

represents your version)


Type regasm.exe <path to your DLL>/dllname.dll/unregister

Copyright 2001-2009 ESRI

E
Extend ArcGIS
Desktop with a custom
tool (VB.NET)

Appendix E

Extend ArcGIS Desktop with a custom tool (VB.NET)


Estimated time: 45 minutes
A Dynamic Link Library (DLL) can be used to either customize or extend your
application. It acts as a shared library of functions that cannot, however, be directly
executed. In this exercise, you will create a command by inheriting from the
BaseCommand class available in the Application Developer Framework (ADF) assembly.
When added to ArcMap, this command will allow you to zoom a map to the specific
extent of a selected layer.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following table as a guide:

Property

Value

Language

Visual Basic

Project type

ArcGIS > Desktop

Template

Class Library (ArcMap)

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.

Copyright 2001-2009 ESRI

E-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 2: Create the COM class: myExtent


COM requires every non-private object to have a unique identifier, called a GUID
(Globally Unique Identifier). To make it easier to write a GUID, it is normally expressed
as a hexadecimal number (e.g., 99B42120-6EC7-11CF-A6C7-00AA00A47DD2) and is
called CLSID (Class Identifier) when the GUID is the identification number for a COM
object. Also, the Programmatic Identifier (ProgID) presents a human-readable version of
the CLSID to identify COM objects. The project and class names make up the ProgID
and can be used to uniquely identify your component.
In this step, you will create your own COM component by setting some of the class
properties. A number of COM interoperability attributes will be used to define the class
as a COM class.
In the Solution Explorer window, right-click Class1.vb and choose Delete.
Click OK on the message about the class being deleted permanently.
In the Solution Explorer window, right-click Customize and choose Add > New Item.
In the Add New Item dialog box, specify the following properties:

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:

A member variable m_application is declared for the IApplication interface


representing ArcMap. application
The constructor is set up with stub code.
The overridden OnCreate method with the application hook is created.
The overridden OnClick method is stubbed out.

Expand the COM GUIDs section and review the code.

E-2

Copyright 2001-2009 ESRI

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.

Step 3: Reference ArcGIS Libraries


In the .NET framework, namespaces are the basic building blocks that define the classes
in a hierarchical structure. Using a namespace in a project requires a reference, which you
must add to the project before the classes in the namespace can be used.
In this step, you will reference the appropriate type libraries to build the custom
command.
From the Project menu, choose Add ArcGIS Reference.
In the Add ArcGIS Reference dialog box, add the following references:

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.

Step 4: Make simple changes to the code


In the myExtent.vb code window, scroll down to the constructor for the class.
Notice that all the command properties are empty strings.

Copyright 2001-2009 ESRI

E-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Update their values as follows:


MyBase.m_category = "Extent Commands"
MyBase.m_caption = "My Extent Command"
MyBase.m_message = "Zoom to the extent of the active layer in the TOC"
MyBase.m_toolTip = "Zoom in"
MyBase.m_name = "Customize_MyExtentCommand"

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.

Change the File Name to myExtent.bmp.


You will now write a piece of code to shrink the extent (width and height) of the current
view in ArcMap to 40% of its original size, and reset the active view to the new extent.
In the code window, scroll down to locate the OnClick property. Expand the
overridden class methods, if necessary.

E-4

Copyright 2001-2009 ESRI

Appendix E

Add the following code to the OnClick property:


Dim mxDoc As IMxDocument = m_application.Document
Dim activeView As IActiveView = mxDoc.ActiveView
Dim currExtent As IEnvelope = activeView.Extent
currExtent.Expand(0.4D, 0.4D, True)
activeView.Extent = currExtent
activeView.Refresh()

Save the solution.

Step 5: Compile and register


In this step, you will compile the project. When you do so, .NET will automatically
register the component with COM for you.
Build your solution and check for any errors. (Tip: Ctrl+Shift+B)
To check the results of the Build operation, examine the sub-directories of your project
in Windows Explorer. (Hint: \bin\Debug directory)
Notice that the Debug directory contains a debug information (.pdb) file and a type
library file (.tlb) produced by the Assembly Registration tool.

Step 6: Test your control in ArcMap


In this step, you will verify that the component has been registered correctly with COM
by testing it in ArcMap.
Start ArcMap and browse to \Student\IPAN\Exercise05\MapsAndLayers.mxd.
From the Tools menu, choose Customize.
In the Customize dialog box, click the Commands tab.
In the Save in pull-down list, verify that the current map is chosen.

Click the Add From File button.

Copyright 2001-2009 ESRI

E-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Navigate to the location of your custom DLL.


Select Customize.tlb and click Open.

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.

Drag the control onto one of the ArcMap toolbars.


Close the Customize dialog box.
Test the component.

E-6

Copyright 2001-2009 ESRI

Appendix E

Close ArcMap without saving any changes.

Step 7: Use ILDASM to read the DLL


In this step, you will use the MSIL Disassembler (Ildasm.exe) to read the actual contents
of the DLL file that you created.
Note: You need to compile a project at least once before you can run ILDASM on its
executable.

In Visual Studio, from the Tools menu, choose External Tools.


Click the Add button.
Specify the following:

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.

You must close ILDASM before recompiling the application or Visual


Studio will not be able to overwrite the executable file. In some cases,
it is not possible to recover from this error and you will have to restart
Visual Studio.

Close Visual Studio.

Step 8: Using Component Category Manager


Currently, the classes in your DLL are registered to the Extent Commands category. This
means that they are also registered to the ESRI Mx Commands component category,
which allows the DLL to be used in ArcMap.

Copyright 2001-2009 ESRI

E-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

E-9

F
Extend ArcGIS
Desktop with a custom
tool (C#)

Appendix F

Extend ArcGIS Desktop with a custom tool (C#)


Estimated time: 45 minutes
A Dynamic Link Library (DLL) can be used to either customize or extend your
application. It acts as a shared library of functions that cannot, however, be directly
executed. In this exercise, you will create a command by inheriting from the
BaseCommand class available in the Application Developer Framework (ADF) assembly.
When added to ArcMap, this command will allow you to zoom a map to the specific
extent of a selected layer.

Step 1: Create a new project in Visual Studio


Start Visual Studio and create a new project, using the following table as a guide:

Property

Value

Language

Visual C#

Project type

ArcGIS > Desktop

Template

Class Library (ArcMap)

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.

Copyright 2001-2009 ESRI

F-1

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Step 2: Create the COM class: myExtent


COM requires every non-private object to have a unique identifier, called a GUID
(Globally Unique Identifier). To make it easier to write a GUID, it is normally expressed
as a hexadecimal number (e.g., 99B42120-6EC7-11CF-A6C7-00AA00A47DD2) and is
called CLSID (Class Identifier) when the GUID is the identification number for a COM
object. Also, the Programmatic Identifier (ProgID) presents a human-readable version of
the CLSID to identify COM objects. The project and class names make up the ProgID
and can be used to uniquely identify your component.
In this step, you will create your own COM component by setting some of the class
properties. A number of COM interoperability attributes will be used to define the class
as a COM class.
In the Solution Explorer window, right-click Class1.cs and choose Delete.
Click OK on the message about the class being deleted permanently.
In the Solution Explorer window, right-click Customize and choose Add > New Item.
In the Add New Item dialog box, specify the following properties:

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:

A member variable m_application is declared for the IApplication interface


representing ArcMap application.
The constructor is set up with stub code.
The overridden OnCreate method with the application hook is created.
The overridden OnClick method is stubbed out.

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

Copyright 2001-2009 ESRI

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.

Step 3: Reference ArcGIS Libraries


In the .NET framework, namespaces are the basic building blocks that define the classes
in a hierarchical structure. Using a namespace in a project requires a reference, which you
must add to the project before the classes in the namespace can be used.
In this step, you will reference the appropriate type libraries to build the custom
command.
From the Project menu, choose Add ArcGIS Reference.
In the Add ArcGIS Reference dialog box, add the following references:

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.

Step 4: Make simple changes to the code


In the myExtent.cs code window, scroll down to the constructor for the class.
Notice that all the command properties are empty strings.
Update their values as follows:
base.m_category = "Extent Commands";
base.m_caption = "My Extent Command";
base.m_message = "Zoom to the extent of the active layer in the TOC";
base.m_toolTip = "Zoom in";
base.m_name = "Customize_MyExtentCommand";

Copyright 2001-2009 ESRI

F-3

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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.

Change the File Name to myExtent.bmp.


You will now write a piece of code to shrink the extent (width and height) of the current
view in ArcMap to 40% of its original size, and reset the active view to the new extent.
In the code window, scroll down to locate the OnClick property. Expand the
overridden class methods, if necessary.
Add the following code to the OnClick property:

F-4

Copyright 2001-2009 ESRI

Appendix F

IMxDocument mxDoc = m_application.Document as IMxDocument;


IActiveView activeView = mxDoc.ActiveView;
IEnvelope currExtent = activeView.Extent;
currExtent.Expand(0.4D, 0.4D, true);
activeView.Extent = currExtent;
activeView.Refresh();

Save the solution.

Step 5: Compile and register


In this step, you will compile the project. When you do so, .NET will automatically
register the component with COM for you.
Build your solution and check for any errors. (Tip: Ctrl+Shift+B)
To check the results of the Build operation, examine the sub-directories of your project
in Windows Explorer. (Hint: \bin\Debug directory)
Notice that the Debug directory contains a debug information (.pdb) file and a type
library file (.tlb) produced by the Assembly Registration tool.

Step 6: Test your control in ArcMap


In this step, you will verify that the component has been registered correctly with COM
by testing it in ArcMap.
Start ArcMap and browse to \Student\IPAN\Exercise05\MapsAndLayers.mxd.
From the Tools menu, choose Customize.
In the Customize dialog box, click the Commands tab.
In the Save in pull-down list, verify that the current map is chosen.

Click the Add From File button.


Navigate to the location of your custom DLL.

Copyright 2001-2009 ESRI

F-5

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

Select Customize.tlb and click Open.

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.

Drag the control onto one of the ArcMap toolbars.


Close the Customize dialog box.
Test the component.
Close ArcMap without saving any changes.

F-6

Copyright 2001-2009 ESRI

Appendix F

Step 7: Use ILDASM to read the DLL


In this step, you will use the MSIL Disassembler (Ildasm.exe) to read the actual contents
of the DLL file that you created.
Note: You need to compile a project at least once before you can run ILDASM on its
executable.

In Visual Studio, from the Tools menu, choose External Tools.


Click the Add button.
Specify the following:

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.

You must close ILDASM before recompiling the application or Visual


Studio will not be able to overwrite the executable file. In some cases,
it is not possible to recover from this error and you will have to restart
Visual Studio.

Close Visual Studio.

Step 8: Using Component Category Manager


Currently, the classes in your DLL are registered to the Extent Commands category. This
means that they are also registered to the ESRI Mx Commands component category,
which allows the DLL to be used in ArcMap.

Copyright 2001-2009 ESRI

F-7

Introduction to Programming ArcObjects Using the Microsoft .NET Framework

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

Copyright 2001-2009 ESRI

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.

Copyright 2001-2009 ESRI

F-9

You might also like