Theme:
v
APL+Win 13.2 ⎕CSE Tutorial (4)

In this example we will create a ⎕CSE script that creates a C# form on the fly and then we'll use this script from APL.

Note that it would be easy to create such a form in pure APL, but the purpose of this Tutorial is to teach how to do it using C#: in more complex situations where you need more sophisticated or nicer looking User Controls in your User Interface, your only chance would be to use C# and the new ⎕CSE.

Example 10: Create and use a C# Windows Form

Let's start with the following very simple function.

    ∇ InterestCalc;s;z;⎕cself
[1]
[2]   ⎕cself←'c'⎕cse'Init' 'System' 'System.Drawing' 'System.Windows.Forms'
[3]
[4]   s←''
[5]   s←s,⊂'using System.Drawing;'
[6]   s←s,⊂'using System.Windows.Forms;'
[7]   s←s,⊂'Form form1 = new Form();'
[8]   s←s,⊂'form1.Text = "Interest Calculator";'
[9]   s←s,⊂'form1.Size = new Size(400,300);'
[10]  s←s,⊂'form1.StartPosition = FormStartPosition.CenterScreen;'
[11]  s←s,⊂'form1.ShowDialog();'
[12]  s←⊃s
[13]
[14]  z←⎕cse'Exec's
[15]  :if z=¯1 ⋄ ⎕error⎕cse'GetLastError' ⋄ :endif
[16]
    ∇

If we run the InterestCalc function, we see the following C# form getting displayed, centered on our screen:

C# InterestCalc Form

Nice, but not very exciting yet. We need to add some controls to this form to make it useful. Let's start by adding a Label control and a TextBox control.

    ∇ InterestCalc2;s;z;⎕cself
[1]
[2]   ⎕cself←'c'⎕cse'Init' 'System' 'System.Drawing' 'System.Windows.Forms'
[3]
[4]   s←''
[5]   s←s,⊂'using System.Drawing;'
[6]   s←s,⊂'using System.Windows.Forms;'
[7]   s←s,⊂'Form form1 = new Form();'
[8]   s←s,⊂'form1.Text = "Interest Calculator";'
[9]   s←s,⊂'form1.Size = new Size(400,300);'
[10]  s←s,⊂'form1.StartPosition = FormStartPosition.CenterScreen;'
[11]
[12]  s←s,⊂'Label lPrincipal = new Label();'
[13]  s←s,⊂'lPrincipal.Text = "Principal:";'
[14]  s←s,⊂'lPrincipal.Location = new Point(5,8);'
[15]  s←s,⊂'lPrincipal.Size = new Size(80,13);'
[16]
[17]  s←s,⊂'TextBox txtPrincipal = new TextBox();'
[18]  s←s,⊂'txtPrincipal.Location = new Point(100,5);'
[19]  s←s,⊂'txtPrincipal.Size = new Size(150,21);'
[20]
[21]  s←s,⊂'form1.Controls.Add(lPrincipal);'
[22]  s←s,⊂'form1.Controls.Add(txtPrincipal);'
[23]  s←s,⊂'form1.ShowDialog();'
[24]  s←⊃s
[25]
[26]  z←⎕cse'Exec's
[27]  :if z=¯1 ⋄ ⎕error⎕cse'GetLastError' ⋄ :endif
    ∇

As you can see, we create a totally separate Label control on lines 12 to 15 and a TextBox control on lines 17 to 19.

If we did only that and tried our InterestCalc2 function it would display a Form identical to the previous one and we would not see our 2 controls. To make them children of the Form, we must add them to the Form Controls collection. This is what's done on lines 21 and 22.

Note that we define the position of the controls in the Form client area, using the Location property: this property must be set to an instance of a Point object which defines the coordinates in the Form client area of the top left corner of the Control. The Point .Net Framework class is part of the System.Drawing DLL, so we have added System.Drawing in the Init statement and have added a using System.Drawing; statement as well to avoid having to type System.Drawing.Point.

Similarly the size of the controls is defined using their Size property which is set to an instance of the Size object. Arguments are expressed in pixels.

Everything in C# is an object and once you get used to it, you will find it very natural and very easy to use the .Net Framework.

So now, if we run the InterestCalc2 APL function, we see the following C# form getting displayed centered on the screen:

C# InterestCalc Form

Now that we know how to add controls to a C# Form let's continue populating our Form to complete it.

    ∇ InterestCalc3;s;z;⎕cself
[1]
[2]   ⎕cself←'c'⎕cse'Init' 'System' 'System.Drawing' 'System.Windows.Forms'
[3]
[4]   s←''
[5]   s←s,⊂'using System.Drawing;'
[6]   s←s,⊂'using System.Windows.Forms;'
[7]   s←s,⊂'Form form1 = new Form();'
[8]   s←s,⊂'form1.Text = "Interest Calculator";'
[9]   s←s,⊂'form1.Size = new Size(400,300);'
[10]  s←s,⊂'form1.StartPosition = FormStartPosition.CenterScreen;'
[11]
[12]  s←s,⊂'Label lPrincipal = new Label();'
[13]  s←s,⊂'lPrincipal.Text = "Principal:";'
[14]  s←s,⊂'lPrincipal.Location = new Point(5,8);'
[15]  s←s,⊂'lPrincipal.Size = new Size(80,13);'
[16]
[17]  s←s,⊂'TextBox txtPrincipal = new TextBox();'
[18]  s←s,⊂'txtPrincipal.Location = new Point(100,5);'
[19]  s←s,⊂'txtPrincipal.Size = new Size(150,21);'
[20]
[21]  s←s,⊂'Label lInterest = new Label();'
[22]  s←s,⊂'lInterest.Text = "Interest:";'
[23]  s←s,⊂'lInterest.Location = new Point(5,34);'
[24]  s←s,⊂'lInterest.Size = new Size(80,13);'
[25]
[26]  s←s,⊂'TextBox txtInterest = new TextBox();'
[27]  s←s,⊂'txtInterest.Location = new Point(100,31);'
[28]  s←s,⊂'txtInterest.Size = new Size(150,21);'
[29]
[30]  s←s,⊂'Label lYears = new Label();'
[31]  s←s,⊂'lYears.Text = "Years:";'
[32]  s←s,⊂'lYears.Location = new Point(5,60);'
[33]  s←s,⊂'lYears.Size = new Size(80,13);'
[34]
[35]  s←s,⊂'NumericUpDown nudYears = new NumericUpDown();'
[36]  s←s,⊂'nudYears.Location = new Point(100,57);'
[37]  s←s,⊂'nudYears.Size = new Size(150,21);'
[38]  s←s,⊂'nudYears.Minimum = 5;'
[39]  s←s,⊂'nudYears.Maximum = 50;'
[40]
[41]  s←s,⊂'Label lBalance = new Label();'
[42]  s←s,⊂'lBalance.Text = "Yearly account balance:";'
[43]  s←s,⊂'lBalance.Location = new Point(5,90);'
[44]  s←s,⊂'lBalance.Size = new Size(150,13);'
[45]
[46]  s←s,⊂'TextBox txtBalance = new TextBox();'
[47]  s←s,⊂'txtBalance.Location = new Point(5,106);'
[48]  s←s,⊂'txtBalance.Size = new Size(374,150);'
[49]  s←s,⊂'txtBalance.Multiline = true;'
[50]  s←s,⊂'txtBalance.ReadOnly = true;'
[51]
[52]  s←s,⊂'Button btnCalc = new Button();'
[53]  s←s,⊂'btnCalc.Text = "Calculate";'
[54]  s←s,⊂'btnCalc.Location = new Point(289,4);'
[55]  s←s,⊂'btnCalc.Size = new Size(90,21);'
[56]
[57]  s←s,⊂'form1.Controls.Add(lPrincipal);'
[58]  s←s,⊂'form1.Controls.Add(txtPrincipal);'
[59]  s←s,⊂'form1.Controls.Add(lInterest);'
[60]  s←s,⊂'form1.Controls.Add(txtInterest);'
[61]  s←s,⊂'form1.Controls.Add(lYears);'
[62]  s←s,⊂'form1.Controls.Add(nudYears);'
[63]  s←s,⊂'form1.Controls.Add(lBalance);'
[64]  s←s,⊂'form1.Controls.Add(txtBalance);'
[65]  s←s,⊂'form1.Controls.Add(btnCalc);'
[66]  s←s,⊂'form1.ShowDialog();'
[67]  s←⊃s
[68]
[69]  z←⎕cse'Exec's
[70]  :if z=¯1 ⋄ ⎕error⎕cse'GetLastError' ⋄ :endif
[71]
    ∇
C# InterestCalc Form

Our Form user interface is now complete. If you click on the Calculate button, nothing happens yet, of course. So we need to learn how to handle events in C#.

Let's add a Click event handler to the btnCalc button:

Add the following code after line 55:

[56]   s←s,⊂'btnCalc.Click += btnCalc_Click;'
[57]
[58]   s←s,⊂'private void btnCalc_Click(object sender, EventArgs e)'
[59]   s←s,⊂'{'
[60]   s←s,⊂'      MessageBox.Show("Calculate button was clicked!");'
[61]   s←s,⊂'}'

Note that because we are using the EventArgs class, we also need to add a using System; statement at the top of the script.

Line 56 declares method btnCalc_Click as being the event handler for the Click event on button btnCalc.

Then lines 58 to 61 implement the btnCalc_Click event handler method.

In C# an event handler always has 2 arguments: the first one represents the object on which the event occurred so that one could retrieve this object in the event handler code and the second one is an instance of an object (here EventArgs) containing the possible arguments of the event (the EventArgs object is equivalent to ⎕warg in an APL event handler).

For now and to easily check that our event handler method is running ok, we just display a MessageBox when the btnCalc button is clicked.

C# InterestCalc Form

All what's left to be done now is to properly implement the btnCalc_Click event handler to calculate the year account balance and display the results in the bottom TextBox.

Here is how we can write the btnCalc_Click event handler in C#:

[57]  s←s,⊂'btnCalc.Click += btnCalc_Click;'
[58]
[59]  s←s,⊂'private void btnCalc_Click(object sender, EventArgs e)'
[60]  s←s,⊂'{'
[61]  s←s,⊂'      double balance;'
[62]  s←s,⊂'      double principal = Convert.ToDouble(txtPrincipal.Text);'
[63]  s←s,⊂'      double interest = Convert.ToDouble(txtInterest.Text);'
[64]  s←s,⊂'      int years = Convert.ToInt32(nudYears.Value);'
[65]  s←s,⊂'      string text = "Year\tBalance\r\n";'
[66]  s←s,⊂'      for (int i = 1; i <= years; i++)'
[67]  s←s,⊂'      {'
[68]  s←s,⊂'          balance = principal * Math.Pow((100+interest)/100, i);'
[69]  s←s,⊂'          text += string.Format("{0}\t{1:C}\r\n", i, balance);'
[70]  s←s,⊂'      }'
[71]  s←s,⊂'      txtBalance.Text = text;'
[72]  s←s,⊂'}'

Here are some comments:

  • on line 61 we declare a variable called balance as being a double (the equivalent of a floating point scalar in APL): in C#, we must declare the type of a variable before we can use it
  • on line 62 we retrieve the content of the txtPrincipal TextBox and convert it to a double
  • on line 63 we retrieve the content of the txtInterest TextBox and convert it to a double
  • on line 64 we retrieve the Value property of the nudYears NumericUpDown control and convert it to an int
  • on line 65 we declare a variable text as being a string and initialize it with a character string: note that the \t character is a Tab, that \r is a carriage return and \n a line feed. It is very nice and powerful to be able to include such escaped characters within C# strings!
  • lines 66 to 70 contain a for loop: in the body of this loop, delimited byb curly braces, we first calculate the yearly balance and then append the calculated result to the text string
  • note on line 69 the very powerful use of the string.Format method to format a character string the first argument describes the format to use and include placeholders ({0} and {1}) that are to be replaced by the values provided in the remaining arguments, {0} is replaced by the value of i and {1} is replaced by the value of balance. When using placeholders you can add formatting instructions, so in {1:C} the C means: format the value as a money value
  • finally, on line 71, the txtBalance TextBox is filled by setting its Text property to the text variable

What a beautiful and clean language C# (and the .Net Framework) is!

So let's now try our CSE script:

       InterestCalc5
C# InterestCalc Form

The final version of our InterestCalc APL function therefore is:

    ∇ InterestCalc5;s;z;⎕cself
[1]
[2]   ⎕cself←'c'⎕cse'Init' 'System' 'System.Drawing' 'System.Windows.Forms'
[3]
[4]   s←''
[5]   s←s,⊂'using System;'
[6]   s←s,⊂'using System.Drawing;'
[7]   s←s,⊂'using System.Windows.Forms;'
[8]   s←s,⊂'Form form1 = new Form();'
[9]   s←s,⊂'form1.Text = "Interest Calculator";'
[10]  s←s,⊂'form1.Size = new Size(400,300);'
[11]  s←s,⊂'form1.StartPosition = FormStartPosition.CenterScreen;'
[12]
[13]  s←s,⊂'Label lPrincipal = new Label();'
[14]  s←s,⊂'lPrincipal.Text = "Principal:";'
[15]  s←s,⊂'lPrincipal.Location = new Point(5,8);'
[16]  s←s,⊂'lPrincipal.Size = new Size(80,13);'
[17]
[18]  s←s,⊂'TextBox txtPrincipal = new TextBox();'
[19]  s←s,⊂'txtPrincipal.Location = new Point(100,5);'
[20]  s←s,⊂'txtPrincipal.Size = new Size(150,21);'
[21]
[22]  s←s,⊂'Label lInterest = new Label();'
[23]  s←s,⊂'lInterest.Text = "Interest:";'
[24]  s←s,⊂'lInterest.Location = new Point(5,34);'
[25]  s←s,⊂'lInterest.Size = new Size(80,13);'
[26]
[27]  s←s,⊂'TextBox txtInterest = new TextBox();'
[28]  s←s,⊂'txtInterest.Location = new Point(100,31);'
[29]  s←s,⊂'txtInterest.Size = new Size(150,21);'
[30]
[31]  s←s,⊂'Label lYears = new Label();'
[32]  s←s,⊂'lYears.Text = "Years:";'
[33]  s←s,⊂'lYears.Location = new Point(5,60);'
[34]  s←s,⊂'lYears.Size = new Size(80,13);'
[35]
[36]  s←s,⊂'NumericUpDown nudYears = new NumericUpDown();'
[37]  s←s,⊂'nudYears.Location = new Point(100,57);'
[38]  s←s,⊂'nudYears.Size = new Size(150,21);'
[39]  s←s,⊂'nudYears.Minimum = 5;'
[40]  s←s,⊂'nudYears.Maximum = 50;'
[41]
[42]  s←s,⊂'Label lBalance = new Label();'
[43]  s←s,⊂'lBalance.Text = "Yearly account balance:";'
[44]  s←s,⊂'lBalance.Location = new Point(5,90);'
[45]  s←s,⊂'lBalance.Size = new Size(150,13);'
[46]
[47]  s←s,⊂'TextBox txtBalance = new TextBox();'
[48]  s←s,⊂'txtBalance.Location = new Point(5,106);'
[49]  s←s,⊂'txtBalance.Size = new Size(374,150);'
[50]  s←s,⊂'txtBalance.Multiline = true;'
[51]  s←s,⊂'txtBalance.ReadOnly = true;'
[52]
[53]  s←s,⊂'Button btnCalc = new Button();'
[54]  s←s,⊂'btnCalc.Text = "Calculate";'
[55]  s←s,⊂'btnCalc.Location = new Point(289,4);'
[56]  s←s,⊂'btnCalc.Size = new Size(90,21);'
[57]  s←s,⊂'btnCalc.Click += btnCalc_Click;'
[58]
[59]  s←s,⊂'private void btnCalc_Click(object sender, EventArgs e)'
[60]  s←s,⊂'{'
[61]  s←s,⊂'      double balance;'
[62]  s←s,⊂'      double principal = Convert.ToDouble(txtPrincipal.Text);'
[63]  s←s,⊂'      double interest = Convert.ToDouble(txtInterest.Text);'
[64]  s←s,⊂'      int years = Convert.ToInt32(nudYears.Value);'
[65]  s←s,⊂'      string text = "Year\tBalance\r\n";'
[66]  s←s,⊂'      for (int i = 1; i <= years; i++)'
[67]  s←s,⊂'      {'
[68]  s←s,⊂'          balance = principal * Math.Pow((100+interest)/100, i);'
[69]  s←s,⊂'          text += string.Format("{0}\t{1:C}\r\n", i, balance);'
[70]  s←s,⊂'      }'
[71]  s←s,⊂'      txtBalance.Text = text;'
[72]  s←s,⊂'}'
[73]
[74]  s←s,⊂'form1.Controls.Add(lPrincipal);'
[75]  s←s,⊂'form1.Controls.Add(txtPrincipal);'
[76]  s←s,⊂'form1.Controls.Add(lInterest);'
[77]  s←s,⊂'form1.Controls.Add(txtInterest);'
[78]  s←s,⊂'form1.Controls.Add(lYears);'
[79]  s←s,⊂'form1.Controls.Add(nudYears);'
[80]  s←s,⊂'form1.Controls.Add(lBalance);'
[81]  s←s,⊂'form1.Controls.Add(txtBalance);'
[82]  s←s,⊂'form1.Controls.Add(btnCalc);'
[83]  s←s,⊂'form1.ShowDialog();'
[84]  s←⊃s
[85]
[86]  z←⎕cse'Exec's
[87]  :if z=¯1 ⋄ ⎕error⎕cse'GetLastError' ⋄ :endif
    ∇

So, in 87 lines of APL code, we've created a script which creates and displays a complete and useful C# Form that we can use in any APL application.

Note, as mentioned in earlier examples, that the recommended way is to rather develop the C# Form using Visual Studio 2012 and make it a DLL. Then you can load this DLL using ⎕CSE, create an isntance of the Form contained in the DLL and then call its ShowDialog method to display and use it in your APL application. Taking this approach will be our next example.

Example 11: Using an APL event handler

You may ask yourself if it is possible to handle the Click event on the btnCalc button in APL rather than in C#

It is possible and one way to do it is as follows:

    ∇ InterestCalc6;s;z;⎕cself
[1]
[2]   ⎕cself←'c'⎕cse'Init' 'System' 'System.Drawing' 'System.Windows.Forms'
[3]
[4]   s←''
[5]   s←s,⊂'using System;'
[6]   s←s,⊂'using System.Drawing;'
[7]   s←s,⊂'using System.Windows.Forms;'
[8]   s←s,⊂'Form form1 = new Form();'
[9]   s←s,⊂'form1.Text = "Interest Calculator";'
[10]  s←s,⊂'form1.Size = new Size(400,300);'
[11]  s←s,⊂'form1.StartPosition = FormStartPosition.CenterScreen;'
[12]
[13]  s←s,⊂'Label lPrincipal = new Label();'
[14]  s←s,⊂'lPrincipal.Text = "Principal:";'
[15]  s←s,⊂'lPrincipal.Location = new Point(5,8);'
[16]  s←s,⊂'lPrincipal.Size = new Size(80,13);'
[17]
[18]  s←s,⊂'TextBox txtPrincipal = new TextBox();'
[19]  s←s,⊂'txtPrincipal.Location = new Point(100,5);'
[20]  s←s,⊂'txtPrincipal.Size = new Size(150,21);'
[21]
[22]  s←s,⊂'Label lInterest = new Label();'
[23]  s←s,⊂'lInterest.Text = "Interest:";'
[24]  s←s,⊂'lInterest.Location = new Point(5,34);'
[25]  s←s,⊂'lInterest.Size = new Size(80,13);'
[26]
[27]  s←s,⊂'TextBox txtInterest = new TextBox();'
[28]  s←s,⊂'txtInterest.Location = new Point(100,31);'
[29]  s←s,⊂'txtInterest.Size = new Size(150,21);'
[30]
[31]  s←s,⊂'Label lYears = new Label();'
[32]  s←s,⊂'lYears.Text = "Years:";'
[33]  s←s,⊂'lYears.Location = new Point(5,60);'
[34]  s←s,⊂'lYears.Size = new Size(80,13);'
[35]
[36]  s←s,⊂'NumericUpDown nudYears = new NumericUpDown();'
[37]  s←s,⊂'nudYears.Location = new Point(100,57);'
[38]  s←s,⊂'nudYears.Size = new Size(150,21);'
[39]  s←s,⊂'nudYears.Minimum = 5;'
[40]  s←s,⊂'nudYears.Maximum = 50;'
[41]
[42]  s←s,⊂'Label lBalance = new Label();'
[43]  s←s,⊂'lBalance.Text = "Yearly account balance:";'
[44]  s←s,⊂'lBalance.Location = new Point(5,90);'
[45]  s←s,⊂'lBalance.Size = new Size(150,13);'
[46]
[47]  s←s,⊂'TextBox txtBalance = new TextBox();'
[48]  s←s,⊂'txtBalance.Location = new Point(5,106);'
[49]  s←s,⊂'txtBalance.Size = new Size(374,150);'
[50]  s←s,⊂'txtBalance.Multiline = true;'
[51]  s←s,⊂'txtBalance.ReadOnly = true;'
[52]
[53]  s←s,⊂'Button btnCalc = new Button();'
[54]  s←s,⊂'btnCalc.Text = "Calculate";'
[55]  s←s,⊂'btnCalc.Location = new Point(289,4);'
[56]  s←s,⊂'btnCalc.Size = new Size(90,21);'
[57]
[58]  ⍝ s←s,⊂'btnCalc.Click += btnCalc_Click;'
[59]  s←s,⊂'APL: 0 0⍴⎕cse"AddEventHandler" "btnCalc" "Click" "btnCalc_Click" "sink"'
[60]
[61]  ⍝ s←s,⊂'private void btnCalc_Click(object sender, EventArgs e)'
[62]  ⍝ s←s,⊂'{'
[63]  ⍝ s←s,⊂'      double balance;'
[64]  ⍝ s←s,⊂'      double principal = Convert.ToDouble(txtPrincipal.Text);'
[65]  ⍝ s←s,⊂'      double interest = Convert.ToDouble(txtInterest.Text);'
[66]  ⍝ s←s,⊂'      int years = Convert.ToInt32(nudYears.Value);'
[67]  ⍝ s←s,⊂'      string text = "Year\tBalance\r\n";'
[68]  ⍝ s←s,⊂'      for (int i = 1; i <= years; i++)'
[69]  ⍝ s←s,⊂'      {'
[70]  ⍝ s←s,⊂'          balance = principal * Math.Pow((100+interest)/100, i);'
[71]  ⍝ s←s,⊂'          text += string.Format("{0}\t{1:C}\r\n", i, balance);'
[72]  ⍝ s←s,⊂'      }'
[73]  ⍝ s←s,⊂'      txtBalance.Text = text;'
[74]  ⍝ s←s,⊂'}'
[75]
[76]  s←s,⊂'public double Principal { get { return Convert.ToDouble(txtPrincipal.Text); } }'
[77]  s←s,⊂'public double Interest { get { return Convert.ToDouble(txtInterest.Text); } }'
[78]  s←s,⊂'public int Years { get { return Convert.ToInt32(nudYears.Value); } }'
[79]  s←s,⊂'public string Balance { get { return txtBalance.Text; } set { txtBalance.Text = value; } }'
[80]
[81]  s←s,⊂'form1.Controls.Add(lPrincipal);'
[82]  s←s,⊂'form1.Controls.Add(txtPrincipal);'
[83]  s←s,⊂'form1.Controls.Add(lInterest);'
[84]  s←s,⊂'form1.Controls.Add(txtInterest);'
[85]  s←s,⊂'form1.Controls.Add(lYears);'
[86]  s←s,⊂'form1.Controls.Add(nudYears);'
[87]  s←s,⊂'form1.Controls.Add(lBalance);'
[88]  s←s,⊂'form1.Controls.Add(txtBalance);'
[89]  s←s,⊂'form1.Controls.Add(btnCalc);'
[90]  s←s,⊂'form1.ShowDialog();'
[91]  s←⊃s
[92]
[93]  z←⎕cse'Exec's
[94]  :if z=¯1 ⋄ ⎕error⎕cse'GetLastError' ⋄ :endif
[95]
    ∇

Note that line 58 has been commented as well as lines 61 to 74, so we are no longer using a C# event handler.

Instead, on line 59 we are using the APL: prefix on this script line to tell the CSE System that control should be temporarily sent back to APL when this script runs to have APL+Win execute this line of code. This is powerful and allows us to define an event handler for the Click event on the btnCalc button, in APL.

The 1st argument is the object on which the event occurs

The 2nd argument is the C# event name that is being handled

The 3rd argument is the name of the monadic APL callback function to be run when the button is clicked

The last argument is a non empty character string that could contain some data sent by C# to the APL callback function

Our APL btnCalc_Click callback function will need to retrieve the content of the InterestCalc form controls (the Principal value, the Interest value, the Years value) in order to calculate the Balances.

Here is a very important information to learn and remember: in C# you should NEVER try to access a control directly from outside your Form code. Instead the way to do this is through public properties you define in your Form.

So we have added 4 properties on lines 76 to 79 to be able to access the controls on the form and read or write their values. The first 3 properties are read-only properties (they only have a get) and the last one is a read-write property (it has a get and a set).

Now we can write the btnCalc_Click event handler as follows:

    ∇ btnCalc_Click arg;a;b;c;d;e;f;z;principal;interest;years;balance;text
[1]   ⍝∇ APL event handler for the btnCalc button Click event
[2]
[3]   principal←⎕cse'GetValue' 'Principal'
[4]   interest←⎕cse'GetValue' 'Interest'
[5]   years←⎕cse'GetValue' 'Years'
[6]
[7]   balance←principal×(0.01×100+interest)*⍳years
[8]
[9]   text←'Year',⎕tcht,'Balance',⎕tcnl,⎕tclf
[10]  text,←,('I2,<',⎕tcht,'>,M<$>CF12.2,<',⎕tcnl,⎕tclf,'>')⎕fmt(⍳years; balance)
[11]
[12]  z←⎕cse'SetValue' 'Balance'(text~' ')
[13]
    ∇

You can compare this event handler to the C# btnCalc_Click event handler and I am sure you all understand the APL version shown above.

If we run the application, we get the exact same behaviour:

       InterestCalc6
C# InterestCalc Form

 

CSE Tutorial (1)...
CSE Tutorial (2)...
CSE Tutorial (3)...
CSE Tutorial (5)...