Alex Watts
Alex Watts

Reputation: 567

How to pass textbox data to a datagridview in different forms

I have two forms:

The first form (XML Data Loader) contains a DataGridView with six columns (Name, Width, Height, Length, Dead Weight, Load Capacity)

XML Data Loader also has a button on it, which when pressed opens a new forms window (Add New Car). Add New Car has six textboxes where train car data is input by a user.

The goal is for the user to be able to click the Save button on Add New Car and the data will be pushed into a new row in the DataGridView on XML Data Loader, but I am having an issue with actually finding a way to do this. Everything else I've found assumes that DataGridViews are being populated through a database, but mine is user-input populated.


public partial class XMLDataLoader : Form
{
    public XMLDataLoader()
    {
        InitializeComponent();
    }

    private void buttonAddCar_Click(object sender, EventArgs e)
    {
        AddNewCar addNewCar = new AddNewCar();
        addNewCar.Show();
    }
}

enter image description here

public partial class AddNewCar : Form
{
    public AddNewCar()
    {
        InitializeComponent();
    }

    private void buttonNewSave_Click(object sender, EventArgs e)
    {
        //Check that all textboxes have some kind of entry
        //ToDo: check the type of data so that only numbers are entered into non-name categories
        if(textBoxNewName.TextLength < 1)
        {
            MessageBox.Show("Please enter a train name!");
        }
        if (textBoxNewWidth.TextLength < 1)
        {
            MessageBox.Show("Please enter a train width!");
        }
        if (textBoxNewHeight.TextLength < 1)
        {
            MessageBox.Show("Please enter a train height!");
        }
        if (textBoxNewLength.TextLength < 1)
        {
            MessageBox.Show("Please enter a train length!");
        }
        if (textBoxNewDeadWeight.TextLength < 1)
        {
            MessageBox.Show("Please enter a train dead weight!");
        }
        if (textBoxNewLoadCapacity.TextLength < 1)
        {
            MessageBox.Show("Please enter a train load capacity!");
        }

        //Save all data input by user to create a new train momentarily
        var newTrainName = textBoxNewName.Text;
        var newTrainWidth = textBoxNewWidth.Text;
        var newTrainHeight = textBoxNewHeight.Text;
        var newTrainLength = textBoxNewLength.Text;
        var newTrainDeadWeight = textBoxNewDeadWeight.Text;
        var newTrainLoadCapacity = textBoxNewLoadCapacity.Text;
    }
}

enter image description here

Upvotes: 2

Views: 1752

Answers (2)

Alex Watts
Alex Watts

Reputation: 567

Hat tip to @Ed Plunkett for the help - it's working swimmingly now!!


public partial class XMLDataLoader : Form
{
    public XMLDataLoader()
    {
        InitializeComponent();
    }

    //Function for the Add Car button to open the Add New Car window
    private void buttonAddCar_Click(object sender, EventArgs e)
    {
        AddNewCar displayNewCarWindow = new AddNewCar();
        displayNewCarWindow.ShowDialog();

        dataGridViewMainCarDisplay.Rows.Add(displayNewCarWindow.NewTrainName
                                           , displayNewCarWindow.NewTrainWidth
                                           , displayNewCarWindow.NewTrainHeight
                                           , displayNewCarWindow.NewTrainLength
                                           , displayNewCarWindow.NewTrainDeadWeight
                                           , displayNewCarWindow.NewTrainLoadCapacity);
    }

    //Function for the Remove Car button to delete the currently
        //selected car from the datagridview
    private void buttonRemoveCar_Click(object sender, EventArgs e)
    {

    }
}

}


public partial class AddNewCar : Form
{
    public AddNewCar()
    {
        InitializeComponent();
    }

    //Get and Private Set methods to pass textbox data to XMLDataLoader form
    public String NewTrainName { get; private set; }
    public String NewTrainWidth { get; private set; }
    public String NewTrainHeight { get; private set; }
    public String NewTrainLength { get; private set; }
    public String NewTrainDeadWeight { get; private set; }
    public String NewTrainLoadCapacity { get; private set; }

    private void buttonNewSave_Click(object sender, EventArgs e)
    {
        //Check that all textboxes have some kind of entry
        //ToDo: check the type of data so that only numbers are entered into non-name categories
        var message = String.Empty;

        if(textBoxNewName.TextLength < 1)
        {
            message += "Please enter a train name!\n";
        }
        if (textBoxNewWidth.TextLength < 1)
        {
            message += "Please enter a train width!\n";
        }
        if (textBoxNewHeight.TextLength < 1)
        {
            message += "Please enter a train height!\n";
        }
        if (textBoxNewLoadCapacity.TextLength < 1)
        {
            message += "Please enter a train length!\n";
        }
        if (textBoxNewDeadWeight.TextLength < 1)
        {
            message += "Please enter a train dead weight!\n";
        }
        if (textBoxNewLength.TextLength < 1)
        {
            message += "Please enter a train load capacity!\n";
        }

        //Save all data input by user to create a new train
        NewTrainName = textBoxNewName.Text;
        NewTrainWidth = textBoxNewWidth.Text;
        NewTrainHeight = textBoxNewHeight.Text;
        NewTrainLength = textBoxNewLoadCapacity.Text;
        NewTrainDeadWeight = textBoxNewDeadWeight.Text;
        NewTrainLoadCapacity = textBoxNewLength.Text;

        //Handle the form execution for whether or not a textbox is empty
        if (message != String.Empty)
        {
            MessageBox.Show(message);
        }
        else
        {
            DialogResult = DialogResult.OK;
        }
    }        

    //Function for the Cancel button to close the Add New Car window
    private void buttonNewCancel_Click(object sender, EventArgs e)
    {
        DialogResult = DialogResult.Cancel;
    }
}

enter image description here

Upvotes: 0

First, use ShowDialog() instead of Show(). That way, you will still be in buttonAddCar_Click when the AddNewCar dialog closes. The way your code is now, buttonAddCar_Click will exit while AddNewCar is still visible, and your main window will have lost all contact with the instance of AddNewCar that you created.

Secondly, you need to expose the text box values to the caller. So after the dialog closes, addNewCar.textBoxNewName.Text will contain the string the user typed into the New Name TextBox. But by default that's not public. So add a bunch of properties to expose the values:

public String NewName { get { return textBoxNewName.Text; } }

In buttonAddCar_Click after the call to ShowDialog(), you can do whatever you like with the exposed Text properties of all those TextBoxes.

I don't do winforms every day now, so it's possible that textBoxNewName.Text may throw an exception if you touch it after the form closes. Easy fix! Declare the public properties as regular properties instead of get-only accessors...

public String NewName { get; protected set; }

...and assign them their values in the OK click event when the user's input passes validation. Which is our next topic.

Lastly, making the user click on (potentially) six popups in succession is enough to make him commit suicide. Instead, I'd recommend declaring a string variable called message and concatenating:

    string message = "";
    if(textBoxNewName.TextLength < 1)
    {
        message += "Please enter a train name!\n"
    }
    if (textBoxNewWidth.TextLength < 1)
    {
        message += "Please enter a train width!\n";
    }

    //  ...etc....

    if (!String.IsNullOrWhiteSpace(message))
    {
        MessageBox.Show(message);
    }
    else
    {
        NewName = textBoxNewName.Text;
        //  ...and so on for the other five properties. 

        //  This will close the form and cause ShowDialog() to
        //  return DialogResult.OK
        DialogResult = DialogResult.OK;
    }

Form.DialogResult is a useful adjunct to Form.ShowDialog().

If you have a Cancel button, it doesn't even need a Click method. Just set that Button's DialogResult property to DialogResult.Cancel in the form designer, and it'll assign that value to Form.DialogResult when the user clicks it, which will cause the window to close and ShowDialog to return DialogResult.Cancel.

Another way you could do this is declare a simple class which has all the car-creation data in it: NewName, Width, etc. Write an overload of ShowDialog() which returns that type, or which takes a reference to that type and returns bool (true for OK). If user cancels it returns null or false; if user clicks OK and passes validation, it returns an instance of that class, or in the reference version, populates the members of the reference that was passed in, and then returns true.

If you already have a class which represents a Car (from Entity Framework or whatever), you would just use that.

But the way I've described above is consistent with usage in built-in WinForms dialogs like FileOpen and so on. My touchstone when working in any environment like WinForms, MFC, WPF, etc. is What Would the Framework Do? That's almost invariably the right answer, because a) successful frameworks tend to be reasonably well designed (they are used successfully by people who can't access their internals or consult their implementors), and b) anybody who interacts your code will know exactly what to expect because he already knows the framework's way of doing things.

Every time I use third party code that thinks it's smarter than the framework, I can't help noticing how much dumber it is.

Upvotes: 2

Related Questions