TownTalk
asked on
Passing a Form as an argument
I'm trying to duplicate an MsAccess app in C#. In the Access App I have dozens of forms which have some contols which are common to them all. For Instance, they all have a NewRecordButton. I want to call a global InsertNewRecord() function when the NewRecordButton is clicked. In MsAccess I pass the name of the form as an argument, but in C# I think I can pass a reference to the form. So in the form I have the code:
private void NewRecordButtonClick(objec t sender, EventArgs e)
{
MyFormClass.InsertNewRecor d(this);
}
And in my class which houses my global routines I have this:
public class MyFormClass
{
Public void InsertRecord(Form TheForm)
{
TheForm.NewRecordButton.En abled=Fals e;
}
}
This doesn't work. So what am I doing wrong?
private void NewRecordButtonClick(objec
{
MyFormClass.InsertNewRecor
}
And in my class which houses my global routines I have this:
public class MyFormClass
{
Public void InsertRecord(Form TheForm)
{
TheForm.NewRecordButton.En
}
}
This doesn't work. So what am I doing wrong?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you so much for the comprehensive replies!
I like the idea of using the base form. But nothing like this exists in vb, so I have to learn some new concepts here....
The first thing I found is that on Form1, the btnNewRecord is in a fixed location presumably because it is inherited from BaseForm. In my MsAccess app although I have dozens of forms each with 11 common buttons, the forms are different sizes/shapes according to the nature of the data in there. So I definitely need to move the buttons around and preferably resize them. Is there a workaround for this?
Edit: I found the answer to this. In the BaseForm I changed the Modifiers property to Protected.
I like the idea of using the base form. But nothing like this exists in vb, so I have to learn some new concepts here....
The first thing I found is that on Form1, the btnNewRecord is in a fixed location presumably because it is inherited from BaseForm. In my MsAccess app although I have dozens of forms each with 11 common buttons, the forms are different sizes/shapes according to the nature of the data in there. So I definitely need to move the buttons around and preferably resize them. Is there a workaround for this?
Edit: I found the answer to this. In the BaseForm I changed the Modifiers property to Protected.
ASKER
I've got your first example working now thank you.
I'm thinking a bit deeper into this now...... So yes the routines in BaseForm can reference all the common buttons, but what about the text boxes which are different on every form? In my MsAccess application the New Record Button creates a new record and places the Key Field value into a text box of the same name. For example, in the Customers screen the New Record Button causes a new record and customer code to be generated, then writes the new customer code into a text box called CustomerCode. I achieve this by supplying the tablename and keyfield name to the routine which inserts the new record.
I would like to write this code in the BaseForm.OnNewRecordClick and supply it with the relevent parameters. But if I am understanding this correctly, code executing within the BaseForm class will be unable to reference any entity on a form which is inheriting that class even if it knows the name of that entity.
In MS Access I can write: Forms![Form1]![CustomerCod e]= "ABC123"
Is that not possible in C#?
I'm thinking a bit deeper into this now...... So yes the routines in BaseForm can reference all the common buttons, but what about the text boxes which are different on every form? In my MsAccess application the New Record Button creates a new record and places the Key Field value into a text box of the same name. For example, in the Customers screen the New Record Button causes a new record and customer code to be generated, then writes the new customer code into a text box called CustomerCode. I achieve this by supplying the tablename and keyfield name to the routine which inserts the new record.
I would like to write this code in the BaseForm.OnNewRecordClick and supply it with the relevent parameters. But if I am understanding this correctly, code executing within the BaseForm class will be unable to reference any entity on a form which is inheriting that class even if it knows the name of that entity.
In MS Access I can write: Forms![Form1]![CustomerCod
Is that not possible in C#?
ASKER
I think I got it. I put this code in the BaseForm class......
Public Void WriteTextBox(String ControlName, String ControlValue)
{
this.Controls[ControlName] .Text = ControlValue;
}
It even works when called from the chld form.
Public Void WriteTextBox(String ControlName, String ControlValue)
{
this.Controls[ControlName]
}
It even works when called from the chld form.
To provide some clarification to you. When you instantiate the child class (in this case a form), all of the code in the base class (that the child has not overridden) *is* now a part of the child class.
Consider the following:
BaseForm.cs -
However, we cannot access textBox1 from the BaseForm because BaseForm knows nothing about textBox1.
For example:
-saige-
Consider the following:
BaseForm.cs -
using System;
using System.Windows.Forms;
namespace EE_Q28691014
{
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
}
protected virtual void OnNewRecordClick(object sender, EventArgs e)
{
btnNewRecord.Enabled = false;
}
protected virtual void WriteTextBox(Control Control, String Value)
{
Control.Text = Value;
}
}
}
BaseForm.Designer.cs -
namespace EE_Q28691014
{
partial class BaseForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnNewRecord = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnNewRecord
//
this.btnNewRecord.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnNewRecord.Location = new System.Drawing.Point(197, 227);
this.btnNewRecord.Name = "btnNewRecord";
this.btnNewRecord.Size = new System.Drawing.Size(75, 23);
this.btnNewRecord.TabIndex = 0;
this.btnNewRecord.Text = "New Record";
this.btnNewRecord.UseVisualStyleBackColor = true;
this.btnNewRecord.Click += new System.EventHandler(this.OnNewRecordClick);
//
// BaseForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.btnNewRecord);
this.Name = "BaseForm";
this.Text = "BaseForm";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnNewRecord;
}
}
Form1.cs -
using System;
using System.Windows.Forms;
namespace EE_Q28691014
{
public partial class Form1 : BaseForm
{
public Form1()
{
InitializeComponent();
}
protected override void OnNewRecordClick(object sender, EventArgs e)
{
base.OnNewRecordClick(sender, e);
WriteTextBox(textBox1, "Howdy TownTalk");
MessageBox.Show("We have disabled the new record button by using the click event in the parent (base).");
}
}
}
Form1.Designer.cs -
namespace EE_Q28691014
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(13, 13);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(178, 20);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 262);
this.Controls.Add(this.textBox1);
this.Name = "Form1";
this.Text = "Form1";
this.Controls.SetChildIndex(this.textBox1, 0);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox textBox1;
}
}
Produces the following output -This shows that the child form is actually calling the method. Since the child form does know about the textbox control, the method can be used to modify the control.However, we cannot access textBox1 from the BaseForm because BaseForm knows nothing about textBox1.
For example:
// Specify this in the BaseForm.cs. Invalid, will produce compiler errors.
protected virtual void WriteTextBox(string Value)
{
textBox1.Text = Value;
}
-saige-
ASKER
Thanks again for taking the time to do the above. I agree with everything except your final statement. The base form CAN write a value into a textbox on the child form. simplifying what I did just now.....
The Load event of Form1 has this line:
private void FormLoad(object sender, EventArgs e)
{
//KeyFieldName is declared in BaseClass
KeyFieldName = "DepartmentID";
}
And then in the BaseForm....
Public partial class BaseClass : Form
{
protected string KeyFieldname;
Public Void InsertRecord()
{
this.Controls[KeyFieldName ].Text = "Dept007"
}
}
Form1 contains a field called DepartmentID and the above Base Class code writes "Dept007" into it.
So i've got this doing everything I need. Thank you so much for your help.
The Load event of Form1 has this line:
private void FormLoad(object sender, EventArgs e)
{
//KeyFieldName is declared in BaseClass
KeyFieldName = "DepartmentID";
}
And then in the BaseForm....
Public partial class BaseClass : Form
{
protected string KeyFieldname;
Public Void InsertRecord()
{
this.Controls[KeyFieldName
}
}
Form1 contains a field called DepartmentID and the above Base Class code writes "Dept007" into it.
So i've got this doing everything I need. Thank you so much for your help.
Form1.cs -
Open in new window
Form1.Designer.cs -Open in new window
Extensions.cs -Open in new window
Program.cs -Open in new window
Produces the following output --saige-