C# raise event in Child Form Called From Parent Form - c#

I have a tool strip menu in my parent form and I'm loading my child forms into a panel as user controls. I need to fire an event in my child form when the user clicks on the menu strip in my parent form.
Here is the event in the parent control:
//Character Name
private void randomNameToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
if (_SQL_Settings.TabControl == "Character Builder")
{
}
else
{
MessageBox.Show("You must be in the Character Builder Screen
To Generate A Random Character Name, Please Try Again.");
}
}
catch(Exception ex)
{
}
}
//Character
private void randToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
if (_SQL_Settings.TabControl == "Character Builder")
{
}
else
{
MessageBox.Show("You must be in the Character Builder Screen
To Generate A Random Character, Please Try Again.");
}
}
catch (Exception ex)
{
}
}
Here is where I Build my child form in the Parent form:
case "Character Builder":
{
Character_Builder CC = new Character_Builder();
panCC.Controls.Clear();
CC.Dock = DockStyle.Fill;
panCC.Controls.Add(CC);
CC.Main_Menu += Main_Menu;
break;
}
And here is the functions I want to fire off when the user clicks on the parent form menu strip items
private void Generate_Raondom_Character()
{
try
{
}
catch(Exception ex)
{
}
}
private void Generate_Random_Character_Name()
{
try
{
}
catch (Exception ex)
{
}
}
I have added these two events in my child form but I think they need to be in my parent form.
Events:
public event EventHandler Random_Character;
public event EventHandler Random_Name;
Does anyone know what I need to do to get this to work? Sample would be great. I know how to do it in Vb just not c#.

I have one solution. This is not what I wanted to do but it seems to work. I am looping through the controls in my child forum until I find the control I want and editing the controls text. I wanted to use events but I guess this works too. If anyone has better ways to do this please share:
if (_SQL_Settings.TabControl == "Character Builder")
{
DataTable dt = new DataTable();
dt = _SQL.Random_Character_Name();
foreach (Control Parentctrl in panCC.Controls)
{
if (Parentctrl.Name == "Character_Builder")
{
foreach (Control Childctrl in Parentctrl.Controls)
{
if (Childctrl.Name == "cbFirstName")
{
Childctrl.Text = dt.Rows[0]["First_Name"].ToString();
}
if (Childctrl.Name == "cbLastName")
{
Childctrl.Text = dt.Rows[0]["Last_Name"].ToString();
}
if (Childctrl.Name == "cbCharacterTitle")
{
Childctrl.Text = dt.Rows[0]["Character_Title"].ToString();
}
}
}
}

Related

How to refresh contextmenustrip items or refreshing form's items

Basically, i am creating a raw-based web browser application. Bookmarks are added in contextmenu toolstripitem either from using "star" button or via another form. When added using another form, it is not refreshing the contextmenu items which are added from another form in the main form.
MainForm View:
mainform
Favourites/Bookmarks View:
bookmarks
updatebookmarks
This is how it is added via another form:
addbookmark
addbookmark2
Code Preview:
Star Button:
private void favButton_Click(object sender, EventArgs e)
{
if(inputUrlBox.Text != "")
{
var item = inputUrlBox.Text.ToString();
if(!favouritesToolStripMenuItem.DropDownItems.Cast<ToolStripMenuItem>().Any(x => x.Text == item))
{
try {
Properties.Settings.Default.BookmarksList.Add(item + ",null");
Properties.Settings.Default.Save();
foreach (var bookmark in Properties.Settings.Default.BookmarksList) {
var link = bookmark.Split(',')[0].ToString();
favouritesToolStripMenuItem.DropDownItems.Add(link);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
else
{
MessageBox.Show("Bookmark already exists!");
}
}
}
Moving directly to "Add" in another form's button (this is written in BookmarkWindow Form):
private void addButton_Click(object sender, EventArgs e)
{
AddBookmarkWindow form = new AddBookmarkWindow();
form.ShowDialog(this);
}
In AddBookMark's Form (AddBookmkarkWindow.cs):
if ((isUri) && (linkinput != null && linkinput.Length > 0) && (nameinput != null && nameinput.Length > 0))
{
Properties.Settings.Default.BookmarksList.Add(linkinput + "," + nameinput);
Properties.Settings.Default.Save();
MainWindow mw = new MainWindow();
mw.updatebookmarkstab(linkinput);
this.Close();
MessageBox.Show("Added!");
}
This "updatebookmarkstab" function is in mainwindow/mainform:
public void updatebookmarkstab(string item)
{
menuStrip1.Refresh();
contextMenuStrip1.Refresh();
favouritesToolStripMenuItem.DropDownItems.Add(item);
}
What I expect is, once i add bookmark(s) from another form, I want it to be showed in main form's contextmenustrip item just like how "star" works.
Anyone has any idea on how to refresh menuitems from another form or has a better solution to provide this view.

C# getting information in the behind form

I have two forms
the first one is FrmReceiveItems from which I can display the second one
FrmItemSearch. In the second one I can choose a certain item to add to a DataGridView in the first form. The problem is that whenever I add an item I will have a new object from the first form. I want all chosen items to be added to the first opened form. I try to test if any object of the first form is opened .. as following:
private void dgv_ItemsSearch_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
try
{
//Connection obj = new Connection();
//Connection.FrmChose = 10;
FrmRecieveItemsVoucher FRI = new FrmRecieveItemsVoucher();
Form frmT = Application.OpenForms["FRI"];
int value = Connection.FrmChose;
if (value == 10)
{
FRI.dataGridView_ItemsVoucher.Rows.Add();
int CurrentRowIndex = FRI.dataGridView_ItemsVoucher.Rows.Count;
FRI.dataGridView_ItemsVoucher.Rows[CurrentRowIndex - 1].Cells[0].Value = dgv_ItemsSearch.CurrentRow.Cells[2].Value;
FRI.dataGridView_ItemsVoucher.Rows[CurrentRowIndex - 1].Cells[1].Value = dgv_ItemsSearch.CurrentRow.Cells[1].Value;
// here I try to test
if (frmT != null)
{
this.Dispose();
}
else
{
FRI.Show();
}
}
else
{
FrmItems frmItems = new FrmItems();
//frmCust.btn_new(sender,e);
string Code = Convert.ToString(dgv_ItemsSearch.CurrentRow.Cells[2].Value);
this.Dispose();
frmItems.Show();
frmItems.Show_Record_data(Code);
}
}
catch (Exception Ex)
{
MessageBox.Show(Ex.Message);
}
}
well there are a lot of ways to achieve this. What I would personally go for is creating a BindingList and setting a ListChanged event on that list that would then trigger a reload in the second form.

How to validate textboxes before saving

I got this code and what I am looking for is to validate the text boxes before saving. Now if I fill the textboxes then I clear any of them it saves anyway. How could I possibly check if the are all filled before saving? I was trying to add handlers for textchanged events but I didn't work. Any suggestion will be appreciated, cheers.
public partial class frmTrainer : Form
{
public frmTrainer()
{
InitializeComponent();
// We initialize new event handlers for the subjects textboxes
this.englishTextBox.KeyPress += new KeyPressEventHandler(englishTextBox_KeyPress);
this.mathsTextBox.KeyPress += new KeyPressEventHandler(mathsTextBox_KeyPress);
this.physicsTextBox.KeyPress += new KeyPressEventHandler(physicsTextBox_KeyPress);
}
// We create a public list for all the textbox controls in the form
public List textBoxes = new List();
private void frmTrainer_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'rCMDataSet.Students_Credentials' table. You can move, or remove it, as needed.
this.students_CredentialsTableAdapter.Fill(this.rCMDataSet.Students_Credentials);
// We initialize the List of textboxes
textBoxAdd();
}
// We create method stubs for the KeyPress event on the subjects textboxes
// to allow them receive only numeric inputs
private void englishTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
MessageBox.Show("Numeric input accepted only");
}
}
private void mathsTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
MessageBox.Show("Numeric input accepted only");
}
}
private void physicsTextBox_KeyPress(object sendet, KeyPressEventArgs e)
{
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar))
{
e.Handled = true;
MessageBox.Show("Numeric input accepted only");
}
}
// We create a method to add each textbox to the List
private void textBoxAdd()
{
textBoxes.Add(studentIDTextBox);
textBoxes.Add(first_NameTextBox);
textBoxes.Add(last_NameTextBox);
textBoxes.Add(usernameTextBox);
textBoxes.Add(passwordTextBox);
textBoxes.Add(englishTextBox);
textBoxes.Add(mathsTextBox);
textBoxes.Add(physicsTextBox);
textBoxes.Add(trainerIDTextBox);
}
// We create a private method to validate the textboxes
private void CheckTextBox()
{
foreach(TextBox txt in textBoxes)
{
if (string.IsNullOrWhiteSpace(txt.Text))
{
MessageBox.Show("Please insert data correctly");
}
}
}
private void students_CredentialsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.CheckTextBox();
try
{
//this.Validate();
this.students_CredentialsBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.rCMDataSet);
MessageBox.Show("Data saved successfully");
}
catch(System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void toolStripExit_Click(object sender, EventArgs e)
{
// We disable the automatic validation when clicking Exit button
this.AutoValidate = AutoValidate.Disable;
// We call the method to close the application
Application.Exit();
}
private void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
{
// We disable the navigation buttons to prevent any skipping errors
this.bindingNavigatorMoveFirstItem.Enabled = false;
this.bindingNavigatorMoveLastItem.Enabled = false;
this.bindingNavigatorMoveNextItem.Enabled = false;
this.bindingNavigatorMovePreviousItem.Enabled = false;
}
}
}
In your students_CredentialsBindingNavigatorSaveItem_Click event, while you do call the CheckTextBox method to "validate" your controls, you're essentially not doing anything about empty controls except to show a MessageBox. What you should do is to return a boolean on the validation method whenever an empty input is found:
private bool CheckTextBox()
{
bool isValid = true;
foreach(TextBox txt in textBoxes)
{
if (string.IsNullOrWhiteSpace(txt.Text))
{
isValid = false;
MessageBox.Show("Please insert data correctly");
break; //You only need one invalid input to prevent saving
}
}
return isValid;
}
And in your Click event, check for the return value of the method and exit the event if an invalid input is detected:
private void students_CredentialsBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
if(!this.CheckTextBox()) return; //Stop executing code if there's invalid input
try
{
//this.Validate();
this.students_CredentialsBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.rCMDataSet);
MessageBox.Show("Data saved successfully");
}
catch(System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Did you try using the String.Trim method on your text box text like:
foreach(TextBox txt in textBoxes)
{
//trim whitespaces from text at both ends and might be better to operate on a string
String text = txt.ToString();
text.Trim();
if (string.IsNullOrWhiteSpace(text))
{
MessageBox.Show("Please insert data correctly");
}
}

need to unify child form button clicks into one routine

I have discovered that I am beginning to use the same code for a few different click events. I have a MDI form and there are "master children" as I call them that will open other children associated with the master. This is the master/detail thing going on. An example is the Company master child will have buttons to open the Contact, Industry, etc associated with the Company. Below is a sample of the code that opens the Contact child form. This code is also being used for the others as well.
What I am looking to do is to be able to use just one and fill in the button, form, message, and a connection label between Company and Contact. The code at the botton is what I have so far and I marked the lines that need to be changed with what I'm looking for. The lines with the single arrow "seem" to work but the multi arrow line can't get it right. Providing both for comparison reasons.
Could someone look this/these over and see what I'm doing wrong (or missing) in the consolidated code?
Thanks...John
//CODE TO OPEN THE CONTACT CHILD FORM
private void btnCompanyContact_Click(object sender, EventArgs e)
{
bool isOpen = false;
foreach (Form f in Application.OpenForms)
{
if (f is frmContact)
{
isOpen = true;
MessageBox.Show("The Contact list is already open.", "INFORMATION", MessageBoxButtons.OK);
f.BringToFront();
f.Controls["lblRecordID"].Text = lblCompanyID.Text;
break;
}
}
if (!isOpen)
{
frmContact contact = new frmContact();
contact.MdiParent = this.MdiParent;
contact.ReceiveValue(lblCompanyID.Text);
contact.StartPosition = FormStartPosition.Manual;
contact.Location = new Point(100, 100);
contact.Show();
}
else
{
//do nothing
}
}
//CONSOLIDATE ALL THE BUTTON OPENING INTO THIS ROUTINE
private void OpenCompanyInformationForm(Button btn, Form name, string message, string lbl)
{
bool isOpen = false;
foreach (Form f in Application.OpenForms)
{
-> if (f == name)
{
isOpen = true;
-> MessageBox.Show("The " + message + " list is already open.", "INFORMATION", MessageBoxButtons.OK);
f.BringToFront();
-> f.Controls[lbl].Text = lblCompanyID.Text;
break;
}
}
if (!isOpen)
{
->->-> frmContact contact = new frmContact();
contact.MdiParent = this.MdiParent;
contact.ReceiveValue(lblCompanyID.Text);
contact.StartPosition = FormStartPosition.Manual;
contact.Location = new Point(100, 100);
contact.Show();
}
else
{
//do nothing
}
}
To perfom the custom function ReceiveValue you need to create a derived class from Form
and create all you forms from this derived class
public class ContactBase : Form
{
public void ReceiveValue(string p_Value)
{
Button button = (Button)this.Controls["lblRecordID"];
if (button == null) return;
button.Text = p_Value;
}
}
private void OpenCompanyInformationForm(Form name)
{
bool isOpen = false;
foreach (Form f in Application.OpenForms)
{
// Just to compare, you can use the Name property
-> if (f.Name == name.Name)
{
isOpen = true;
// If the message is just a name of form, you can use Name or Text property
// in this case you can supress message param
-> MessageBox.Show("The " + f.Text + " list is already open.", "INFORMATION", MessageBoxButtons.OK);
f.BringToFront();
// If the ReceiveValue is just to pass the text of lblCompanyID for lblRecordID button, you can use the function here
-> ((ContactBase)name).ReceiveValue(lblCompanyID.Text);
break;
}
}
if (!isOpen)
{
->->-> ContactBase contact = (ContactBase)Activator.CreateInstance(name.GetType());
contact.MdiParent = this.MdiParent;
contact.ReceiveValue(lblCompanyID.Text);
contact.StartPosition = FormStartPosition.Manual;
contact.Location = new Point(100, 100);
contact.Show();
}
else
{
//do nothing
}
}

Get list of open windows form instance that are excuted from different assembly

I have a 'loader app' that loads a menu and when user clicks the menu image button a list view opens based on the text
(if text = employee)
(Go to class A)
(Go to class B)
...
...
(Show List View Window)
if he clicks again on the same button it opens again, I would like to prevent this.
i.e but this for a WPF application
If you want a list of the open forms, that is Application.OpenForms. You could iterate over this, using GetType() and checking the .Assembly to find those from a different assembly. Beyond that, I'm not entire clear on the question...
Assembly currentAssembly = Assembly.GetExecutingAssembly();
List<Form> formsFromOtherAssemblies = new List<Form>();
foreach (Form form in Application.OpenForms) {
if (form.GetType().Assembly != currentAssembly) {
formsFromOtherAssemblies.Add(form);
}
}
If you just want to track forms you have opened yourself, then cache that instance. Or if you use "owned forms", you can just check by name:
private void button1_Click(object sender, EventArgs e) {
foreach (Form form in OwnedForms) {
if (form.Name == "Whatever") {
form.Activate();
return;
}
}
Form child = new Form();
child.Name = "Whatever";
child.Owner = this;
child.Show(this);
}
NewProduct newproduct;
private void button1_Click(object sender, EventArgs e)
{
if(!isOpened())
{
newproduct = new NewProduct();
newproduct.Show();
}
}
private bool isOpened()
{
foreach (Form f in Application.OpenForms)
{
if (f == newproduct)
{
return true;
}
}
return false;
}
Another simple example
private Boolean FindForm(String formName)
{
foreach (Form f in Application.OpenForms)
{
if (f.Name.Equals(formName))
{
f.Location = new Point(POINT.X, POINT.Y + 22);
return true;
}
}
return false;
}
You can use a Command pattern. The loader assembly will search for commands in loaded assemblies.
For every command the loader create menu item ( or anything else, you want ), and click event will run the concrete command.
The command must know if should be created new form or used some already existing.
Mark Garvell's answer helped me to figure out what I should do, but it needed adjusting for WPF.
(In my case I wanted to close any windows not owned by the main one when it closes, but the principle is the same.)
private void EmployeeMenuItemClick(object sender, RoutedEventArgs e)
{
bool found = false;
foreach(Window w in Application.Current.Windows)
{
if(w.GetType() == typeof(EmployeeListViewWindow)
{
found = true;
break;
}
}
if(!found)
{
EmployeeListViewWindow ew = new EmployeeListViewWindow();
ew.Show();
}
}

Categories

Resources