{"id":27,"date":"2010-12-09T17:12:52","date_gmt":"2010-12-10T01:12:52","guid":{"rendered":"http:\/\/gis.qtools.com\/blog\/"},"modified":"2016-04-11T12:11:47","modified_gmt":"2016-04-11T19:11:47","slug":"part-5-adding-utility-dialog-form","status":"publish","type":"page","link":"https:\/\/gis.qtools.com\/blog\/tutorials\/vba-to-c-add-in\/part-5-adding-utility-dialog-form\/","title":{"rendered":"Part 5: Adding the Utility&#8217;s Dialog Form"},"content":{"rendered":"<p><strong>Tutorial Navigation<\/strong> | Previous: <a href=\"..\/part-4-creating-new-add-in-project\/\">Part 4: Creating New Add-in Project<\/a> | Next: <a href=\"..\/part-6-converting-vba-arcobjects-to-cs\/\">Part 6: Converting VBA ArcObjects to CS<\/a><\/p>\n<p>Continuing with the Visual Studio project from Part 4, we will now replicate the dialog form used by the VBA utility.<\/p>\n<p>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.<\/p>\n<h1>Resources<\/h1>\n<h3>Files<\/h3>\n<p>See Part 4.<\/p>\n<h3>Video Demonstrations<\/h3>\n<p>The following videos are also linked from the relevant sections below. (opens in a new browser window or tab)<\/p>\n<p><a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt1.swf.html\" target=\"_blank\">Add new form and add controls to it<\/a> (duration 1:07)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt2.swf.html\" target=\"_blank\">Set properties of controls..<\/a> (duration 1:02)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt3.swf.html\" target=\"_blank\">Set properties of controls..continued<\/a> (duration 0:58)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt4.swf.html\" target=\"_blank\">Finishing setting control properties and re-position<\/a> (duration 1:14)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt5.swf.html\" target=\"_blank\">Set properties of form<\/a> (duration 0:47)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt6.swf.html\" target=\"_blank\">Quick test of dialog form in ArcMap<\/a> (duration 0:39)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt7.swf.html\" target=\"_blank\">Add form&#8217;s event handlers and private fields<\/a> (duration 0:42)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt8.swf.html\" target=\"_blank\">Add properties and code to form class<\/a> (duration 1:00)<br \/>\n<a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt9.swf.html\" target=\"_blank\">Finish coding form class, add test code to button, and test in ArcMap<\/a> (duration 1:10)<\/p>\n<h1>Adding and Designing the Dialog Form<\/h1>\n<h2>Add a Blank Form to the Project<\/h2>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt1.swf.html\" target=\"_blank\">Add new form and add controls to it<\/a> (duration 1:07)<\/p>\n<p>Open the Solution Explorer if it is not visible (<em>View | Solution Explorer<\/em>). Right-click on the project name (&#8220;VBA_to_CS_Tutorial&#8221;) and select <em>Add | Windows Form&#8230;<\/em> from the context menu.<\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_01.png\" \/><\/p>\n<p>Locate and select the <em>Visual C# Items<\/em> item in the <em>Categories <\/em>list. Under <em>Templates<\/em>, select <em>Windows Form<\/em>. Change the <em>Name <\/em> to &#8220;frmStaggerOffset.cs&#8221;. Click the <em>OK <\/em>button.<\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_02.png\" \/><\/p>\n<p>A new blank form will be added to the project and will be displayed in design view.<\/p>\n<h2>Add Controls to the Form<\/h2>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt2.swf.html\" target=\"_blank\">Set properties of controls..<\/a> (duration 1:02)<br \/>\n<b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt3.swf.html\" target=\"_blank\">Set properties of controls..continued<\/a> (duration 0:58)<br \/>\n<b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt4.swf.html\" target=\"_blank\">Finishing setting control properties and re-position<\/a> (duration 1:14)<\/p>\n<p>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.<\/p>\n<p>Add a Label<br \/>\n  Text: Be sure to have an active edit session.<\/p>\n<p>Add a Label<br \/>\n  Name: labLayerInfo<br \/>\n  Text: Layer Info&#8230;<\/p>\n<p>Add a Label<br \/>\n  Text: Enter the amount of offset in map units (feet).<\/p>\n<p>Add a Label<br \/>\n  Text: North-South Route (East-West Offset)<\/p>\n<p>Add a Label<br \/>\n  Text: East-West Route (North-South Offset)   <\/p>\n<p>Add a TextBox (to the right of North-South Route label)<br \/>\n  Name: txtOffsetX<\/p>\n<p>Add a TextBox (to the right of East-West Route label)<br \/>\n  Name: txtOffsetY<\/p>\n<p>Add a Button<br \/>\n  Name: btnOk<br \/>\n  DialogResult: OK<br \/>\n  Text: &amp;OK<\/p>\n<p>Add a Button<br \/>\n  Name: btnCancel<br \/>\n  DialogResult: Cancel<br \/>\n  Text: &amp;Cancel<\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_03.png\" \/><\/p>\n<h2>Set Properties of the Form<\/h2>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt5.swf.html\" target=\"_blank\">Set properties of form<\/a> (duration 0:47)<\/p>\n<p>Click once on an empty area of the form to select it. Open the Properties window and edit the following properties for the form:<\/p>\n<p>AcceptButton: btnOk<br \/>\nCancelButton: btnCancel<br \/>\nFormBorderStyle: FixedDialog<br \/>\nMaximizeBox: False<br \/>\nMinimizeBox: False<br \/>\nStartPosition: CenterParent<br \/>\nText: Stagger Offset Features<\/p>\n<h2>Test the Dialog Form<\/h2>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt6.swf.html\" target=\"_blank\">Quick test of dialog form in ArcMap<\/a> (duration 0:39)<\/p>\n<p>In the <em>Solution Explorer<\/em>, open the <em>StaggerOffsetButton.cs <\/em>file (double-click it). It will display in the Code Editor.<\/p>\n<p>Replace the code in the <code>OnClick()<\/code> method with the following code to display the new dialog form in ArcMap:<\/p>\n<pre lang=\"csharp\" line=\"15\">\r\nprotected override void OnClick()\r\n{\r\n    try\r\n    {\r\n        \/\/ Create the form\r\n        frmStaggerOffset staggerOffsetDialog = new frmStaggerOffset();\r\n        \/\/ Display the form as a modal dialog\r\n        staggerOffsetDialog.ShowDialog();\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        MessageBox.Show(ex.Message + \"\\n\\n\" + ex.StackTrace); \r\n        \/\/ Uncomment next line to re-throw the exception, which will halt ArcMap\r\n        \/\/ throw;\r\n    }\r\n}\r\n<\/pre>\n<p>Note: Wrapping all your code in a &#8220;catch all&#8221; 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.<\/p>\n<p>Start debugging (press green arrow button or F5).<\/p>\n<p>Wait for ArcMap to load. Once it opens, open the provided <em>VBAtoCS_Tutorial_01_v10.mxd <\/em>map. Your toolbar and button should be where you placed on a tool panel.<\/p>\n<p>Click the button to display the new dialog form.<\/p>\n<p>Click the Cancel button to close the form, and close ArcMap to return to Visual Studio and stop debugging.<\/p>\n<h2>Provide Access to Dialog Values<\/h2>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt7.swf.html\" target=\"_blank\">Add form&#8217;s event handlers and private fields<\/a> (duration 0:42)<\/p>\n<p>Unlike VBA, in C# the form&#8217;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.<\/p>\n<p>Right-click on a blank area of the form in design view and select <em>View Code&#8230; <\/em>from the context menu.<\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_04.png\" \/><\/p>\n<p>Initially, the form code file contains:<\/p>\n<pre lang=\"csharp\" line=\"15\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.ComponentModel;\r\nusing System.Data;\r\nusing System.Drawing;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Windows.Forms;\r\n\r\nnamespace VBA_to_CS_Tutorial\r\n{\r\n    public partial class frmStaggerOffset : Form\r\n    {\r\n        public frmStaggerOffset()\r\n        {\r\n            InitializeComponent();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Expand this to view the entire <em>frmStaggerOffsets.cs <\/em>file after making the following changes (<a href=\"#\" onclick=\"xcollapse('X5543');return false;\">+\/-<\/a>)<\/p>\n<div id=\"X5543\" style=\"display: none; background: transparent;\">\n<pre lang=\"csharp\" line=\"1\">\r\nusing System;\r\nusing System.Collections.Generic;\r\nusing System.ComponentModel;\r\nusing System.Data;\r\nusing System.Drawing;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Windows.Forms;\r\n\r\nnamespace VBA_to_CS_Tutorial\r\n{\r\n    public partial class frmStaggerOffset : Form\r\n    {\r\n        private double offsetX = 0;\r\n        private double offsetY = 0;\r\n\r\n        public frmStaggerOffset()\r\n        {\r\n            InitializeComponent();\r\n        }\r\n\r\n        \/\/ Overload the constructor to accept an argument\r\n        public frmStaggerOffset(string layerInfo)\r\n            : this()  \/\/ call the default constructor\r\n        {\r\n            \/\/ Display the layer info on the form\r\n            this.labLayerInfo.Text = layerInfo;\r\n        }\r\n\r\n        private void btnOk_Click(object sender, EventArgs e)\r\n        {\r\n            this.Close();\r\n        }\r\n\r\n        private void frmStaggerOffset_FormClosing(object sender,\r\n            FormClosingEventArgs e)\r\n        {\r\n            if (this.DialogResult != DialogResult.OK)\r\n            {\r\n                \/\/ abort this method and skip validation\r\n                return;\r\n            }\r\n\r\n            try\r\n            {\r\n                offsetX = Convert.ToDouble(this.txtOffsetX.Text);\r\n                offsetY = Convert.ToDouble(this.txtOffsetY.Text);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                MessageBox.Show(\"Please enter a valid number.\\n\\n\" +\r\n                    ex.Message, \"Invalid Offset Value(s)\");\r\n                e.Cancel = true; \/\/ Prevents form from closing\r\n            }\r\n        }\r\n\r\n        private void frmStaggerOffset_Load(object sender, EventArgs e)\r\n        {\r\n            \/\/ Set defaults for offsets\r\n            this.txtOffsetX.Text = \"0\";\r\n            this.txtOffsetY.Text = \"0\";\r\n        }\r\n\r\n        public double OffsetX\r\n        {\r\n            get { return offsetX; }\r\n        }\r\n\r\n        public double OffsetY\r\n        {\r\n            get { return offsetY; }\r\n        }\r\n\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>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.<\/p>\n<p>Click on the <em>frmStaggerOffset.cs [Design]<\/em> 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 <em>Events <\/em>view by clicking the lightning bolt button:<\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_05.png\" \/><\/p>\n<p>Locate the <code>FormClosing<\/code> 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.<\/p>\n<p>Repeat to add an event handler for the <code>Load<\/code> event.<\/p>\n<p>View the form in the designer again and double-click on the <em>OK <\/em>button to insert an event handler for it as well.<\/p>\n<p>At the top of the class add two new private double fields:<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\nprivate double offsetX = 0;\r\nprivate double offsetY = 0;\r\n<\/pre>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt8.swf.html\" target=\"_blank\">Add properties and code to form class<\/a> (duration 1:00)<\/p>\n<p>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.):<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\npublic double OffsetX\r\n{\r\n    get { return offsetX; }\r\n}\r\n\r\npublic double OffsetY\r\n{\r\n    get { return offsetY; }\r\n}\r\n<\/pre>\n<p>When the <em>OK <\/em>button is clicked, we want to close the form. Locate the empty click event handler and enter code to call the form&#8217;s <code>Close()<\/code> method:<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\nprivate void btnOk_Click(object sender, EventArgs e)\r\n{\r\n    this.Close();\r\n}\r\n<\/pre>\n<p>Locate the empty <code>Load<\/code> event handler and add two statements to initialize the offset value controls to zero:<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\nprivate void frmStaggerOffset_Load(object sender, EventArgs e)\r\n{\r\n    \/\/ Set defaults for offsets\r\n    this.txtOffsetX.Text = \"0\";\r\n    this.txtOffsetY.Text = \"0\";\r\n}\r\n<\/pre>\n<p>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:<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\n\/\/ Overload the constructor to accept an argument\r\npublic frmStaggerOffset(string layerInfo)\r\n    : this()  \/\/ call the default constructor\r\n{\r\n    \/\/ Display the layer info on the form\r\n    this.labLayerInfo.Text = layerInfo;\r\n}\r\n<\/pre>\n<p>And finally, we need to validate the values entered for offsets in the <code>FormClosing<\/code> event handler:<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\nprivate void frmStaggerOffset_FormClosing(object sender,\r\n    FormClosingEventArgs e)\r\n{\r\n    if (this.DialogResult != DialogResult.OK)\r\n    {\r\n        \/\/ abort this method and skip validation\r\n        return;\r\n    }\r\n\r\n    try\r\n    {\r\n        offsetX = Convert.ToDouble(this.txtOffsetX.Text);\r\n        offsetY = Convert.ToDouble(this.txtOffsetY.Text);\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        MessageBox.Show(\"Please enter a valid number.\\n\\n\" +\r\n            ex.Message, \"Invalid Offset Value(s)\");\r\n        e.Cancel = true; \/\/ Prevents form from closing\r\n    }\r\n}\r\n<\/pre>\n<p><b>Video Demonstation:<\/b> <a href=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/video\/CS2008_AddinForm_Demo_pt9.swf.html\" target=\"_blank\">Finish coding form class, add test code to button, and test in ArcMap<\/a> (duration 1:10)<\/p>\n<h2>Test Setting and Getting Dialog Values<\/h2>\n<p>To test the new form, we will additional code to the Add-In Button&#8217;s <code>OnClick()<\/code> method.<\/p>\n<p>Select the <em>StaggerOffsetButton.cs <\/em>file in the code editor, locate the <code>OnClick()<\/code> method and replace its contents with the following code:<\/p>\n<pre lang=\"csharp\" line=\"0\">\r\nprotected override void OnClick()\r\n{\r\n    try\r\n    {\r\n      \/\/ Set the Layer Info\r\n      string layerInfo = \"Move xx features in:\\n\" + \"SomeFeatureClassName\";\r\n    \r\n      \/\/ Create the form\r\n      frmStaggerOffset staggerOffsetDialog = new frmStaggerOffset(layerInfo);\r\n     \r\n      \/\/ Display the form as a modal dialog\r\n      staggerOffsetDialog.ShowDialog();\r\n    \r\n      \/\/ Check if form was cancelled\r\n      if (staggerOffsetDialog.DialogResult != DialogResult.OK)\r\n      {\r\n          \/\/ abort\r\n          return;\r\n      }\r\n    \r\n      \/\/ Get the offset values from the form\r\n      double offsetX = staggerOffsetDialog.OffsetX;\r\n      double offsetY = staggerOffsetDialog.OffsetY;\r\n    \r\n      \/\/ Display the offset values for testing\r\n      MessageBox.Show(\"offsetX: \" + offsetX.ToString() +\r\n          \"\\noffsetY: \" + offsetY.ToString());\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        MessageBox.Show(ex.Message + \"\\n\\n\" + ex.StackTrace);\r\n    }\r\n}\r\n<\/pre>\n<p>Start debugging (press green arrow button or F5).<\/p>\n<p>Wait for ArcMap to load. Once it opens, open the provided <em>VBAtoCS_Tutorial_01_v10.mxd <\/em>map. Your toolbar and button should be where you placed on a tool panel.<\/p>\n<p>Click the Add-In&#8217;s button to display the new dialog form.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_06.png\" \/><\/p>\n<p>Notice the layer info label text has been fill with:<br \/>\nMove xx features in:<br \/>\nSomeFeatureClassName<\/p>\n<p>Enter various valid (numeric) values for the offsets and click the <em>OK<\/em> button to verify they are returned correctly from the dialog.<\/p>\n<p><img decoding=\"async\" src=\"\/\/gis.qtools.com\/tutorials\/vba_to_cs\/images\/CS2008_AddForm_07.png\" \/><\/p>\n<p>Try some invalid (non-numeric) values to verify error handling.<\/p>\n<p>Close ArcMap to return to Visual Studio and stop debugging.<\/p>\n<p>Now that the dialog form is functional, it is time to turn our attention to converting VBA ArcObjects code to C#.<\/p>\n<p><strong>Tutorial Navigation<\/strong> | Previous: <a href=\"..\/part-4-creating-new-add-in-project\/\">Part 4: Creating New Add-in Project<\/a> | Next: <a href=\"..\/part-6-converting-vba-arcobjects-to-cs\/\">Part 6: Converting VBA ArcObjects to CS<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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#. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":8,"menu_order":5,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-27","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/pages\/27","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":3,"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/pages\/27\/revisions"}],"predecessor-version":[{"id":87,"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/pages\/27\/revisions\/87"}],"up":[{"embeddable":true,"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/pages\/8"}],"wp:attachment":[{"href":"https:\/\/gis.qtools.com\/blog\/wp-json\/wp\/v2\/media?parent=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}