Working with win forms - c#

I have 2 win forms..Form A and B, form B is let's say child and A is parent...
Form B is sending some data to A, but i have duplicate process with form A when i close form B...a second form A opens up...
This is the code that I put in form B...but the problem is that the value from form B is not "going" to form A...with this code only form A opens up, there is no duplicate process and B closes up, but no data comes from B to A...
This is the code:
private void button1_Click(object sender, EventArgs e)
{
//Index of the row which is currently selected.
int myIndex = dataGridView1.CurrentRow.Index;
DataGridViewRow row = this.dataGridView1.Rows[myIndex];
brdok = row.Cells["Broj_dokumenta"].Value.ToString();
FormCollection fc = Application.OpenForms;
bool FormFound = false;
foreach (Form frm in fc)
{
if (frm.Name == "Main")
{
//Open form A
Main f = new Main();
f.textRadniNalog.AppendText(brdok);
f.Focus();
FormFound = true;
}
}
if (FormFound == false)
{
Main f = new Main();
f.Show();
}
//close form B
this.Close();
}

The other answer explains how you can keep your current basic architecture, except without the specific bug. That said, Marko's comment is a better answer. Here's what that would look like:
partial class Main : Form
{
private void button1_Click(object sender, EventArgs e)
{
// Add whatever other initialization is needed here, of course
new FormB(this).Show();
}
}
partial class FormB : Form
{
private Main _main;
public FormB(Main main)
{
_main = main;
}
private void button1_Click(object sender, EventArgs e)
{
//Index of the row which is currently selected.
int myIndex = dataGridView1.CurrentRow.Index;
DataGridViewRow row = this.dataGridView1.Rows[myIndex];
brdok = row.Cells["Broj_dokumenta"].Value.ToString();
_main.textRadniNalog.AppendText(brdok);
_main.Focus();
//close form B
this.Close();
}
}
If it's actually possible for the Main form to be closed while FormB is open (something you can prevent by showing FormB using the ShowDialog() method instead of the Show() method), then you can add logic to account for that:
partial class FormB : Form
{
private Main _main;
public FormB(Main main)
{
_main = main;
if (_main != null)
{
_main.FormClosed += (sender, e) => _main = null;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (_main != null)
{
//Index of the row which is currently selected.
int myIndex = dataGridView1.CurrentRow.Index;
DataGridViewRow row = this.dataGridView1.Rows[myIndex];
brdok = row.Cells["Broj_dokumenta"].Value.ToString();
_main.textRadniNalog.AppendText(brdok);
_main.Focus();
}
else
{
new Main().Show();
}
//close form B
this.Close();
}
}
If needed, you can similarly handle the scenario where the Main form could be opened after FormB is shown; the code that does that would of course need to know about the FormB instance, and would pass the new Main form instance reference to it when it shows the form. In that case — where forms rely on each other but come and go on some arbitrary mechanism — it would be best, rather than having each individual form have to know what other form(s) have to react to them, for you to have some top-level controller object that deals with all of the interactions, including being the go-between for events and state changes in different windows.

looks like you are creating a new instance even when the form is found
if (frm.Name == "Main")
{
//Open form A
Main f = new Main();
please try changing it to
if (frm is Main)
{
Main f = frm as Main;
f.textRadniNalog.AppendText(brdok);
f.Focus();
or
var mainFrm=fc.OfType<Main>().FirstOrDefault();
if (mainFrm != null)
{
mainFrm.textRadniNalog.AppendText(brdok);
mainFrm.Focus();
}
else
{
Main f = new Main();
f.Show();
}

Related

open every Window form as child to MdiParent

I'm having MdiParent form which has Menu and Submenu
Parent Form is Say Form A if I open Form B using submenu option using following code
B addbill = new B();
B.Show();
B.MdiParent = this;
It opens Form B as child of Form A. Now I want to open Form C from Form B after click the Button on Form B and Form B will be closed and Form C will be opened as Child of Form A
Again after click button on Form C , Form C Will be closed and Form B will be opened as Form A
So what can I do to do same ?
On FormB button click event write this code:
FormC fc=new FormC();
fc.MdiParent=this.MdiParent;
fc.Show();
And in FormC load event write this code:
FormB fb=new FormB();
fb.Hide();
fb.Close();
before B is closed:
C.MdiParent = B.MdiParent; // which is pointing to A
In Form B button click where you are calling Form C, you have to assign the MdiParent of FormB to MdiParent of FormC which is FormA. After that you can close FormB.
//FormB Button Click
private void button1_Click(object sender, EventArgs e)
{
FormC frm = new FormC();
frm.MdiParent = this.MdiParent; // assign MdiParent of FormB to FormC
frm.Show();
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
Analysis an = new Analysis();//on login click open anothe form on same perrent
an.MdiParent = this.MdiParent;
an.Show();
}
It's Work..Try This Code
private void btCountSale_Click(object sender, EventArgs e)
{
bool exist = false;
foreach (Form f in Application.OpenForms)
{
if (f.Text == "Counter Sale")
{
exist = true;
f.BringToFront();
break;
}
}
if (exist == false)
{
frmCounterSale fm = new frmCounterSale();
fm.MdiParent = this.MdiParent;
fm.Show();
}
}
It's Work..Try This Code
private void btCountSale_Click(object sender, EventArgs e)
{
bool exist = false;
foreach (Form f in Application.OpenForms)
{
if (f.Name== "frmCounterSale")
{
exist = true;
f.BringToFront();
break;
}
}
if (exist == false)
{
frmCounterSale fm = new frmCounterSale();
fm.MdiParent = this.MdiParent;
fm.Show();
}
}

user's impatient multiple clicks on menuitem loads MDI child form multiple times

Some forms I want to be loaded only once by the MDI Parent. So, in the click event of the menuitem, I look to see if the MDI parent's .Children property already contains the form and the form is loaded only if it is not already among the children:
bool alreadyLoaded = false;
if (this.MdiChildren.Length > 0)
{
foreach (Form frm in this.MdiChildren)
{
if (frm.Name == "foo")
{
alreadyLoaded=true;
break;
}
}
}
if (! alreadyLoaded)
{
FOO f = new FOO();
f.MdiParent=this;
f.Show();
}
But if the impatient user clicks rapidly on the menu item the very first time the form is loaded, it can be loaded more than once. The second and third clicks on the menu item launch a new copy of the form before the instance loaded by the first click is fully instantiated.
I suppose I could maintain my own list of launched form names and, in the menuitem's click eventhandler, add the form's name to the list if it isn't already there, and later remove it from the list in the child form's Closed eventhandler. But is there a better way?
Try out this class:
/// <summary>
/// Displays form in mdi form once
/// </summary>
/// <autor>Saber Amani</autor>
/// <lastUpdate>2009-03-03</lastUpdate>
public class MdiFormDisplayer
{
private Hashtable fForms = new Hashtable();
private object fSender = null;
public MdiFormDisplayer(object sender)
{
fSender = sender;
}
public Form GetForm(Type formType)
{
string formName = formType.Name;
Form frm = (Form)fForms[formName];
if (frm == null || frm.IsDisposed)
{
frm = CreateNewInstance(formType);
fForms[formName] = frm;
}
return frm;
}
public Form GetForm(string formName)
{
if (fSender == null)
throw new ArgumentNullException("Sender", "Sender can't be null");
return GetForm(fSender, formName);
}
public Form GetForm(object sender, string formName)
{
Form frm = (Form)fForms[formName];
if (frm == null || frm.IsDisposed)
{
frm = CreateNewInstance(sender, formName);
fForms[formName] = frm;
}
return frm;
}
private Form CreateNewInstance(object sender, string formName)
{
Type frmType;
frmType = FindFormType(sender, formName);
Form frmInstance = (Form)CallTypeConstructor(frmType);
return frmInstance;
}
private Form CreateNewInstance(Type frmType)
{
Form frmInstance = (Form)CallTypeConstructor(frmType);
return frmInstance;
}
private Type FindFormType(object sender, string formName)
{
Type baseType = sender.GetType();
Assembly senderAssembly = Assembly.GetAssembly(baseType);
Type result = null;
// Search with assembly standard method
result = senderAssembly.GetType(baseType.Namespace + "." + formName);
if (result != null)
return result;
// Search with in the types
Type[] assemblyTypes = senderAssembly.GetTypes();
formName = formName.ToLower();
for (int i = 0; i < assemblyTypes.Length; i++)
{
if (assemblyTypes[i].Name.ToLower() == formName)
return assemblyTypes[i];
}
return null;
}
private object CallTypeConstructor(Type frmType)
{
Type[] contructTypes = new Type[] { };
ConstructorInfo constructorObj = frmType.GetConstructor(contructTypes);
object result = constructorObj.Invoke(null);
return result;
}
}
use like this :
public partial class frmMainForm : Form
{
MdiFormDisplayer forms;
public frmMainForm()
{
InitializeComponent();
forms = new MdiFormDisplayer(this);
}
private void btnCompany_Click(object sender, EventArgs e)
{
Form frm = forms.GetForm(typeof(frmCompany));
frm.MdiParent = this;
frm.Show();
frm.Focus();
}
}
Hope this help.
a simple flag that you set when the menu handler is called - called something like "processingClick". If this flag is already set, just quit the handler. Remember to reset it to false at the end of the routine.
Alternatively you could put a big critical section around the contents of the menu handler - so if its click twice in rapid succession, the 2nd click will wait for the 1st one to be handled. That guarantees that your 1st click gets to do all its processing.
you could disable the menu item on first click directly before instatiating the respective form... and on closing the form you could reenable the menu item... this way the user can't do what you describe...

how to prevent opening a form multiple times in c#

i have created an application in which a menustrip is present in which 2 buttons are there, one for ADD, and another for UPDATE & both controls are in a single form, means a button of add & update is there in a single form, whenever i press add button in menustrip update button will be disabled, and when i press update on menustrip the add button will disable. how to do this? i m doing this by show method but that form is opening multiple times using show().
private void addRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
Form1 f2 = new Form1();
f2.MdiParent = this;
f2.Show();
f2.button1.Enabled = true;
}
private void updateRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
Form1 f2 = new Form1();
f2.MdiParent = this;
f2.Show();
f2.button2.Enabled = true;
f2.button1.Enabled = false;
}
you simply have to use a single form in this case. try using the singleton approach -
http://hashfactor.wordpress.com/2009/03/31/c-winforms-create-a-single-instance-form/
try using .ShowDialog() instead .Show() and no other form will be able to be clicked on until that one closes.
To do that you'll need to have an instance of that Form outside of those methods that you dismply show if the Form has already been created, or create and show it if it has not (this is the singleton pattern). Here's an example:
Form1 f2 = null;
private void addRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (f2 == null)
{
f2 = new Form1();
f2.MdiParent = this;
f2.button1.Enabled = true;
}
f2.Show();
}
private void updateRecordsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (f2 == null)
{
f2.MdiParent = this;
f2.button2.Enabled = true;
f2.button1.Enabled = false;
}
f2.Show();
}
One question on your disabling of the menu items though, how do you plan on re-enabling them after they have been disabled?
just try to check that form is already opened or not by using its Text Property.. if it is opened just focus on that form other wise show that form as normally
private void button1_Click(object sender, EventArgs e)
{
bool IsOpen = false;
foreach (Form f in Application.OpenForms)
{
if (f.Text == "Form1")
{
IsOpen = true;
f.Focus();
break;
}
}
if (IsOpen == false)
{
Form f1 = new Form1();
f1.Show();
}
}
Try This Guys Its Simple

How to close MDIChild C# VS2010?

Actually Its my first project. While I want to convert my VB.Net2008 to C#2010 I have few clarification pls.
In Form2 Properties I set - IsMDIContainer = True. Then the below code to open my MdiChild and now what is my problem when I click the close button, it's also closing the MDIParent. But I need to close only mdichild... for that I tried as like Vb.Net2008 style by the following codes placed in MDIParent Form2, Its not working. Any right directions ...
private void toolStripButton1_Click(object sender, EventArgs e)
{
Form3 NwMdiChild2 = new Form3;
NwMdiChild2.MdiParent = this;
NwMdiChild2.Dock = System.Windows.Forms.DockStyle.Fill;
NwMdiChild2.Show();
}
private void Form2_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
Form[] MdiChildForms = this.MdiChildren;
int kkk1 = MdiChildForms.Length;
int x = 0;
for (x = 0; x <= MdiChildForms.Length - 1; x += 1)
{
if (MdiChildForms[x].Name == "Form1")
{
kkk1 = kkk1 - 1;
}
MdiChildForms[x].Close();
}
if (kkk1 > 0)
{
// For Not Closing
e.Cancel = true;
}
else
{
// For Closing
e.Cancel = false;
Application.Exit();
}
}
Any Right Directions for Me?
I'm not sure if I understand well what you want to achieve: do you want, when click Parent Form close button, insteed of closing parent form, to close all the child's form? Form2 is your main form (parent MDI container), Form3 is the MDI children, isn't it?
Please try following code and tell if it's what you are asking for:
private void toolStripButton1_Click(object sender, EventArgs e)
{
Form3 NwMdiChild2 = new Form3(); //don't forget ()
NwMdiChild2.MdiParent = this;
NwMdiChild2.Dock = System.Windows.Forms.DockStyle.Fill;
NwMdiChild2.Show();
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
//if no MDI child - this is going to be skipped and norlmal Form2 close takes place
if (this.MdiChildren.Length > 0) //close childrens only when there are some
{
foreach (Form childForm in this.MdiChildren)
childForm.Close();
e.Cancel = true; //cancel Form2 closing
}
}

Find, Find Next?

I am trying to make a find, find next function for my program, which I did manage to do with this code:
int findPos = 0;
private void button1_Click(object sender, EventArgs e)
{
try
{
string s = textBox1.Text;
richTextBox1.Focus();
findPos = richTextBox1.Find(s, findPos, RichTextBoxFinds.None);
richTextBox1.Select(findPos, s.Length);
findPos += textBox1.Text.Length;
//i = richTextBox1.Find(s, i + s.Length, RichTextBoxFinds.None);
}
catch
{
MessageBox.Show("No Occurences Found");
findPos = 0;
}
}
And it works great in form1 but if I use this code and try to call it from form2 It doesn't do anything:
//Form1
public void FindNext()
{
try
{
this.Focus();
Form2 frm2 = new Form2();
string s = frm2.textBox1.Text;
richTextBox1.Focus();
findPos = richTextBox1.Find(s, findPos, RichTextBoxFinds.None);
richTextBox1.Select(findPos + 1, s.Length);
findPos += textBox1.Text.Length;
}
catch
{
MessageBox.Show("No Occurences Found");
findPos = 0;
}
}
//Form2
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
frm1.FindNext();
}
Does any one know why this is?
Thanks,Tanner.
string s = Interaction.InputBox("enter search text", "Notepad-search", "", 100, 100);
//The above syntax is from vb.net so add reference as microsoft.VisualBasic from references. The above code creates an alertbox. Then type the text which you want search and click on ok.
int f = richTextBox1.Find(s);
if (f >= 0)
{
MessageBox.Show("search Text is found");
}
else
{
MessageBox.Show("search Text is not found");
}
I think you may be confused in how you reference Form1 and Form2 from each other.
Calling new Form() and new Form2() create references to new instances of Form1 and Form2, they don't reference the forms that are already open. You need to get the references for the existing instances.
Assuming that Form1 is the main form for your application and it creates and shows Form2, you can either add a property to Form2 that represents the instance of Form1 that created it, or you can appropriate the Owner property for this purpose (I'd recommend that).
In your code on Form1 that shows Form2 initially (not in the code you have above), call frm2.Show(this) instead of just frm2.Show(). This will set the Owner property of your Form2 instance equal to thinstance of Form1 that opened it.
Then change your button code for Form2 to this:
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = (Form1)Owner;
frm1.FindNext();
}
This will make you reference the existing form rather than a new one, which is what you want.
As far as the FindNext function goes, you have two choices: either you can hold on to the reference of Form2 (though you probably want to do this anyway) and access the text directly, or you can change FindNext to take a string (this is what I'd recommend).
public void FindNext(string searchText)
{
try
{
this.Focus();
richTextBox1.Focus();
findPos = richTextBox1.Find(searchText, findPos, RichTextBoxFinds.None);
richTextBox1.Select(findPos + 1, searchText.Length);
findPos += searchText.Length;
}
catch
{
MessageBox.Show("No Occurences Found");
findPos = 0;
}
}
Then change the call to frm1.FindNext() on Form2 to frm1.FindNext(textBox1.Text):
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = (Form1)Owner;
frm1.FindNext(textBox1.Text);
}
Looks like you are referencing two different instances of Form2.
In your Form1.FindNext() you have a new instance of Form2 that you are creating and getting the text value from which is different to the instance where you are calling your FindNext() from.
What you might want to do is to pass in the instance of the form to FindNext(). So your function would be...
//Form1
public void FindNext(Form2 frm2)
{
try
{
this.Focus();
string s = frm2.textBox1.Text;
richTextBox1.Focus();
findPos = richTextBox1.Find(s, findPos, RichTextBoxFinds.None);
richTextBox1.Select(findPos + 1, s.Length);
findPos += textBox1.Text.Length;
}
catch
{
MessageBox.Show("No Occurences Found");
findPos = 0;
}
}
//Form2
private void button1_Click(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
frm1.FindNext(this);
}
By writing Form1 frm1 = new Form1();, you're creating a brand-new instance of the Form1 form, which never gets any text and is never shown to the user.
You need to pass the original Form1 instance to Form2 in Form2's constructor.
Similarly, when you write Form2 frm2 = new Form2(); in FindNext, you're making a brand-new Form2 instance without any text.
Instead, you should pass the text as a parameter to the FindNext method.
For example:
public void FindNext(string searchText) {
...
findPos = richTextBox1.Find(searchText, findPos, RichTextBoxFinds.None);
...
}
originalForm.FindNext(textBox1.Text);
Your textbox on the new instance of frm1 will have no value surely? So there is nothing for the method to do...
Try stepping through the code and checking you actually have values to work with?
When you say:
Form1 frm1 = new Form1();
You are creating a fresh version so any extra information thats been added you dont have when accessing frm1
Try this and you will see what I mean
Form1 frm1 = new Form1();
frm1.Show();
When this code is excecuted you will see that you have actually made another instance of your form.
What you need to do is work with the original instance rather than create a new one, so that you still have all that information in your textboxes.
I'll leave you to work this one out, but there is you answer :)

Categories