How to create a common function for show form? - c#

I usually used the following code to show form:
frmEmployeeManage em = null;
private void ShowEmployee_Click(object sender, EventArgs e)
{
if (em == null || em.IsDisposed)
{
em = new frmEmployeeManage();
em.MdiParent = this;
em.FormBorderStyle = FormBorderStyle.None;
em.WindowState = FormWindowState.Maximized;
em.Show();
}
else
{
em.Activate();
}
}
Now I want to write a function for showing form. The following code I don't know how to pass a form class as parameter to the function.
class CommonService
{
public static void ShowFrom(Form frmChild, Form frmParent)
{
if (frmChild == null || frmParent.IsDisposed)
{
frmChild = new Form(); // How passing the form class here?
frmChild.MdiParent = frmParent;
frmChild.FormBorderStyle = FormBorderStyle.None;
frmChild.WindowState = FormWindowState.Maximized;
frmChild.Show();
}
else
{
frmParent.Activate();
}
}
}
Finally I use the show form function like the following example:
frmEmployeeManage em = null;
CommonService.ShowForm(frmEmployee, this);

I think what you need is to use a ref parameter:
public static void ShowFrom<T>(ref T frmChild, Form frmParent) where T : Form, new()
{
if (frmChild == null || frmParent.IsDisposed)
{
frmChild = new T(); // How passing the form class here?
frmChild.MdiParent = frmParent;
frmChild.FormBorderStyle = FormBorderStyle.None;
frmChild.WindowState = FormWindowState.Maximized;
frmChild.Show();
}
else
{
frmParent.Activate();
}
}
And call it like this:
frmEmployeeManage em = null;
CommonService.ShowForm(ref em, this);
ref allows you to change the value of the parameter in a method, and the changes are reflected on the variable passed in as well.

Related

How do I reference a variable from one class to another?

I'm new to C# and I can't figure out how to reference the value of a variable from one class to another.
It's set to when the button is pressed, it'll take the text in the text box and sets that as "alphaask". Then it instances "alphaanswer" which would tell the label to change its text.
"alphaanswer" will take the value "alphaQuest" and see if its equal to "bob" which then would change the label.
ALL I want to know how to set the value of "alphaQuest" from the value of "alphaask" so the string can check it with "alphaanswer"
public partial class QuestionTab : Form
{
public string alphaask = "null";
public void button1_Click(object sender, EventArgs e)
{
// alphabutton
// Checks if something is in textbox then says bool is true
bool asked = false;
if(textBoxAlpha.Text != "")
{
alphaask = textBoxAlpha.Text;
asked = true;
}
if(asked==true)
{
// If bool is true than instance auxy
var instance = new Alpha();
instance.alphaanswer();
}
}
}
public class Alpha
{
string alphaQuest = // <-- I want to make alphaQuest equal to alphaask
alphaanswer();
public void alphaanswer()
{
if (alphaanswer == bob)
{
//change text in label1
}
}
}
Do these changes
public partial class QuestionTab : Form
{
public string alphaask = "null";
public void button1_Click(object sender, EventArgs e)
{
bool asked = false;
if(textBoxAlpha.Text != "")
{
alphaask = textBoxAlpha.Text;
asked = true;
}
if(asked==true)
{
// If bool is true than instance auxy
var instance = new Alpha();
instance.alphaAnswer(alphaask);
//Here you are sending the current value of alphaAsk to the alphaanswer method.
}
}
}
public class Alpha
{
public void alphaAnswer(string alphaAnswer) //This string receives the value you sent
{
if (alphaAnswer == "bob")
{
//change text in label1
}
}
}
make a contractor in class Alpha with String parameter
public Alpha(String value)
{
}
then when you call it
var instance = new Alpha(alphaask);
instance.show();

Create and show a Form instance based on a boolean using Generic Method

I have these classes :
internal partial class FBase : Form
{
public FBase() { InitializeComponent(); }
public FBase(bool owner) : this()
{
if (!owner) { this.Opacity = 0; Load += (s, e) => Close(); }
}
}
internal partial class Form1 : FBase
{
public Form1(bool owner) : base(owner) { InitializeComponent(); }
}
This code works (does not show Form1):
Form1 f = new Form1(false);
if(f != null) { f.MdiParent = parent; f.Show(); }
But this does not work (shows Form1):
OpenSingleMdiChild(() => new Form1(false));
This is the implementation of OpenSingleMdiChild:
public static void OpenSingleMdiChild<T>(this Form parent, Func<T> factory) where T : Form
{
T f = null;
foreach (Form c in parent.MdiChildren) if (c.GetType() == typeof(T)) { f = c; break; }
if (f == null) { f = factory(); f.MdiParent = parent; }
f.Show(); f.Select();
}
If I understand your question, you want to know why Form1 isn't shown. I think your FBase Constructor is the reason:
public FBase(bool owner) : this()
{
if (!owner) { this.Opacity = 0; Load += (s, e) => Close(); }
}
There you tell the Load-Event to Close(); the Form. So it will directly be closed if owner is false. Further you should use some returns in your OpenSingleMdiChild-Method. Because this is really hard to read as #PeterBons points out.
Furthermore this code isn't very clear to me:
using (Form1 f = new Form1(false))
{
if(f != null) { f.MdiParent = parent; f.Show(); }
}
You show a Form and directly destroy it? Why should someone do this?
I hope it answers your questions. Else ask some real questions please ;).

PerformClick on custom button will not work

I have a custom class of a button and when I trigger PerformClick for any of my custom buttons, nothing happens. This is the code:
Declaration of my custom class
public class NonFocusButton : Button
{
public NonFocusButton()
{
SetStyle(ControlStyles.Selectable, false);
}
}
List<NonFocusButton> buttons = new List<NonFocusButton>();
This is the p function:
void p()
{
for (int i = 1; i <= 5; i++)
{
NonFocusButton aux = new NonFocusButton();
aux.Font = new System.Drawing.Font("Britannic Bold", 15.75F,
System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point,
((byte)(0)));
aux.Size = new System.Drawing.Size(192, 43);
aux.UseVisualStyleBackColor = true;
aux.UseWaitCursor = false;
aux.Visible = false;
buttons.Add(aux);
this.Controls.Add(aux);
}
// button start
buttons[0].Location = new System.Drawing.Point(410, 168);
buttons[0].Text = "START GAME";
buttons[0].Click += new System.EventHandler(this.button0_Click);
}
private void button0_Click(object sender, EventArgs e)
{
this.Close();
}
buttons[0].PerformClick(); // will not work
How are buttons declared and filled? This is how I have it, and it works.
// declaration
List<Button> butons = new List<Button>();
// calling
buttons.Add(new Button());
p();
buttons[0].PerformClick();
Edit:
The button has to get focus before it can be clicked.
Why not do something like:
button0_Click(buttons[0], EventArgs.Empty);
or just call Close() from wherever you are calling PerformClick().
The Button PerformClick source code is:
public void PerformClick() {
if (CanSelect) {
bool validatedControlAllowsFocusChange;
bool validate = ValidateActiveControl(out validatedControlAllowsFocusChange);
if (!ValidationCancelled && (validate || validatedControlAllowsFocusChange))
{
//Paint in raised state...
//
ResetFlagsandPaint();
OnClick(EventArgs.Empty);
}
}
}
And CanSelect:
public bool CanSelect {
// We implement this to allow only AxHost to override canSelectCore, but still
// expose the method publicly
//
get {
return CanSelectCore();
}
}
internal virtual bool CanSelectCore() {
if ((controlStyle & ControlStyles.Selectable) != ControlStyles.Selectable) {
return false;
}
for (Control ctl = this; ctl != null; ctl = ctl.parent) {
if (!ctl.Enabled || !ctl.Visible) {
return false;
}
}
return true;
}
My guess as to the restriction is the Selectable flag was used instead of adding another control flag such as AllowsPerformClick.
Instead of using PerformClick, you could use reflection, e.g.
MethodInfo methodOnClick = typeof(Button).GetMethod("OnClick", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
// and then...
methodOnClick.Invoke(myButton, new Object[] { EventArgs.Empty });

User input in subform

I am trying to get values back from a form.
I have been trying this: How to return a value from a Form in C#?
It does not work for me, maybe I'm doing something wrong but at the second part.
using (var form = new frmImportContact())
{
var result = form.ShowDialog();
if (result == DialogResult.OK)
{
string val = form.ReturnValue1; //ReturnValue1 is not an option...
string dateString = form.ReturnValue2;
//Do something here with these values
//for example
this.txtSomething.Text = val;
}
}
I am unable to get "ReturnValue1" to show up. It is declared public, what else do I need to do?
Here is what I have written. My sub-form:
namespace ASPE.GUI.SensorWizard
{
public partial class PortsSensitivity : Form
{
public int ReturnValue1 { get; set; }
public PortsSensitivity()
{
InitializeComponent();
}
private void PortsBox_ValueChanged(object sender, EventArgs e, KeyPressEventArgs m)
{
this.ReturnValue1 = Convert.ToInt16(PortsBox.Value);
}
private void PortsSensitivity_Load(object sender, EventArgs e)
{
}
}
}
And my main form:
//Show Form (Number of Ports, Sensitivity)
Form Part3 = new ASPE.GUI.SensorWizard.PortsSensitivity();
DialogResult dr3 = new DialogResult();
dr3 = Part3.ShowDialog();
//Write Variables
int numofports = Part3.ReturnValue1; //Not an option.
//Close Form
Your Part3 variable is defined as type Form which does not declare the ReturnValue1 property. (the ReturnValue1 property is declared on your PortSensitivity class).
Change
Form Part3 = new ASPE.GUI.SensorWizard.PortsSensitivity();
to
PortSensitivity Part3 = new ASPE.GUI.SensorWizard.PortsSensitivity();
Your first example is also instantiating something of type frmImportContact in the using statement but you have not shown the implementation of this. Check you have declared the property on this type (or that you aren't meant to be creating an instance of the PortSensitivity type).

How to avoid duplicate form creation in .NET Windows Forms?

I am using .NET Windows Forms. My MDI parent form contains the menu. If click the menu the form will be displayed. Up to now no problem.
UserForm uf = new UserForm();
uf.Show();
uf.MdiParent = this;
If I click the menu again another duplicate of the form is created. How to solve this issue?
The cleanest way is to simply track the lifetime of the form instance. Do so by subscribing the FormClosed event. For example:
private UserForm userFormInstance;
private void showUserForm_Click(object sender, EventArgs e) {
if (userFormInstance != null) {
userFormInstance.WindowState = FormWindowState.Normal;
userFormInstance.Focus();
}
else {
userFormInstance = new UserForm();
userFormInstance.MdiParent = this;
userFormInstance.FormClosed += (o, ea) => userFormInstance = null;
userFormInstance.Show();
}
}
You should create a singleton class for managing your form instances:
public class FormProvider
{
public static UserForm UserForm
{
get
{
if (_userForm== null || _userForm.IsDisposed)
{
_userForm= new UserForm ();
}
return _userForm;
}
}
private static UserForm _userForm;
}
NB, this is a very simple Singleton pattern. For the correct way to use the pattern, use this link.
You can then just access the form as follows:
FormProvider.UserForm.Show();
FormProvider.UserForm.MdiParent = this;
When FormProvider.UserForm is accessed for the FIRST time, it will be created. Any subsequent get on the FormProvider.UserForm property will return the form that was created on first access. This means that the form will only ever be created once.
In contrast to the existing answers here, I would not recommend using a Singleton for this. The Singleton pattern is woefully overused, and is generally a "code smell" that indicates that something's gone wrong with your overall design. Singletons are generally put in the same "bucket" as global variables: you'd better have a really strong case for using it.
The simplest solution is to make an instance variable on your main form that represents the form in question, then use that to show it.
public class MainMdiForm : Form
{
...
UserForm userForm;
...
private void ShowUserForm()
{
if(userForm == null || userForm.IsDisposed)
{
userForm = new UserForm();
userForm.MdiParent = this;
}
userForm.Show();
userForm.BringToFront();
}
}
If you know the name of the form :
if (Application.OpenForms["FormName"] == null)
{
Form form = new Form();
form.MdiParent = this;
form.Show();
}
else
Application.OpenForms["FormName"].Focus();
Options:
make UserForm a singleton: http://msdn.microsoft.com/en-us/library/ff650316.aspx
disable the button or menu item when it is clicked: menuItem.Enabled = false;
Typically, disabling the button works fine, and makes more sense from the user's perspective. Singleton works if you need the button enabled for something else.
Singleton is probably not a good solution if the form could be closed and a new instance will later be required.
You could always make the Form a Singleton:
public class MyForm : Form
{
private MyForm _instance = null;
private object _lock = new object();
private MyForm() { }
public static MyForm Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
_instance = new MyForm();
}
}
return _instance;
}
}
}
Then your call would look something like:
MyForm.Instance.Show();
MyForm.Instance.MdiParent = this;
You could just examine the MdiChildren property of your host form to determine if an instance of your UserForm exists in it.
UserForm myForm = null;
foreach (Form existingForm in this.MdiChildren)
{
myForm = existingForm as UserForm;
if (myForm != null)
break;
}
if (myForm == null)
{
myForm = new UserForm();
myForm.MdiParent = this;
myForm.Show();
}
else
myForm.Activate();
This will create a new instance of your UserForm is it doesn't already exist, and it will switch to the created instance if it does exist.
This is my solution in ShowForm() and calling sample in aboutToolStripMenuItem_Click():
private void ShowForm(Type typeofForm, string sCaption)
{
Form fOpen = GetOpenForm(typeofForm);
Form fNew = fOpen;
if (fNew == null)
fNew = (Form)CreateNewInstanceOfType(typeofForm);
else
if (fNew.IsDisposed)
fNew = (Form)CreateNewInstanceOfType(typeofForm);
if (fOpen == null)
{
fNew.Text = sCaption;
fNew.ControlBox = true;
fNew.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
fNew.MaximizeBox = false;
fNew.MinimizeBox = false;
// for MdiParent
//if (f1.MdiParent == null)
// f1.MdiParent = CProject.mFMain;
fNew.StartPosition = FormStartPosition.Manual;
fNew.Left = 0;
fNew.Top = 0;
ShowMsg("Ready");
}
fNew.Show();
fNew.Focus();
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
ShowForm(typeof(FAboutBox), "About");
}
private Form GetOpenForm(Type typeofForm)
{
FormCollection fc = Application.OpenForms;
foreach (Form f1 in fc)
if (f1.GetType() == typeofForm)
return f1;
return null;
}
private object CreateNewInstanceOfType(Type typeofAny)
{
return Activator.CreateInstance(typeofAny);
}
public void ShowMsg(string sMsg)
{
lblStatus.Text = sMsg;
if (lblStatus.ForeColor != SystemColors.ControlText)
lblStatus.ForeColor = SystemColors.ControlText;
}
public void ShowError(string sMsg)
{
lblStatus.Text = sMsg;
if (lblStatus.ForeColor != Color.Red)
lblStatus.ForeColor = Color.Red;
}

Categories

Resources