G'day,

After doing much searching and pinching bits of ideas from here there and
everywhere I came up with a fairly 'clean' solution of including a comboBox
into a dataGrid column.

You can download a fully working C# sample with the Northwind.mdb here:
www.insightgis.com.au/web/stuff/DataGridCombo.zip


The whole thing works like a charm, but I have a slight problem:

When the user navigates to the new row, fills in some data, subsequent new
rows are not displayed! Meaning you can only add just ONE record! It seems
as if the DataGrid is not detecting changes made by the ComboBox, but if you
physically type some value in through the keyboard then its's happy, it
displays a subsequent new row.

Any ideas what might be causing that?

Here's the code if you don't feel like downloading the ZIP:

(Note, dataAdapers and dataGridColumnStyles have have been configured
through the IDE so you'll need the full source code to make this work)

--------------------------------------------------------------

private void Form1_Load(object sender, System.EventArgs e)
{
dbConnection.ConnectionString = @"provider=Microsoft.Jet.OLEDB.4.0; data
source=C:\NWIND.MDB";

// Load the ORDERS and CUSTOMERS tables from the Northwind demo database.
myDataSet = new DataSet();
daOrders.Fill(myDataSet, "ORDERS");
daCustomers.Fill(myDataSet, "CUSTOMERS");
myDataGrid.DataSource = myDataSet.Tables["ORDERS"];

// Create the comboBox to be used by the 'Customer Name' column in the
grid.
comboCustomers = new ComboBox();
comboCustomers.SelectionChangeCommitted += new
EventHandler(comboCustomers_SelectionChangeCommitted);
comboCustomers.Top = -4; // position the combo so that it's text is
aligned with the cell's text.
comboCustomers.Left = -4;
comboCustomers.DropDownWidth = 150;
comboCustomers.Cursor = Cursors.Arrow;
comboCustomers.DropDownStyle = ComboBoxStyle.DropDownList;

// Set the datasource for the comboBox
comboCustomers.DataSource = myDataSet.Tables["CUSTOMERS"];
comboCustomers.DisplayMember = "CompanyName";
comboCustomers.ValueMember = "CustomerId";

// Databind the combBox to the ORDERS table.
comboCustomers.DataBindings.Add("SelectedValue",
myDataSet.Tables["ORDERS"], "CustomerId");

// Assign the new comboBox to the dataGrid column.
// ... NOTE, I've defined dataGrid column styles through the IDE.
colCustomer.TextBox.Controls.Add(comboCustomers);

// Assign event handler when the user enters the 'Customer Name' cell.
colCustomer.TextBox.Enter += new EventHandler(colCustomer_Enter);
}

private void comboCustomers_SelectionChangeCommitted(object sender,
EventArgs e)
{
// Set the text in the 'Customer Name' datagrid cell (underneath the
comboBox).
myDataGrid[myDataGrid.CurrentCell] = comboCustomers.Text;
}

private void colCustomer_Enter(object sender, EventArgs e)
{
// This event handler is triggered when the user clicks on the 'Customer
Name' cell
// The purpose here is to simply display the comboBox.

if (myDataGrid.ReadOnly)
{
// Don't display the comboBox if dataGrid is readOnly!
comboCustomers.Visible = false;
return;
}

comboCustomers.Width = colCustomer.Width + 3;
comboCustomers.Visible = true;
comboCustomers.BringToFront();
}

--------------------------------------------------------------

Cheers,
PeterZ

Re: DataGrid with ComboBox - won't allow me to add more than one by Sijin

Sijin
Fri Aug 20 08:58:19 CDT 2004

Haven't looked through the code, but make sure you call BeginEdit()
method, when editing starts otherwise you will only get one new row.

Sijin Joseph
http://www.indiangeek.net
http://weblogs.asp.net/sjoseph



PeterZ wrote:
> G'day,
>
> After doing much searching and pinching bits of ideas from here there and
> everywhere I came up with a fairly 'clean' solution of including a comboBox
> into a dataGrid column.
>
> You can download a fully working C# sample with the Northwind.mdb here:
> www.insightgis.com.au/web/stuff/DataGridCombo.zip
>
>
> The whole thing works like a charm, but I have a slight problem:
>
> When the user navigates to the new row, fills in some data, subsequent new
> rows are not displayed! Meaning you can only add just ONE record! It seems
> as if the DataGrid is not detecting changes made by the ComboBox, but if you
> physically type some value in through the keyboard then its's happy, it
> displays a subsequent new row.
>
> Any ideas what might be causing that?
>
> Here's the code if you don't feel like downloading the ZIP:
>
> (Note, dataAdapers and dataGridColumnStyles have have been configured
> through the IDE so you'll need the full source code to make this work)
>
> --------------------------------------------------------------
>
> private void Form1_Load(object sender, System.EventArgs e)
> {
> dbConnection.ConnectionString = @"provider=Microsoft.Jet.OLEDB.4.0; data
> source=C:\NWIND.MDB";
>
> // Load the ORDERS and CUSTOMERS tables from the Northwind demo database.
> myDataSet = new DataSet();
> daOrders.Fill(myDataSet, "ORDERS");
> daCustomers.Fill(myDataSet, "CUSTOMERS");
> myDataGrid.DataSource = myDataSet.Tables["ORDERS"];
>
> // Create the comboBox to be used by the 'Customer Name' column in the
> grid.
> comboCustomers = new ComboBox();
> comboCustomers.SelectionChangeCommitted += new
> EventHandler(comboCustomers_SelectionChangeCommitted);
> comboCustomers.Top = -4; // position the combo so that it's text is
> aligned with the cell's text.
> comboCustomers.Left = -4;
> comboCustomers.DropDownWidth = 150;
> comboCustomers.Cursor = Cursors.Arrow;
> comboCustomers.DropDownStyle = ComboBoxStyle.DropDownList;
>
> // Set the datasource for the comboBox
> comboCustomers.DataSource = myDataSet.Tables["CUSTOMERS"];
> comboCustomers.DisplayMember = "CompanyName";
> comboCustomers.ValueMember = "CustomerId";
>
> // Databind the combBox to the ORDERS table.
> comboCustomers.DataBindings.Add("SelectedValue",
> myDataSet.Tables["ORDERS"], "CustomerId");
>
> // Assign the new comboBox to the dataGrid column.
> // ... NOTE, I've defined dataGrid column styles through the IDE.
> colCustomer.TextBox.Controls.Add(comboCustomers);
>
> // Assign event handler when the user enters the 'Customer Name' cell.
> colCustomer.TextBox.Enter += new EventHandler(colCustomer_Enter);
> }
>
> private void comboCustomers_SelectionChangeCommitted(object sender,
> EventArgs e)
> {
> // Set the text in the 'Customer Name' datagrid cell (underneath the
> comboBox).
> myDataGrid[myDataGrid.CurrentCell] = comboCustomers.Text;
> }
>
> private void colCustomer_Enter(object sender, EventArgs e)
> {
> // This event handler is triggered when the user clicks on the 'Customer
> Name' cell
> // The purpose here is to simply display the comboBox.
>
> if (myDataGrid.ReadOnly)
> {
> // Don't display the comboBox if dataGrid is readOnly!
> comboCustomers.Visible = false;
> return;
> }
>
> comboCustomers.Width = colCustomer.Width + 3;
> comboCustomers.Visible = true;
> comboCustomers.BringToFront();
> }
>
> --------------------------------------------------------------
>
> Cheers,
> PeterZ
>
>

Re: DataGrid with ComboBox - won't allow me to add more than one new row??? by PeterZ

PeterZ
Sun Aug 22 19:31:33 CDT 2004

Hi Sijin,

Tried including BeginEdit() but I still don't get additional new rows.

This is the code when I commit the selection in the comboBox:


private void comboCustomers_SelectionChangeCommitted(object sender,
EventArgs e)
{
// Set the text in the 'Customer Name' datagrid cell (underneath the
comboBox).

int colNum = myDataGrid.CurrentCell.ColumnNumber;
int rowNum = myDataGrid.CurrentCell.RowNumber;

myDataGrid.BeginEdit(colCustomer, rowNum);
myDataGrid[myDataGrid.CurrentCell] = comboCustomers.Text;
myDataGrid.EndEdit(colCustomer, rowNum, false);
}


A new row doesn't appear until I physically type in a value in one of the
other columns.



"Sijin Joseph" <sijinNOSPAMdotnet@hotmail.com> wrote in message
news:OYO4i3rhEHA.2848@TK2MSFTNGP10.phx.gbl...
> Haven't looked through the code, but make sure you call BeginEdit()
> method, when editing starts otherwise you will only get one new row.
>
> Sijin Joseph
> http://www.indiangeek.net
> http://weblogs.asp.net/sjoseph
>
>
>
> PeterZ wrote:
> > G'day,
> >
> > After doing much searching and pinching bits of ideas from here there
and
> > everywhere I came up with a fairly 'clean' solution of including a
comboBox
> > into a dataGrid column.
> >
> > You can download a fully working C# sample with the Northwind.mdb here:
> > www.insightgis.com.au/web/stuff/DataGridCombo.zip
> >
> >
> > The whole thing works like a charm, but I have a slight problem:
> >
> > When the user navigates to the new row, fills in some data, subsequent
new
> > rows are not displayed! Meaning you can only add just ONE record! It
seems
> > as if the DataGrid is not detecting changes made by the ComboBox, but if
you
> > physically type some value in through the keyboard then its's happy, it
> > displays a subsequent new row.
> >
> > Any ideas what might be causing that?
> >
> > Here's the code if you don't feel like downloading the ZIP:
> >
> > (Note, dataAdapers and dataGridColumnStyles have have been configured
> > through the IDE so you'll need the full source code to make this work)
> >
> > --------------------------------------------------------------
> >
> > private void Form1_Load(object sender, System.EventArgs e)
> > {
> > dbConnection.ConnectionString = @"provider=Microsoft.Jet.OLEDB.4.0;
data
> > source=C:\NWIND.MDB";
> >
> > // Load the ORDERS and CUSTOMERS tables from the Northwind demo
database.
> > myDataSet = new DataSet();
> > daOrders.Fill(myDataSet, "ORDERS");
> > daCustomers.Fill(myDataSet, "CUSTOMERS");
> > myDataGrid.DataSource = myDataSet.Tables["ORDERS"];
> >
> > // Create the comboBox to be used by the 'Customer Name' column in the
> > grid.
> > comboCustomers = new ComboBox();
> > comboCustomers.SelectionChangeCommitted += new
> > EventHandler(comboCustomers_SelectionChangeCommitted);
> > comboCustomers.Top = -4; // position the combo so that it's text is
> > aligned with the cell's text.
> > comboCustomers.Left = -4;
> > comboCustomers.DropDownWidth = 150;
> > comboCustomers.Cursor = Cursors.Arrow;
> > comboCustomers.DropDownStyle = ComboBoxStyle.DropDownList;
> >
> > // Set the datasource for the comboBox
> > comboCustomers.DataSource = myDataSet.Tables["CUSTOMERS"];
> > comboCustomers.DisplayMember = "CompanyName";
> > comboCustomers.ValueMember = "CustomerId";
> >
> > // Databind the combBox to the ORDERS table.
> > comboCustomers.DataBindings.Add("SelectedValue",
> > myDataSet.Tables["ORDERS"], "CustomerId");
> >
> > // Assign the new comboBox to the dataGrid column.
> > // ... NOTE, I've defined dataGrid column styles through the IDE.
> > colCustomer.TextBox.Controls.Add(comboCustomers);
> >
> > // Assign event handler when the user enters the 'Customer Name' cell.
> > colCustomer.TextBox.Enter += new EventHandler(colCustomer_Enter);
> > }
> >
> > private void comboCustomers_SelectionChangeCommitted(object sender,
> > EventArgs e)
> > {
> > // Set the text in the 'Customer Name' datagrid cell (underneath the
> > comboBox).
> > myDataGrid[myDataGrid.CurrentCell] = comboCustomers.Text;
> > }
> >
> > private void colCustomer_Enter(object sender, EventArgs e)
> > {
> > // This event handler is triggered when the user clicks on the
'Customer
> > Name' cell
> > // The purpose here is to simply display the comboBox.
> >
> > if (myDataGrid.ReadOnly)
> > {
> > // Don't display the comboBox if dataGrid is readOnly!
> > comboCustomers.Visible = false;
> > return;
> > }
> >
> > comboCustomers.Width = colCustomer.Width + 3;
> > comboCustomers.Visible = true;
> > comboCustomers.BringToFront();
> > }
> >
> > --------------------------------------------------------------
> >
> > Cheers,
> > PeterZ
> >
> >



Re: DataGrid with ComboBox - won't allow me to add more than one by Sijin

Sijin
Mon Aug 23 08:00:10 CDT 2004

This is a multi-part message in MIME format.
--------------020106030200020600040701
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Add this code to the comboBox TextChanged event handler, where isEditing
is a bool variable that keeps track of wether the combo is editing
or not. I am also attaching a class that i wrote that creates a custom
combo box column based on the genghis autocomplete combo box control.

private void combo_TextChanged(object sender,EventArgs e)
{
if(!_isEditing)
{
_isEditing = true;
base.ColumnStartedEditing(_combo);
}
}

Sijin Joseph
http://www.indiangeek.net
http://weblogs.asp.net/sjoseph



PeterZ wrote:
> Hi Sijin,
>
> Tried including BeginEdit() but I still don't get additional new rows.
>
> This is the code when I commit the selection in the comboBox:
>
>
> private void comboCustomers_SelectionChangeCommitted(object sender,
> EventArgs e)
> {
> // Set the text in the 'Customer Name' datagrid cell (underneath the
> comboBox).
>
> int colNum = myDataGrid.CurrentCell.ColumnNumber;
> int rowNum = myDataGrid.CurrentCell.RowNumber;
>
> myDataGrid.BeginEdit(colCustomer, rowNum);
> myDataGrid[myDataGrid.CurrentCell] = comboCustomers.Text;
> myDataGrid.EndEdit(colCustomer, rowNum, false);
> }
>
>
> A new row doesn't appear until I physically type in a value in one of the
> other columns.
>
>
>
> "Sijin Joseph" <sijinNOSPAMdotnet@hotmail.com> wrote in message
> news:OYO4i3rhEHA.2848@TK2MSFTNGP10.phx.gbl...
>
>>Haven't looked through the code, but make sure you call BeginEdit()
>>method, when editing starts otherwise you will only get one new row.
>>
>>Sijin Joseph
>>http://www.indiangeek.net
>>http://weblogs.asp.net/sjoseph
>>
>>
>>
>>PeterZ wrote:
>>
>>>G'day,
>>>
>>>After doing much searching and pinching bits of ideas from here there
>
> and
>
>>>everywhere I came up with a fairly 'clean' solution of including a
>
> comboBox
>
>>>into a dataGrid column.
>>>
>>>You can download a fully working C# sample with the Northwind.mdb here:
>>>www.insightgis.com.au/web/stuff/DataGridCombo.zip
>>>
>>>
>>>The whole thing works like a charm, but I have a slight problem:
>>>
>>>When the user navigates to the new row, fills in some data, subsequent
>
> new
>
>>>rows are not displayed! Meaning you can only add just ONE record! It
>
> seems
>
>>>as if the DataGrid is not detecting changes made by the ComboBox, but if
>
> you
>
>>>physically type some value in through the keyboard then its's happy, it
>>>displays a subsequent new row.
>>>
>>>Any ideas what might be causing that?
>>>
>>>Here's the code if you don't feel like downloading the ZIP:
>>>
>>>(Note, dataAdapers and dataGridColumnStyles have have been configured
>>>through the IDE so you'll need the full source code to make this work)
>>>
>>>--------------------------------------------------------------
>>>
>>>private void Form1_Load(object sender, System.EventArgs e)
>>>{
>>> dbConnection.ConnectionString = @"provider=Microsoft.Jet.OLEDB.4.0;
>
> data
>
>>>source=C:\NWIND.MDB";
>>>
>>> // Load the ORDERS and CUSTOMERS tables from the Northwind demo
>
> database.
>
>>> myDataSet = new DataSet();
>>> daOrders.Fill(myDataSet, "ORDERS");
>>> daCustomers.Fill(myDataSet, "CUSTOMERS");
>>> myDataGrid.DataSource = myDataSet.Tables["ORDERS"];
>>>
>>> // Create the comboBox to be used by the 'Customer Name' column in the
>>>grid.
>>> comboCustomers = new ComboBox();
>>> comboCustomers.SelectionChangeCommitted += new
>>>EventHandler(comboCustomers_SelectionChangeCommitted);
>>> comboCustomers.Top = -4; // position the combo so that it's text is
>>>aligned with the cell's text.
>>> comboCustomers.Left = -4;
>>> comboCustomers.DropDownWidth = 150;
>>> comboCustomers.Cursor = Cursors.Arrow;
>>> comboCustomers.DropDownStyle = ComboBoxStyle.DropDownList;
>>>
>>> // Set the datasource for the comboBox
>>> comboCustomers.DataSource = myDataSet.Tables["CUSTOMERS"];
>>> comboCustomers.DisplayMember = "CompanyName";
>>> comboCustomers.ValueMember = "CustomerId";
>>>
>>> // Databind the combBox to the ORDERS table.
>>> comboCustomers.DataBindings.Add("SelectedValue",
>>>myDataSet.Tables["ORDERS"], "CustomerId");
>>>
>>> // Assign the new comboBox to the dataGrid column.
>>> // ... NOTE, I've defined dataGrid column styles through the IDE.
>>> colCustomer.TextBox.Controls.Add(comboCustomers);
>>>
>>> // Assign event handler when the user enters the 'Customer Name' cell.
>>> colCustomer.TextBox.Enter += new EventHandler(colCustomer_Enter);
>>>}
>>>
>>>private void comboCustomers_SelectionChangeCommitted(object sender,
>>>EventArgs e)
>>>{
>>> // Set the text in the 'Customer Name' datagrid cell (underneath the
>>>comboBox).
>>> myDataGrid[myDataGrid.CurrentCell] = comboCustomers.Text;
>>>}
>>>
>>>private void colCustomer_Enter(object sender, EventArgs e)
>>>{
>>> // This event handler is triggered when the user clicks on the
>
> 'Customer
>
>>>Name' cell
>>> // The purpose here is to simply display the comboBox.
>>>
>>> if (myDataGrid.ReadOnly)
>>> {
>>> // Don't display the comboBox if dataGrid is readOnly!
>>> comboCustomers.Visible = false;
>>> return;
>>> }
>>>
>>> comboCustomers.Width = colCustomer.Width + 3;
>>> comboCustomers.Visible = true;
>>> comboCustomers.BringToFront();
>>>}
>>>
>>>--------------------------------------------------------------
>>>
>>>Cheers,
>>>PeterZ
>>>
>>>
>
>
>

--------------020106030200020600040701
Content-Type: text/plain;
name="DataGridAutoCompleteComboColumn.cs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="DataGridAutoCompleteComboColumn.cs"

using System;
using System.Drawing;
using System.Windows;
using System.Windows.Forms;

using Genghis.Windows.Forms;

namespace CHF.Costing.CustomColumnStyles
{
/// <summary>
///
/// </summary>
public class DataGridAutoCompleteComboColumn : DataGridColumnStyle
{
#region Fields
private bool _isEditing = false;
private DataGridCompletionCombo _combo = new DataGridCompletionCombo();
private string oldValue = null;
private const int xMargin = 1;
private const int yMargin = 2;
private DataGrid _grid = null;
#endregion

#region Ctor
public DataGridAutoCompleteComboColumn()
{
_combo.Visible = false;
}
#endregion

#region Public Methods
public void SetItems(object[] items)
{
_combo.Items.AddRange(items);
}
#endregion

#region DataGridColumnStyle Overrides
protected override void Abort(int rowNum)
{
this.EndEdit();
this.RollBack();
}

protected override bool Commit(CurrencyManager dataSource, int rowNum)
{
if (!_isEditing)
{
this.EndEdit();
return true;
}

try
{
object value = this._combo.Text;
base.SetColumnValueAtRow(dataSource, rowNum, value);
}
catch(Exception)
{
Abort(rowNum);
return false;
}
this.EndEdit();
return true;
}

protected override void Edit(CurrencyManager source, int rowNum, System.Drawing.Rectangle bounds, bool readOnly, string instantText, bool cellIsVisible)
{
//If this column is readonly, then don't bother showing the combo
if(base.ReadOnly)
return;

this._combo.Text = this.GetText(base.GetColumnValueAtRow(source, rowNum));

if (cellIsVisible)
{
this._combo.Bounds = bounds;
this._combo.Visible = true;
_combo.TextChanged += new EventHandler(combo_TextChanged);
}
else
{
this._combo.Bounds = bounds;
this._combo.Visible = false;
}

this._combo.RightToLeft = base.DataGridTableStyle.DataGrid.RightToLeft;
this.oldValue = this._combo.Text;
this._combo.Focus();
this._combo.Select(0,_combo.Text.Length);

if (this._combo.Visible)
{
base.DataGridTableStyle.DataGrid.Invalidate(bounds);
}
}

protected override int GetMinimumHeight()
{
return _combo.PreferredHeight + yMargin;
}

protected override int GetPreferredHeight(System.Drawing.Graphics g, object value)
{
return _combo.PreferredHeight + yMargin;
}

protected override System.Drawing.Size GetPreferredSize(System.Drawing.Graphics g, object value)
{
return new Size(0,0);
}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum)
{
Paint(g,bounds,source,rowNum,false);
}

protected override void Paint(System.Drawing.Graphics g, System.Drawing.Rectangle bounds, CurrencyManager source, int rowNum, bool alignToRight)
{
string text = GetText(this.GetColumnValueAtRow( source, rowNum ));
Brush bgBrush = null;
Brush fgBrush = null;
if(_grid.IsSelected(rowNum))
{
bgBrush = new SolidBrush( this.DataGridTableStyle.SelectionBackColor );
fgBrush= new SolidBrush( this.DataGridTableStyle.SelectionForeColor );
}
else
{
bgBrush = new SolidBrush( this.DataGridTableStyle.BackColor );
fgBrush= new SolidBrush( this.DataGridTableStyle.ForeColor );
}

g.FillRectangle( bgBrush, bounds );
g.DrawString( text, this.DataGridTableStyle.DataGrid.Font, fgBrush, bounds );
}

protected override void SetDataGridInColumn(DataGrid value)
{
base.SetDataGridInColumn(value);
if (this._combo.Parent != null)
{
this._combo.Parent.Controls.Remove(this._combo);

}

if (value != null)
{
value.Controls.Add(this._combo);

}

_grid = value;
}

protected override void ConcedeFocus()
{
HideCombo();

}
#endregion

#region Helper Methods
protected string GetText(object value)
{
if(value == null)
return this.NullText;
else
return value.ToString();
}

protected void RollBack()
{
this._combo.Text = this.oldValue;
}

protected void HideCombo()
{
this._combo.Visible = false;
}

protected void EndEdit()
{
_combo.TextChanged -= new EventHandler(combo_TextChanged);
HideCombo();
_isEditing = false;
base.Invalidate();
}
#endregion

#region ComboBox Event Handlers
private void combo_TextChanged(object sender,EventArgs e)
{
if(!_isEditing)
{
_isEditing = true;
base.ColumnStartedEditing(_combo);
}
}
#endregion
}
}

--------------020106030200020600040701--