Introduction
So why did I make this control? Lots of software development companies produce software for small businesses, and lots of these products are called ERPs. These applications use as many databases as possible, believe me, I know an ERP project that uses such a control in almost every form, and it has two hundred to three hundred forms. Why use this? Because it allows you to bind a data source to a combo box, bind in the meaning that if the data source changes, the control items change too. And when an item is selected, a data row can be obtained from that item, and finally the data row's primary keys.
About the Control
Except what I mentioned before, this control has an item format property, which is used to format the items based on the data row.
Let's say we have a table with lots of stuff, with an employee name, age, and salary... We want to show in the control its items in the following way: "Elvis Preasy, income 200$
". The row format does this thing by passing to it the column indexes surrounded by <>
(like HTML tags). So in the previous example, the format string
would be "<1> <2>, income <3>$
", assuming that column 1 and 2 define the employee name and column 3 his income.
And this is not all, the control supports row filtering, actually it doesn't filter its items, it recreates new ones based on the filter. The filter is like the ADO.NET data view row filter.
The last drop is made by the possibility to get the row corresponding to an item (the selected item), and its primary keys.
How All This Is Made?
All this is made by holding into the control the data source (some want to know what is the data source), the corresponding table that gives us the items, a data view for the filtering, and some entities used for the data rows association (means that a row has an item attached to it).
private ArrayList _bindedItems = new ArrayList();
private object _dataSource = null;
private DataTable _controlDataTable = null;
private DataView _dataView = new DataView();
private string _dataMember = "";
private string _displayFormat = "";
private string _rowFilter = "";
All the operations are made at the calls to the control properties:
public string BindedDataFormat [...]
public string BindedDataFiler [...]
public object BindedDataSource [...]
public string BindedDataMember [...]
public DataRow SelectedRow [...]
There are some inner private
functions that process all the data and a static
procedure that returns the primary keys of a data row in an object vector:
public static object[] GetRowPK(DataRow row)
{
ArrayList pks = new ArrayList();
DataTable dt = row.Table;
foreach(DataColumn dc in dt.PrimaryKey)
{
pks.Add(row[dc]);
}
return pks.ToArray();
}
The DropDownStyle
property of the control is read only to avoid ambiguity, and a lots of headaches.
To make this control bind to the data source, I added the data table that gives all the rows we need, a handling procedure at row changed and row deleted. At a data source change, the old table's handling methods are removed.
private DataRowChangeEventHandler _rowChanged;
private void SetControlData()
{
if(_controlDataTable == null)
return;
_controlDataTable.RowChanged += _rowChanged;
_controlDataTable.RowDeleted += _rowChanged;
private void ClearControlData()
{
if(_controlDataTable != null)
{
_controlDataTable.RowChanged -= _rowChanged;
_controlDataTable.RowDeleted -= _rowChanged;
}
In a form, it is very easy to use the control..., just attach a format on it (or it will not display anything) and set its data source:
comboBox1.BindedDataFormat = "<id> <0>, <name> <1>, <surname> <2> ";
comboBox1.BindedDataSource = dataTable;
Instead of Ending
I hope somebody finds this control useful, for I already found it...