1

I have two forms, "FrmRunEntry" and "FrmPartNumEntry". When I enter a value on the FrmRunEntry form, it displays the FrmPartNumEntry from and a combobox. After selecting a value in the combobox, I want to press the ENTER key and carry the selected value from the combobox back to a textbox on the FrmRunEntry form. But I cant get it to work. My combobox and form Keydown events never get triggered. My program just sits on the combobox and does nothing after I press ENTER. I've search the forum extensively and have tried the following solutions without success:

How to pass value from one form into another's combobox

How to get selected items of Combobox from one form to another form in C#

I've also tried a few other solutions that didn't work. I'm a new C# programmer and I admit I don't have a deep understanding of how C# events work. I'm hoping someone can assist in solving this problem and help me understand what I'm doing wrong. Here's the code I'm using:

FORM 1

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HydroProgram
{
    public partial class FrmRunEntry : Form
    {
        public string selectedPartNumber = "";

        public FrmRunEntry()
        {
            InitializeComponent();
            this.ActiveControl = TxtHydro;
            TxtHydro.Focus();
        }

        private void FrmRunEntry_Load(object sender, EventArgs e)
        {
            //Text Boxes
            TxtHydro.CharacterCasing = CharacterCasing.Upper;

            if (!string.IsNullOrEmpty(selectedPartNumber))
            {
                TxtPartNum.Text = selectedPartNumber;
            }
        }

 
        private void TxtHydro_KeyDown(object sender, KeyEventArgs e)
        
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.Hide();
                FrmPartNumEntry f = new FrmPartNumEntry();
                f.ShowDialog();
            }
        }
    }
}


FORM 2

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HydroProgram
{
    public partial class FrmPartNumEntry : Form
    {
        public FrmPartNumEntry()
        {
            InitializeComponent();
            this.ActiveControl = CboPartNum;
        }

        private void FrmPartNumEntry_Load(object sender, EventArgs e)
        {
            //Combo Box
            CboPartNum.Location = new Point(668, 240);
            CboPartNum.Size = new Size(255, 23);
            CboPartNum.Focus();
            CboPartNum.SelectedIndex = 1;
        }

        private void CboPartNum_KeyDown(object sender, KeyEventArgs e)              <-- NOT BEING TRIGGERED
        {
            processRequest(e);
        }

        private void FrmPartNumEntry_KeyDown(object sender, KeyEventArgs e)         <-- NOT BEING TRIGGERED
        {
            processRequest(e);
        }

        private void processRequest(KeyEventArgs e)                     <-- NEVER REACHED
        {
            if (e.KeyCode == Keys.Enter && this.ActiveControl == CboPartNum)
            {
                this.Hide();
                FrmRunEntry f = new FrmRunEntry();
                f.selectedPartNumber = Convert.ToString(CboPartNum.SelectedItem);
                f.ShowDialog();
            }
        }
    }
}
NewUser
  • 27
  • 7
  • Does this answer your question? [Communicate between two windows forms in C#](https://stackoverflow.com/questions/1665533/communicate-between-two-windows-forms-in-c-sharp) – JohnG Jun 21 '21 at 22:13

5 Answers5

1

you can overload the constructor of the form for example

public FrmPartNumEntry()
{
    InitializeComponent();
    this.ActiveControl = CboPartNum;
}

To This

public public FrmPartNumEntry(int value)
{
    InitializeComponent();
    this.ActiveControl = CboPartNum;
}

Then store value in a private variable. Then you can use it anyway as you want. if you want to pass anything simply use an object as a parameter then cast it inside the constructor. for example

public public FrmPartNumEntry(object value)
{
    InitializeComponent();
    int x = (int) value;
    this.ActiveControl = CboPartNum;
}

in your situation where both forms are running.

assume you form1 contains combobox and form2 need the data of it then

  1. Make a static field in form1 and make it public.
  2. use textchanged event in combobox to assign the value to static field
  3. access by form1.staticfieldname from form2.
  • When I tried your code: I got a compiler error: CS1525 Invalid expression term 'object' on this line: int x = (int) object; – NewUser Jun 21 '21 at 15:28
  • Now there's a new problem. "int x = (int)value; gives me an unhandled exception: System.InvalidCastException: 'Unable to cast object of type System.String' to type "System.Int32'.' Also, VS won't allow me duplicate 'public' as in "public public FrmPartNumEntry(object value)". Do you have any suggestions? – NewUser Jun 21 '21 at 17:22
  • yeah if you are sending a string from form1 cast it to string instead of int in form2. – chamod priyamal Jun 22 '21 at 17:02
  • public public FrmPartNumEntry(object value) why use two public keywords ? – chamod priyamal Jun 22 '21 at 17:03
1

I am not getting the same result as you describe. When I click on the combo box in the frmPartNumEntry form, then press the “Enter” key… the CboPartNum_KeyDown event fires as expected. So the posted code does not demonstrate what you describe.

In addition and more importantly, your code is “creating” and “hiding” multiple forms that are only displayed once, then hid and never used again. This certainly will cause confusion and problems. One issue is that if you execute the complete code, then try to “exit” the program by clicking the red x in the top right of the form… you may notice that execution does NOT stop. The code continues to run and this is because the hidden forms are technically still executing as they were never closed.

To show this… let us look at the code in the first form FrmRunEntry TxtHydro_KeyDown event. If the user presses the “Enter” key, then the currently displayed FrmRunEntry is hidden…

this.Hide();

Then a new second form FrmPartNumEntry is created and it is displayed using a ShowDialog();… This may appear correct, however there is one big problem with this code… when the user closes the second form and code execution returns to THIS code… the current FrmRunEntry is never UN-HIDDEN.

The code in second form’s FrmPartNumEntry processRequest method follows this same odd pattern, hide the current form, then it creates a NEW FrmRunEntry? ... This is NOT going to be the same FrmRunEntry form which was previously hidden. In reality NOW you have TWO (2) FrmRunEntry forms and one is hidden. If you continue to execute this code, each time the steps are duplicated… 2 NEW forms are created and hidden.

I am confident this is NOT what you want.

The posted duplicate link shows several ways to pass data between forms. In your particular case, one possible solution is the make the ComboBox on the second form a “public” combo box. Then make the following changes to the processRequest method. First, we do not want to “hide” this form… we want to CLOSE it. In addition we do NOT want to create a new FrmRunEntry form, we want to UN-hide the one that was previously hidden. So, in the processRequest all we need is to close the form. Something like…

private void processRequest(KeyEventArgs e) {
  if (e.KeyCode == Keys.Enter && this.ActiveControl == CboPartNum) {
    this.Close();
  }
}

When this form closes, then execution will go back to the first form. Specifically the TxtHydro_KeyDown event. Execution will begin right after the…

f.ShowDialog(); 

line of code. So it is here where want to UN-Hide/Show the previously hidden FrmRunEntry form. In addition, we want to get the selected ComboBox value from the now closed FrmPartNumEntry. Fortunately, even though the second form is “technically” closed and not displayed… we should still be able to access the “public” variables on the form. As noted previously, if the ComboBox has it's Modifiers property set to public then the following code should work and give the first form access to the second forms ComboBox. Something like…

private void TxtHydro_KeyDown(object sender, KeyEventArgs e) {
  if (e.KeyCode == Keys.Enter) {
    this.Hide();
    FrmPartNumEntry f = new FrmPartNumEntry();
    f.ShowDialog();
    this.Show();
    TxtHydro.Text = f.CboPartNum.Text;
  }
}

I hope this makes sense and helps.

JohnG
  • 9,259
  • 2
  • 20
  • 29
  • You critique of my code makes perfect sense and I plan to adjust how I open and close forms accordingly. However, even after implementing your suggestions, it doesn't seem to address the cause of my problem. Once FrmPartNumEntry is displayed with the ShowDialog(), nothing else happens. I know the CboPartNum_KeyDown event should fire after selecting a value, but it doesn't, even after changing the "Modifiers" property on the combobox to public. Could there be a more systemic problem with my form that's preventing it from behaving as expected? – NewUser Jun 22 '21 at 12:51
  • 1
    Have put a break point in the `CboPartNum_KeyDown` event to verify it is not getting fired? If it is not firing, then it sounds like the event has not been subscribed to. To verify if the event has been properly subscribed to… go to the designer, click on the `CboPartNum` combo box, look at the properties window (bottom right), click on the combo boxes event properties (little thunderbolt) and look at the `KeyDown` event. If it is blank then that is why the event is not firing. If it is not blank… it should show your event. – JohnG Jun 22 '21 at 13:40
  • 1
    Subscribing to the event looks something like… `CboPartNum.KeyDown += new KeyEventHandler(CboPartNum_KeyDown);` You can also put this line of code in the form’s constructor. If you do not properly “subscribe” to the event, it will not fire. – JohnG Jun 22 '21 at 13:40
  • 1
    In addition your comment… _”I know the CboPartNum_KeyDown event should fire after selecting a value,… “_ … this is not true, if you change the combo box selection, the combo boxes `KeyDown` event will NOT fire, to get the `KeyDown` event to fire, you need to select a value in the combo box THEN press the “Enter” Key. If you want the event to fire when the user changes a selection in the combo box, then you need to subscribe to the combo boxes `SelectedIndexChanged` event and put your code in that event. – JohnG Jun 22 '21 at 13:52
  • OMG! After struggling with this problem for several days I can't believe the solution was so simple. I updated the combobox event property and it worked perfectly. Then I deleted it and added the CboPartNum.KeyDown += new KeyEventHandler(CboPartNum_KeyDown); statement to the form's constructor and it also worked perfectly. I tend to like to use code, so I kept the statement in the constructor. You have no idea how grateful I am! – NewUser Jun 22 '21 at 14:43
1

Thanks to JohnG, the solution to my problem was amazingly simple. All I needed was a single line of code in the form constructor to subscribe the combobox to the event handler like this:

public FrmPartNumEntry()
        {
            InitializeComponent();
            this.ActiveControl = CboPartNum;
            CboPartNum.KeyDown += new KeyEventHandler(CboPartNum_KeyDown); <-- SOLUTION
        }
NewUser
  • 27
  • 7
0

One solution would be to:

on form1 define the variable as static:

public partial class Form1 : Form
{
   public static string name = "xxx";
}

then on form2 access the variable from form1:

public partial class Form2 : Form
{
   lblName.Text = Form1.name;
}
stefan_aus_hannover
  • 1,777
  • 12
  • 13
0

another option is to use an event. The following is a generic code sample which has Main form with a ComboBox and button. Press the button to show the child form and when the ComboBox selection changes an event is fired for any listeners which Form1 does listen for in a method which first checks to see if the item is in the ComboBox in Form1, if not exists, add it and select it.

Child form (Form2)

using System;
using System.Linq;
using System.Windows.Forms;
using static System.Globalization.DateTimeFormatInfo;

namespace CodeSample
{
    public partial class Form2 : Form
    {
        public delegate void SelectionChange(string sender);
        public event SelectionChange OnSelectionChange;
        
        public Form2()
        {
            InitializeComponent();
            
            MonthsComboBox.DataSource = 
                Enumerable.Range(1, 12).Select((index) => 
                CurrentInfo.GetMonthName(index)).ToList();

            MonthsComboBox.SelectedIndexChanged += 
                MonthsComboBoxOnSelectedIndexChanged;
        }

        private void MonthsComboBoxOnSelectedIndexChanged(object sender, EventArgs e)
        {
            OnSelectionChange?.Invoke(MonthsComboBox.Text);
        }
    }
}

Form1 main form

Note I use ShowDialog, Show may be used instead.

using System;
using System.Windows.Forms;

namespace CodeSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void ShowChildForm_Click(object sender, EventArgs e)
        {
            var f = new Form2();
            
            f.OnSelectionChange += OnSelectionChange;
            
            try
            {
                f.ShowDialog();
            }
            finally
            {
                f.OnSelectionChange -= OnOnSelectionChange;
                f.Dispose();
            }
        }

        private void OnSelectionChange(string sender)
        {
            if (MonthsComboBox.FindString(sender) != -1) return;
            
            MonthsComboBox.Items.Add(sender);
            MonthsComboBox.SelectedIndex = MonthsComboBox.Items.Count - 1;
        }
    }
}
Karen Payne
  • 4,341
  • 2
  • 14
  • 31
  • I've been trying to use events. But once the second form is show, no events will fire. I've tried SelectedIndexChanged, TextChanged, KeyDown on the combobox, and KeyDown on the form. It displays my form and then goes to sleep. All I can do is exit. I'm open to any ideas you may ahve. – NewUser Jun 21 '21 at 20:50