Qtools GIS
Part 5: Adding the Utility’s Dialog Form
Tutorial Navigation | Previous: Part 4: Creating New Add-in Project | Next: Part 6: Converting VBA ArcObjects to CS
Continuing with the Visual Studio project from Part 4, we will now replicate the dialog form used by the VBA utility.
Note: In this tutorial we are performing a mostly line-by-line conversion of VBA to C#. At this stage, no attempt will be made to conform to all best practices for C# coding, such as robust and specific exception handling.
Resources
Files
See Part 4.
Video Demonstrations
The following videos are also linked from the relevant sections below. (opens in a new browser window or tab)
Add new form and add controls to it (duration 1:07)
Set properties of controls.. (duration 1:02)
Set properties of controls..continued (duration 0:58)
Finishing setting control properties and re-position (duration 1:14)
Set properties of form (duration 0:47)
Quick test of dialog form in ArcMap (duration 0:39)
Add form’s event handlers and private fields (duration 0:42)
Add properties and code to form class (duration 1:00)
Finish coding form class, add test code to button, and test in ArcMap (duration 1:10)
Adding and Designing the Dialog Form
Add a Blank Form to the Project
Video Demonstation: Add new form and add controls to it (duration 1:07)
Open the Solution Explorer if it is not visible (View | Solution Explorer). Right-click on the project name (“VBA_to_CS_Tutorial”) and select Add | Windows Form… from the context menu.
Locate and select the Visual C# Items item in the Categories list. Under Templates, select Windows Form. Change the Name to “frmStaggerOffset.cs”. Click the OK button.
A new blank form will be added to the project and will be displayed in design view.
Add Controls to the Form
Video Demonstation: Set properties of controls.. (duration 1:02)
Video Demonstation: Set properties of controls..continued (duration 0:58)
Video Demonstation: Finishing setting control properties and re-position (duration 1:14)
Use the image below (or the provided VBA_OffsetFeatures_Form.png image file) to resize the form and as a guide to adding visual controls from the toolbox.
Add a Label
Text: Be sure to have an active edit session.
Add a Label
Name: labLayerInfo
Text: Layer Info…
Add a Label
Text: Enter the amount of offset in map units (feet).
Add a Label
Text: North-South Route (East-West Offset)
Add a Label
Text: East-West Route (North-South Offset)
Add a TextBox (to the right of North-South Route label)
Name: txtOffsetX
Add a TextBox (to the right of East-West Route label)
Name: txtOffsetY
Add a Button
Name: btnOk
DialogResult: OK
Text: &OK
Add a Button
Name: btnCancel
DialogResult: Cancel
Text: &Cancel
Set Properties of the Form
Video Demonstation: Set properties of form (duration 0:47)
Click once on an empty area of the form to select it. Open the Properties window and edit the following properties for the form:
AcceptButton: btnOk
CancelButton: btnCancel
FormBorderStyle: FixedDialog
MaximizeBox: False
MinimizeBox: False
StartPosition: CenterParent
Text: Stagger Offset Features
Test the Dialog Form
Video Demonstation: Quick test of dialog form in ArcMap (duration 0:39)
In the Solution Explorer, open the StaggerOffsetButton.cs file (double-click it). It will display in the Code Editor.
Replace the code in the OnClick()
method with the following code to display the new dialog form in ArcMap:
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | protected override void OnClick() { try { // Create the form frmStaggerOffset staggerOffsetDialog = new frmStaggerOffset(); // Display the form as a modal dialog staggerOffsetDialog.ShowDialog(); } catch (Exception ex) { MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace); // Uncomment next line to re-throw the exception, which will halt ArcMap // throw; } } |
Note: Wrapping all your code in a “catch all” exception handler prevents unhandled exceptions from crashing ArcMap, and the message displayed will help you debug the problem. However, be aware that there is the potential for ArcMap to be left in an unstable state depending on the operation that caused the exception.
Start debugging (press green arrow button or F5).
Wait for ArcMap to load. Once it opens, open the provided VBAtoCS_Tutorial_01_v10.mxd map. Your toolbar and button should be where you placed on a tool panel.
Click the button to display the new dialog form.
Click the Cancel button to close the form, and close ArcMap to return to Visual Studio and stop debugging.
Provide Access to Dialog Values
Video Demonstation: Add form’s event handlers and private fields (duration 0:42)
Unlike VBA, in C# the form’s controls are private to the form class. In order to pass information between the form and the code in the button class we need to create some public properties, and hook into some events.
Right-click on a blank area of the form in design view and select View Code… from the context menu.
Initially, the form code file contains:
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace VBA_to_CS_Tutorial { public partial class frmStaggerOffset : Form { public frmStaggerOffset() { InitializeComponent(); } } } |
Expand this to view the entire frmStaggerOffsets.cs file after making the following changes (+/-)
We need to pass a string with layer information to the dialog to display when it opens, and then return to numeric values for the offsets when closed.
Click on the frmStaggerOffset.cs [Design] tab page to display the form designer and click once on an empty area of the form to select it. Open the Properties window and switch to Events view by clicking the lightning bolt button:
Locate the FormClosing
event and double-click on it to insert a new event handler in the form code file, which we will use to set the return values.
Repeat to add an event handler for the Load
event.
View the form in the designer again and double-click on the OK button to insert an event handler for it as well.
At the top of the class add two new private double fields:
private double offsetX = 0; private double offsetY = 0; |
Video Demonstation: Add properties and code to form class (duration 1:00)
Next, add two public read-only properties to access the fields. (Notice the uppercase first letter, which differentiates the identifiers for the property and its field. C# is case-sensitive. You could also use differently spelled identifiers, but the manner shown is the widely used convention.):
public double OffsetX { get { return offsetX; } } public double OffsetY { get { return offsetY; } } |
When the OK button is clicked, we want to close the form. Locate the empty click event handler and enter code to call the form’s Close()
method:
private void btnOk_Click(object sender, EventArgs e) { this.Close(); } |
Locate the empty Load
event handler and add two statements to initialize the offset value controls to zero:
private void frmStaggerOffset_Load(object sender, EventArgs e) { // Set defaults for offsets this.txtOffsetX.Text = "0"; this.txtOffsetY.Text = "0"; } |
We want to pass a string to the dialog, so we will add an overloaded constructor. Insert the following code directly under the existing constructor:
// Overload the constructor to accept an argument public frmStaggerOffset(string layerInfo) : this() // call the default constructor { // Display the layer info on the form this.labLayerInfo.Text = layerInfo; } |
And finally, we need to validate the values entered for offsets in the FormClosing
event handler:
private void frmStaggerOffset_FormClosing(object sender, FormClosingEventArgs e) { if (this.DialogResult != DialogResult.OK) { // abort this method and skip validation return; } try { offsetX = Convert.ToDouble(this.txtOffsetX.Text); offsetY = Convert.ToDouble(this.txtOffsetY.Text); } catch (Exception ex) { MessageBox.Show("Please enter a valid number.\n\n" + ex.Message, "Invalid Offset Value(s)"); e.Cancel = true; // Prevents form from closing } } |
Video Demonstation: Finish coding form class, add test code to button, and test in ArcMap (duration 1:10)
Test Setting and Getting Dialog Values
To test the new form, we will additional code to the Add-In Button’s OnClick()
method.
Select the StaggerOffsetButton.cs file in the code editor, locate the OnClick()
method and replace its contents with the following code:
protected override void OnClick() { try { // Set the Layer Info string layerInfo = "Move xx features in:\n" + "SomeFeatureClassName"; // Create the form frmStaggerOffset staggerOffsetDialog = new frmStaggerOffset(layerInfo); // Display the form as a modal dialog staggerOffsetDialog.ShowDialog(); // Check if form was cancelled if (staggerOffsetDialog.DialogResult != DialogResult.OK) { // abort return; } // Get the offset values from the form double offsetX = staggerOffsetDialog.OffsetX; double offsetY = staggerOffsetDialog.OffsetY; // Display the offset values for testing MessageBox.Show("offsetX: " + offsetX.ToString() + "\noffsetY: " + offsetY.ToString()); } catch (Exception ex) { MessageBox.Show(ex.Message + "\n\n" + ex.StackTrace); } } |
Start debugging (press green arrow button or F5).
Wait for ArcMap to load. Once it opens, open the provided VBAtoCS_Tutorial_01_v10.mxd map. Your toolbar and button should be where you placed on a tool panel.
Click the Add-In’s button to display the new dialog form.
Notice the layer info label text has been fill with:
Move xx features in:
SomeFeatureClassName
Enter various valid (numeric) values for the offsets and click the OK button to verify they are returned correctly from the dialog.
Try some invalid (non-numeric) values to verify error handling.
Close ArcMap to return to Visual Studio and stop debugging.
Now that the dialog form is functional, it is time to turn our attention to converting VBA ArcObjects code to C#.
Tutorial Navigation | Previous: Part 4: Creating New Add-in Project | Next: Part 6: Converting VBA ArcObjects to CS
#1 by Ann on April 27, 2016 - 10:21 am
Good tutorial. I have a quick question:
This code is in a VBA module called CreateData:
Public doing As String
Public Function CreateSQLGDB(cmdstrin As String) As IWorkspace
Dim pWorkspace As IWorkspace
Dim pPropset As IPropertySet
Set pPropset = New PropertySet
pPropset.SetProperty “CONNECTSTRING”, connStr
Dim pWorkspaceFact As IWorkspaceFactory
Set pWorkspaceFact = New OLEDBWorkspaceFactory
Set pWorkspace = pWorkspaceFact.Open(pPropset, 0)
Dim cmdstr As String
cmdstr = cmdstrin
pWorkspace.ExecuteSQL cmdstr
Set pWorkspace = Nothing
Set pPropset = Nothing
End Function
How can I convert it into C#? Thanks