Adding a Single-record Form

So far, we have a form that displays clients in a read-only grid. Now we need a CRUD form, that is, a form that will let us create, update, and delete clients. We’ll create one from the GenericForm template and call it ClientForm. Notice that the form’s Text property, which is reflected as the form’s title, is automatically set to the name you gave the form. That’s a nice feature of templates.

Of course, the form isn’t exactly what we need. We don’t need the data grid view nor the splitter. Getting rid of the data grid view is easy. We select it and press the Delete key. But when we try this with the splitter, nothing happens! Why not? What’s going on is that, when we think we’re selecting the splitter, we’re really just selecting one of the panels, and since the panels are an integral part of the control, they can’t be deleted. What we need to do is select the splitter control itself. To do this, select either panel and press the Escape key. Then you can press Delete to remove the splitter.

So now we have an empty shell of a form. We need to add fields to it.

By default, dragging a table from Data Sources to a form creates a Data Grid View. Table columns also have a default input control. In both cases, however, you can change this by clicking the table or column and activating the drop-down. In the case of tables, we can choose between Data Grid View and Details, which means each column turned into an input text box on the form.

So, let’s change Clients from DataGridView to Details, and then let’s drag the entire table over to our empty form. Here’s what we wind up with.

As expected, Visual Studio created a bunch of data objects when we dropped the table into the form. To refresh what they all are, let start with the table adapter manager.

The Various Data Objects

tableAdapterManager The table adapter manager is only useful when you’re updating related tables. If you’re deleting a parent row, for example, you want to delete all the child rows first. Or if you’re adding a parent row with child rows, you want to add the parent first so that you then have the foreign key for the child rows. The table adapter manager accomplishes this automatically with its UpdateAll method. We’re not updating related tables, so we really don’t need it, but we’ll leave it for now.

dSClients This is the dataset. It contains an in-memory representation of the data you define in the Data Designer or in code. This would include the data tables. However, the data tables themselves are manipulated using methods in the table adapters, not the dataset.

clientsTableAdapter This object contains the methods that insert, update, and delete rows in the Clients table that is held in dSClients. The table adapter object doesn’t contain the table, at least not in any usable form that I know of. It’s just a wrench to work on the table that lives in the data set. This distinction between data set and table adapter confused me for a while.

clientsBindingSource The binding source is what connects the data in the data tables (that are in the data set) to the various fields (text boxes, combo, calendar, etc.). The binding source causes the controls on the screen to refresh their data when the current row changes. You also use it to update the current row, just before using the table adapter to update it in the table (after which, you would use the dataset to update the actual database).

clientsBindingNavigator This control provides a toolbar with buttons that are already coded to navigate through the database. It also creates code to save an updated row. Each of its navigation buttons maps to a method in the binding source. That’s why you can’t find any code for it anywhere! 🙂

Now let’s look at the code Visual Studio generated for us just in the cs file (it generates a whole lot more in the Designer.cs file, as we’ve seen).

using System.Windows.Forms;

namespace TheBooks
{
    public partial class ClientForm : Form
    {
        public ClientForm()
        {
            InitializeComponent();
        }

        private void clientsBindingNavigatorSaveItem_Click(
            object sender, System.EventArgs e)
        {
            this.Validate();
            this.clientsBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.dSClients);

        }

        private void ClientForm_Load(object sender, System.EventArgs e)
        {
            // TODO: This line of code loads data into the 'dSClients.Clients'
            //       table. You can move, or remove it, as needed.
            this.clientsTableAdapter.Fill(this.dSClients.Clients);

        }
    }
}

We saw in ClientList how Visual Studio adds the line that calls the table adapter’s Fill method. Now we see that Visual Studio also adds code for the binding navigator’s SaveItem method.

There’s a lot we could do to customize the form and make it look nicer and be more user friendly, but let’s move ahead for now. Note that this form isn’t connected to anything. If we run the application, this form won’t show up. We will have to connect this new form to the rest of the application.

To make sure a detail I miss doesn’t prevent anyone from getting to this point, here’s a zip file with all the source code so far and the SQLite database.

Leave a Reply

Your email address will not be published. Required fields are marked *