Need a DataGridViewComboBoxColumn

T

Tony Johansson

Hello!

I have a form class called WareHouse. To this class is added
a DataGridView control and some buttons and label controls.
In addition I have a class called FileManger where I handle all things that
has to do with the textfile.
Such as reading and writing.
When I click on the Save button I store the contents of the DataGridView to
a plain textfile and
when the application starts the contents of the textfile is displayed in the
DataGridView.

In the C-tor for WareHouse I do the following
public Lager()
{
InitializeComponent();
_bindingSource.DataSource = _dataTable;
dataGridViewWareHouse.DataSource = _bindingSource;
}

All variables that start with a underscore is instance members.
I also have a form load on the WareHouse which is listed below and all other
methods that is used.
In sequence I do the following in the WareHouse_Load event handler.
1. I create DataColumn in method GetNewColumn()
2. I add all created DataColumn to my DataTable.
3. I fetch all my rows from the textfile. Each row in the textfile contains
five fields.
4. I create DataRow by using the values from the textfile and add these
DataRow to my DataTable
5. At the end of the WareHouse_Load I do some important settings.

Now to my problem. A DataGridView is just a way of display the underlaying
DataTable.
So a DataGridView will just display what is defined in the DataTable
I have a column in the DataTable that is called Type which is of type string
as you can see.
What I want is that this column Type should be of type
DataGridViewComboBoxColumn so there will be
some alternatives to chose from..
Type represent different kind of media product such as book,DV,DVD and
games.

Can somebody explain how this can be done ?

private void WareHouse_Load(object sender, EventArgs e)
{
string[] rowData;
if (dataGridViewWareHouse.RowCount > 0)
_dataTable.Rows.Clear();

if (_dataTable.Columns.Count == 0)
{
_dataTable.Columns.Add(GetNewColumn("Name", "Name", "System.String"));
_dataTable.Columns.Add(GetNewColumn("Price", "Price",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("ProdNr", "ProdNr",
"System.Int32"));
_dataTable.Columns.Add(GetNewColumn("Count", "Count",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Type", "Type", "System.String"));
}
_myList = FileManager.GetAllProducts();
foreach (string line in _myList)
{
rowData = line.Split(new char[] { ',' });
CreateNewRow(rowData);
}
DataView view = new DataView(_dataTable);
view.AllowDelete = false;
dataGridViewWareHouse.Columns["ProdNr"].ReadOnly = true;
_dataTable.AcceptChanges();
}

private DataColumn GetNewColumn(string columnName, string columnCaption,
string columnType)
{
DataColumn dataColumn = new DataColumn(columnName,
System.Type.GetType(columnType));
if (columnName == "ProdNr")
{
dataColumn.AutoIncrement = true;
dataColumn.AutoIncrementSeed = 1;
}
dataColumn.Caption = columnCaption;
return dataColumn;
}


private void CreateNewRow(string[] rowData)
{
DataRow dataRow = _dataTable.NewRow();
int i = 0;

foreach (string fieldData in rowData)
dataRow[i++] = fieldData;

_dataTable.Rows.Add(dataRow);
}

//Tony
 
C

Cor Ligthert[MVP]

I think there is enough here

http://msdn.microsoft.com/en-us/library/bxt3k60s(VS.85).aspx

Cor

Tony Johansson said:
Hello!

I have a form class called WareHouse. To this class is added
a DataGridView control and some buttons and label controls.
In addition I have a class called FileManger where I handle all things
that has to do with the textfile.
Such as reading and writing.
When I click on the Save button I store the contents of the DataGridView
to a plain textfile and
when the application starts the contents of the textfile is displayed in
the DataGridView.

In the C-tor for WareHouse I do the following
public Lager()
{
InitializeComponent();
_bindingSource.DataSource = _dataTable;
dataGridViewWareHouse.DataSource = _bindingSource;
}

All variables that start with a underscore is instance members.
I also have a form load on the WareHouse which is listed below and all
other methods that is used.
In sequence I do the following in the WareHouse_Load event handler.
1. I create DataColumn in method GetNewColumn()
2. I add all created DataColumn to my DataTable.
3. I fetch all my rows from the textfile. Each row in the textfile
contains five fields.
4. I create DataRow by using the values from the textfile and add these
DataRow to my DataTable
5. At the end of the WareHouse_Load I do some important settings.

Now to my problem. A DataGridView is just a way of display the underlaying
DataTable.
So a DataGridView will just display what is defined in the DataTable
I have a column in the DataTable that is called Type which is of type
string as you can see.
What I want is that this column Type should be of type
DataGridViewComboBoxColumn so there will be
some alternatives to chose from..
Type represent different kind of media product such as book,DV,DVD and
games.

Can somebody explain how this can be done ?

private void WareHouse_Load(object sender, EventArgs e)
{
string[] rowData;
if (dataGridViewWareHouse.RowCount > 0)
_dataTable.Rows.Clear();

if (_dataTable.Columns.Count == 0)
{
_dataTable.Columns.Add(GetNewColumn("Name", "Name",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Price", "Price",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("ProdNr", "ProdNr",
"System.Int32"));
_dataTable.Columns.Add(GetNewColumn("Count", "Count",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Type", "Type",
"System.String"));
}
_myList = FileManager.GetAllProducts();
foreach (string line in _myList)
{
rowData = line.Split(new char[] { ',' });
CreateNewRow(rowData);
}
DataView view = new DataView(_dataTable);
view.AllowDelete = false;
dataGridViewWareHouse.Columns["ProdNr"].ReadOnly = true;
_dataTable.AcceptChanges();
}

private DataColumn GetNewColumn(string columnName, string columnCaption,
string columnType)
{
DataColumn dataColumn = new DataColumn(columnName,
System.Type.GetType(columnType));
if (columnName == "ProdNr")
{
dataColumn.AutoIncrement = true;
dataColumn.AutoIncrementSeed = 1;
}
dataColumn.Caption = columnCaption;
return dataColumn;
}


private void CreateNewRow(string[] rowData)
{
DataRow dataRow = _dataTable.NewRow();
int i = 0;

foreach (string fieldData in rowData)
dataRow[i++] = fieldData;

_dataTable.Rows.Add(dataRow);
}

//Tony
 
T

Tony Johansson

Hello"

I have looked at the code.
All my DataColumn has been added to the DataTable and the DataRow is added
to the DataTable.
In the example code they add the DataGridViewComboBoxColumn to the
DataGridView.
In my code I never add anything to the DataGridView

So I have tried two different things they are named 1 and 2 below. Both of
the modification is done in the Load event method.
Below is the complete code that I tried. As you can see I comment out this
row
_dataTable.Columns.Add(GetNewColumn("Typ", "Typ", "System.String"));
because I instead want to get a DataGridViewComBoxColumn.
So in this first test I did just that add my DataGridViewComboBoxColumn to
the DataGridView.
The test failed miserably because when method CreateNewRow is trying to
access column 4 it will throw
an IndexOutOfrangeException with text cannot find column 4.
In test number 2 you have the complete code for the Load below where the
modification has been done.
Even this test failed. This test was little better then the first because
the DataGridComboBoxColumn
was shown so I could select values from it. But OnSave when looping and
fetching the values from the DataTable
the ComboBoxColumn was not there. So the value for DataGridComboBoxColumn
only exist in the DataGridView.
1.
private void CreateNewRow(string[] rowData)
{
DataRow dataRow = _dataTable.NewRow();
int i = 0;

foreach (string fieldData in rowData)
dataRow[i++] = fieldData;

_dataTable.Rows.Add(dataRow);
}
private void WareHouse_Load(object sender, EventArgs e)
{
string[] rowData;
if (dataGridViewWareHouse.RowCount > 0)
_dataTable.Rows.Clear();

if (_dataTable.Columns.Count == 0)
{
_dataTable.Columns.Add(GetNewColumn("Namn", "Namn",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Pris", "Pris",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("ProdNr", "ProdNr",
"System.Int32"));
_dataTable.Columns.Add(GetNewColumn("Antal", "Antal",
"System.String"));
// _dataTable.Columns.Add(GetNewColumn("Typ", "Typ",
"System.String"));
}

DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.HeaderText = "Typ";
cb.MaxDropDownItems = 3;
cb.Items.AddRange("BOK", "DV", "DVD", "GAME");
dataGridViewWareHouse.Columns.Add(cb);

_myList = FileManager.GetAllProducts();

foreach (string line in _myList)
{
rowData = line.Split(new char[] { ',' });
CreateNewRow(rowData);
}

DataView view = new DataView(_dataTable);
view.AllowDelete = false;

dataGridViewWareHouse.Columns["ProdNr"].ReadOnly = true;
_dataTable.AcceptChanges();
}
2.
private void Lager_Load(object sender, EventArgs e)
{
string[] rowData;
if (dgLager.RowCount > 0)
_dataTable.Rows.Clear();

if (_dataTable.Columns.Count == 0)
{
_dataTable.Columns.Add(GetNewColumn("Namn", "Namn",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Pris", "Pris",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("ProdNr", "ProdNr",
"System.Int32"));
_dataTable.Columns.Add(GetNewColumn("Antal", "Antal",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Typ", "Typ",
"System.String"));
}

DataGridViewComboBoxColumn cb = new DataGridViewComboBoxColumn();
cb.HeaderText = "Typ";
cb.MaxDropDownItems = 3;
cb.Items.AddRange("BOK", "DV", "DVD", "GAME");
dgLager.Columns.Remove("Typ");
dgLager.Columns.Add(cb);

_myList = FileManager.GetAllProducts();

foreach (string line in _myList)
{
rowData = line.Split(new char[] { ',' });
CreateNewRow(rowData);
}

DataView view = new DataView(_dataTable);
view.AllowDelete = false;

dgLager.Columns["ProdNr"].ReadOnly = true;
_dataTable.AcceptChanges();
}

I just can't understand why it's not possibly to add a
DataGridViewComboBoxColumn to a DataTable
because that would solve my problem.

It might work if I both read the DataTable as I use now and also read the
DataGridView to be able to get the Type value
but this would give a very strange and bad solution.

So if anyone doesn't have any good solution I think I keep the good old
string for the type column.
This might be a bug in .net.

//Tony


Cor Ligthert said:
I think there is enough here

http://msdn.microsoft.com/en-us/library/bxt3k60s(VS.85).aspx

Cor

Tony Johansson said:
Hello!

I have a form class called WareHouse. To this class is added
a DataGridView control and some buttons and label controls.
In addition I have a class called FileManger where I handle all things
that has to do with the textfile.
Such as reading and writing.
When I click on the Save button I store the contents of the DataGridView
to a plain textfile and
when the application starts the contents of the textfile is displayed in
the DataGridView.

In the C-tor for WareHouse I do the following
public Lager()
{
InitializeComponent();
_bindingSource.DataSource = _dataTable;
dataGridViewWareHouse.DataSource = _bindingSource;
}

All variables that start with a underscore is instance members.
I also have a form load on the WareHouse which is listed below and all
other methods that is used.
In sequence I do the following in the WareHouse_Load event handler.
1. I create DataColumn in method GetNewColumn()
2. I add all created DataColumn to my DataTable.
3. I fetch all my rows from the textfile. Each row in the textfile
contains five fields.
4. I create DataRow by using the values from the textfile and add these
DataRow to my DataTable
5. At the end of the WareHouse_Load I do some important settings.

Now to my problem. A DataGridView is just a way of display the
underlaying DataTable.
So a DataGridView will just display what is defined in the DataTable
I have a column in the DataTable that is called Type which is of type
string as you can see.
What I want is that this column Type should be of type
DataGridViewComboBoxColumn so there will be
some alternatives to chose from..
Type represent different kind of media product such as book,DV,DVD and
games.

Can somebody explain how this can be done ?

private void WareHouse_Load(object sender, EventArgs e)
{
string[] rowData;
if (dataGridViewWareHouse.RowCount > 0)
_dataTable.Rows.Clear();

if (_dataTable.Columns.Count == 0)
{
_dataTable.Columns.Add(GetNewColumn("Name", "Name",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Price", "Price",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("ProdNr", "ProdNr",
"System.Int32"));
_dataTable.Columns.Add(GetNewColumn("Count", "Count",
"System.String"));
_dataTable.Columns.Add(GetNewColumn("Type", "Type",
"System.String"));
}
_myList = FileManager.GetAllProducts();
foreach (string line in _myList)
{
rowData = line.Split(new char[] { ',' });
CreateNewRow(rowData);
}
DataView view = new DataView(_dataTable);
view.AllowDelete = false;
dataGridViewWareHouse.Columns["ProdNr"].ReadOnly = true;
_dataTable.AcceptChanges();
}

private DataColumn GetNewColumn(string columnName, string columnCaption,
string columnType)
{
DataColumn dataColumn = new DataColumn(columnName,
System.Type.GetType(columnType));
if (columnName == "ProdNr")
{
dataColumn.AutoIncrement = true;
dataColumn.AutoIncrementSeed = 1;
}
dataColumn.Caption = columnCaption;
return dataColumn;
}


private void CreateNewRow(string[] rowData)
{
DataRow dataRow = _dataTable.NewRow();
int i = 0;

foreach (string fieldData in rowData)
dataRow[i++] = fieldData;

_dataTable.Rows.Add(dataRow);
}

//Tony
 
C

Cor Ligthert[MVP]

Tony,

(I made a sample for you, I tried to convert a very old VB sample but it was
more work than I expected )

That seems to me easier then that I have to use code because I don't have
the input.

\\\
DataTable dt = new DataTable();
dt.Columns.Add("ID");
dt.Columns.Add("Name");
dt.Columns.Add("State");
dt.LoadDataRow(new Object[] { "1", "Ken Tucker", "Florida" }, true);
dt.LoadDataRow(new Object[] { "2", "Cor Ligthert", "Netherlands" }, true);
dt.LoadDataRow(new Object[] { "3", "Armin Zingler", "Germany" }, true);
dt.LoadDataRow(new Object[] { "4", "Herfried K. Wagner", "Austria" }, true);
BindingSource bs = new BindingSource();
bs.DataSource = dt;
dataGridView1.DataSource = bs;
dataGridView1.Columns.Remove("State");
DataGridViewComboBoxColumn dgvCombo = new DataGridViewComboBoxColumn();
dgvCombo.DataPropertyName = "State";
dgvCombo.Items.Add("Florida");
dgvCombo.Items.Add("Netherlands");
dgvCombo.Items.Add("United Kingdom");
dgvCombo.Items.Add("Germany");
dgvCombo.Items.Add("Austria");
dgvCombo.Items.Add("Texas");
dgvCombo.HeaderText = "State";
dataGridView1.Columns.Add(dgvCombo);
///

I hope this helps,

Cor
 
T

Tony Johansson

Hello!

The main problem is that I'm not allowed to read the DataTable to get the
value for
DataGridViewComboBoxColumn because the DataGridViewComboBoxColumn
is not located in the DataTable but is instead located in the DataGridView.
This will cause trouble because I have no rowState and I have to read two
different controls.
So I think I skip this DataGridViewComboBoxColumn but use a string object
that I can store in the DataTable.
I will have to validate that the value in the Type is a correct input

//Tony
 
T

Tony Johansson

Hello!

I works now I just forgot the DataPropertyName on the
DataGridViewComboBoxColumn
Many thanks!!

//Tony
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top