Bind ComboBox and Other Controls to DataGridView using STT - CodeProject

:

Introduction

In our previous articles, we presented the STT DLL library and how some of its functionalities can be used in practice:

The demo application of this article continues on from the last article. If there are things which are unclear, please read the previous articles.

In this article, we will show how to easily set ComboBox data sources and how to bind WinForm controls to a DataGridView using STT.

In our demo application, we will bind text, float, date Columns and two types of ComboBox controls. One has its source in a STT table class and another has a custom source. We also have binding to a button where the button back color, flat style and On_Click event are binded to the DataGridView.

Background

It is a real pain to work with DataGridViews and it gets worse if ComboBoxes come to it. Why? For real functionality, how should it be in a ComboBox. You have to add it to a DataGridView with code. And that every time the ComboBox source changes. Doing it for one ComboBox is hard work, then comes a second, a third one and so on.... while the code becomes larger and larger and confusing. If you have tried to add a ComboBox to a DataGridView from scratch, you know what I mean.

Using the Code

Bind a Control to a DataGridView

To bind a control to a DataGridView using STT, we need only one line of code:

tblTable1.Columns["TextColumn"].BindToControl(textBox1);

Every change in the dgv cell will be synced to the control and from the control to the dgv cell. Moving through the dgv will change the values in the binded controls.

It is important that the binding code is before the code with which we bind a STT table class to a DataGridView.

tblTable1.Columns["TextColumn"].BindToControl(textBox1);
tblTable1.BindTableToDataGridView(dgvTable1);

The same code is used for any kind of Control we want to bind to our DataGridView.

Now you ask yourself "what is with the ComboBoxes"? If I bind a combobox to the DatagridView, where does it have its datasource?

If we bind a combobox to a datagrdiview using STT, the datagridview combobox resulting from that will have the datasource from the combobox we have binded it. That will bring us to the next part of the article.

Set the datasource of a ComboBox

We all know how to set a datasource of a ComboBox. Even if it is easy, it takes time and code. If we use STT tables, it is just one line of code.

STT.ComboBoxAdapter.EqualiseComboBoxes(comboBox1, tblTable2.ComboBox("PlayerName"));

What does this line of code do? It takes a combobox control with no source (comboBox1) and sets its source to the Table2. It uses as default the ID Column as value member and the column Name as display member. If there is no column Name in our source table, we can set another column like PlayerName. We can also change the valuemember of the column from ID to another but because in the STT every table should have an ID column, we can leave it now how it is.

After that, our combobox has its datasource and we can bind it to our datagridview.

tblTable1.Columns["PlayerID"].BindToControl(comboBox2);

It is important that the control we bind to a column has the same DatagridViewColumn control type. That means that we can bind a combobox only to a combobox column of our table. If we see our Table1, the PlayerID column we will notice that is an combobox column.

Columns.AddComboBox(this, "PlayerID", "Player");

STT has an event for the table class called OnBindingColumnsToControls. That event can be added to the table before the binding to a DataGridView.

tblTable1.OnBindingColumnsToControls += tblTable1_OnBindingColumnsToControls;
tblTable1.BindTableToDataGridView(dgvTable1);

And in that event, we can set our control binding code.

void tblTable1_OnBindingColumnsToControls(object sender)
{
    tblTable1.Columns["TextColumn"].BindToControl(textBox1);

    STT.ComboBoxAdapter.EqualiseComboBoxes(comboBox1, tblTable2.ComboBox("PlayerName"));
    tblTable1.Columns["PlayerID"].BindToControl(comboBox1);
}

Every time we use the context menu of the table and press "Refresh Fields", this event will be called. Also before binding the table to a dgv, it will be raised.

Why would we use the Refresh Fields action?

If we have a ComboBox in our DataGridView whose source is another table in our application. If values or rows in our source table are changed, we will still have those values from the moment we binded our ComboBox control. To refresh our combobox source, we use this action RefreshFields.

That also means that a ComboBox whose datasource is set with the STT has only a snapshot of the table data from the moment its source is set. That also means that the application does not load its combobox source from the server every time we click on it or use the combobox in our datagridview.

ComboBox sources can be set without using STT. In that case, we also have to take care that the table columns have the right DataGridView column type.

Columns.Add(this, "CustomComboBox", typeof(string), "", "(100)", "", false, 
	System.Data.SqlDbType.NVarChar, true, "Custom cbo",100,new DataGridViewComboBoxColumn());

Bind button to DataGridView

It is easy to add a button to a DataGridView. But binding it to a Form control is another story. If I bind a button to the DataGridView, I would like that the On_Click event raises even if I press the button on the DataGridView. It should also work the other way. If I add e event on the DataGridView button, it should be raised also on the binded form control button. Try the demo application and watch what happens. To have a button click event stored in our DataGridView button, we need to override the OnButtonClick event in the STT table class.

public override void ButtonClick(object sender, DataGridViewCellEventArgs e)
{
    if (DataGridView.Columns[e.ColumnIndex].Name == "Button")
    {
        MessageBox.Show("DataGridView button click", "Button Click");
    }
}

Demo Application

If you open the demo application, you will notice that the whole code for binding 7 different types of controls is very small.

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 STTDemoProject
{
    public partial class Table1Form : Form
    {
        Table1 tblTable1 = new Table1();
        Table2 tblTable2 = new Table2();

        public Table1Form()
        {
            InitializeComponent();

            DataTable tblCustomSource = new DataTable();
            tblCustomSource.Columns.Add("Value", typeof(string));
            tblCustomSource.Columns.Add("Display", typeof(string));
            tblCustomSource.Rows.Add("Item1", "Item1");
            tblCustomSource.Rows.Add("Item2", "Item2");
            tblCustomSource.Rows.Add("Item3", "Item3");

            comboBox2.DataSource = tblCustomSource;
            comboBox2.ValueMember = "Value";
            comboBox2.DisplayMember = "Dislay";

            tblTable1.OnBindingColumnsToControls += tblTable1_OnBindingColumnsToControls;
            tblTable1.BindTableToDataGridView(dgvTable1);
        }

        void tblTable1_OnBindingColumnsToControls(object sender)
        {

            tblTable1.Columns["TextColumn"].BindToControl(textBox1);
            tblTable1.Columns["FloatColumns"].BindToControl(textBox2);
            tblTable1.Columns["DateColumn"].BindToControl(textBox3);
            tblTable1.Columns["CheckColumn"].BindToControl(checkBox1);

            STT.ComboBoxAdapter.EqualiseComboBoxes(comboBox1, tblTable2.ComboBox("PlayerName"));
            tblTable1.Columns["PlayerID"].BindToControl(comboBox1);

            tblTable1.Columns["CustomComboBox"].BindToControl(comboBox2);
            tblTable1.Columns["Button"].BindToControl(button1);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("From Control click", "Button Click");
        }
    }
}

To use the demo application, set the reference to the STT DLL file, start it and setup a proper SQL connection, login with the backup user using the password "123" and have fun. :)

Features

  • Binding a TextBox will also bind the autocomplete settings of the TextBox
  • Also a ComboBox autocomplete setting will be binded to the DataGridView
  • The background color of the DataGridView Cells will be synced with their binded controls
  • Binded buttons will sync their flats style and color with their binded controls
  • Using the STT integrated filter within a ComboBox column will show only available values for the ComboBox

Restrictions

I have not used ComboBoxes whose source is their item list. Because of that, it will not work with such kind of comboboxes. An easy workaround is to just set autocomplete to a textbox. If I find time, the list sourced comboboxes will work too. :)

Points of Interest

In our next articles, we will take a look at the update and error log tools of the STT class library.

History

  • 25.03.2015 - First release