Binging custom objects to the DataGridViewComboBoxColumn

G

Guest

Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties, Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of custom type
'Order'.

The Order class simply contains properties like OrderID, OrderName etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for the
strings and DataGridViewComboBoxColumn for the 'Order' object, the code for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

Would be delighted to get an answer or a pointer to a good tutorial.
Couldn't find any that explain how to do this.

Steve
 
B

Bart Mermuys

Hi,

Steve Bugden said:
Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties, Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of custom
type
'Order'.

The Order class simply contains properties like OrderID, OrderName etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for the
strings and DataGridViewComboBoxColumn for the 'Order' object, the code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue then AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource, bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp = ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) == (string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings
 
G

Guest

Hi Bart,

Thankyou very much for the excellent answer.

Though I will need to study binding a bit more to fully understand what's
going on.

Best Regards,

Steve

Bart Mermuys said:
Hi,

Steve Bugden said:
Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties, Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of custom
type
'Order'.

The Order class simply contains properties like OrderID, OrderName etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for the
strings and DataGridViewComboBoxColumn for the 'Order' object, the code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue then AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource, bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp = ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) == (string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings

Would be delighted to get an answer or a pointer to a good tutorial.
Couldn't find any that explain how to do this.

Steve
 
R

RobinS

Check out Brian Noyes' book, "Data Binding with Windows Forms 2.0". It
chock-full of cool stuff about data binding.

Robin S.
Ts'i mahnu uterna ot twan ot geifur hingts uto.
----------------------------------------------------------
Steve Bugden said:
Hi Bart,

Thankyou very much for the excellent answer.

Though I will need to study binding a bit more to fully understand what's
going on.

Best Regards,

Steve

Bart Mermuys said:
Hi,

Steve Bugden said:
Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties,
Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of
custom
type
'Order'.

The Order class simply contains properties like OrderID, OrderName
etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for
the
strings and DataGridViewComboBoxColumn for the 'Order' object, the
code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far
only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue then
AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource, bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp =
ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int
rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter
formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) == (string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings

Would be delighted to get an answer or a pointer to a good tutorial.
Couldn't find any that explain how to do this.

Steve
 
G

Guest

Hi Robin,

THanks for the book tip. That is actually the book I have been following,
couldn't see how to bind a collection of custom objects to a combo on a grid
though.

I am not sure that the DataGridView is the way to go. Some of the 3rd party
products seem to have such fantastic capabilities.

Steve.

RobinS said:
Check out Brian Noyes' book, "Data Binding with Windows Forms 2.0". It
chock-full of cool stuff about data binding.

Robin S.
Ts'i mahnu uterna ot twan ot geifur hingts uto.
----------------------------------------------------------
Steve Bugden said:
Hi Bart,

Thankyou very much for the excellent answer.

Though I will need to study binding a bit more to fully understand what's
going on.

Best Regards,

Steve

Bart Mermuys said:
Hi,

Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties,
Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of
custom
type
'Order'.

The Order class simply contains properties like OrderID, OrderName
etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for
the
strings and DataGridViewComboBoxColumn for the 'Order' object, the
code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far
only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue then
AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource, bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp =
ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int
rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter,
TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter
formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) == (string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings



Would be delighted to get an answer or a pointer to a good tutorial.
Couldn't find any that explain how to do this.

Steve
 
R

RobinS

Ah, I get it. I haven't bound a combobox to my dgv yet, although I *am*
binding a list of objects, and finally have all the add/change/delete
capabilities working.

Just out of curiousity, does your class have a ToString method? I vaguely
remember adding a ToString method to the class for my business object had
some impact on some control I was binding it to, although it might have
been a listbox instead of a combobox. Still, it's free to try it.

I personally have an aversion to 3rd party components, because I don't want
to have to be dependent on something I have to pay for, but a lot of people
use them.

If you send Brian Noyes a specific e-mail, he will probably answer it, and
may be able to help you if your message is short and specific enough.

If you figure it out, please post back. And if *I* figure it out, I'll post
back. Although I won't have time to look at it until next week.

Robin S.
----------------------------------
Steve Bugden said:
Hi Robin,

THanks for the book tip. That is actually the book I have been following,
couldn't see how to bind a collection of custom objects to a combo on a
grid
though.

I am not sure that the DataGridView is the way to go. Some of the 3rd
party
products seem to have such fantastic capabilities.

Steve.

RobinS said:
Check out Brian Noyes' book, "Data Binding with Windows Forms 2.0". It
chock-full of cool stuff about data binding.

Robin S.
Ts'i mahnu uterna ot twan ot geifur hingts uto.
----------------------------------------------------------
Steve Bugden said:
Hi Bart,

Thankyou very much for the excellent answer.

Though I will need to study binding a bit more to fully understand
what's
going on.

Best Regards,

Steve

:

Hi,

message
Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties,
Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of
custom
type
'Order'.

The Order class simply contains properties like OrderID, OrderName
etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for
the
strings and DataGridViewComboBoxColumn for the 'Order' object, the
code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the
dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far
only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue then
AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new
BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource, bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp =
ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int
rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter
valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter
formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) ==
(string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings



Would be delighted to get an answer or a pointer to a good
tutorial.
Couldn't find any that explain how to do this.

Steve
 
G

Guest

Hi Robin,

Thankyou for your reply.

From your reply:
If you send Brian Noyes a specific e-mail, he will probably answer it, and
may be able to help you if your message is short and specific enough.

If you figure it out, please post back. And if *I* figure it out, I'll post
back. Although I won't have time to look at it until next week.

The solution provided by Bart in a previous reply works fine. The only
slight thing is that the sort on the Order column no longer works. I assume
that this is because my orders collection does not yet support sort
functionality, where as previously the ToString method was used on the Order
object when binding to a textbox column.

To recap, I have a collection of Persons, where each person can place one
order, selected from a list. Not a realistic solution I know but I am just
prototyping at the moment.

Although Bart's solution works very well, I have to admit to not fully
understanding what is going on, and that makes me uncomfortable. I think it
would require a serious amount of work on my part to understand it, I am not
sure if it will be worth it when I look at the capabilities of some of the
3rd party controls.

I agree wholeheartedly with you regarding the use of 3rd party products by
the way but when I look at the benefits I have to admit they are so useful.

There are so many products out there but just taking a look at this gallery
of capabilities from infragistics:
http://www.infragistics.com/dotnet/netadvantage/winforms/wingrid.aspx#Gallery

I haven't seen this kind of functionality from the DataGridView. I am sure
it is possible to achieve a lot, but the 3rd party grids have so much
functionality built in.

I agree it is a dependancy. I was hoping to minimise this by using standard
interfaces like IBindingList etc.

Please let me know your thoughts.

Best Regards,

Steve.

RobinS said:
Ah, I get it. I haven't bound a combobox to my dgv yet, although I *am*
binding a list of objects, and finally have all the add/change/delete
capabilities working.

Just out of curiousity, does your class have a ToString method? I vaguely
remember adding a ToString method to the class for my business object had
some impact on some control I was binding it to, although it might have
been a listbox instead of a combobox. Still, it's free to try it.

I personally have an aversion to 3rd party components, because I don't want
to have to be dependent on something I have to pay for, but a lot of people
use them.

If you send Brian Noyes a specific e-mail, he will probably answer it, and
may be able to help you if your message is short and specific enough.

If you figure it out, please post back. And if *I* figure it out, I'll post
back. Although I won't have time to look at it until next week.

Robin S.
----------------------------------
Steve Bugden said:
Hi Robin,

THanks for the book tip. That is actually the book I have been following,
couldn't see how to bind a collection of custom objects to a combo on a
grid
though.

I am not sure that the DataGridView is the way to go. Some of the 3rd
party
products seem to have such fantastic capabilities.

Steve.

RobinS said:
Check out Brian Noyes' book, "Data Binding with Windows Forms 2.0". It
chock-full of cool stuff about data binding.

Robin S.
Ts'i mahnu uterna ot twan ot geifur hingts uto.
----------------------------------------------------------
Hi Bart,

Thankyou very much for the excellent answer.

Though I will need to study binding a bit more to fully understand
what's
going on.

Best Regards,

Steve

:

Hi,

message
Hi,

I have bound a collection of type IBindingList to a DataGridView.

Each object in the collection contains various string properties,
Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of
custom
type
'Order'.

The Order class simply contains properties like OrderID, OrderName
etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn for
the
strings and DataGridViewComboBoxColumn for the 'Order' object, the
code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order (List<Order>)
Everything displays OK and I can make selections from the
dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String' to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so far
only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context == DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue then
AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new
BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource, bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp =
ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int
rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter
valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter
formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) ==
(string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings



Would be delighted to get an answer or a pointer to a good
tutorial.
Couldn't find any that explain how to do this.

Steve
 
R

RobinS

According to Bart's message, you are binding to SelectedItem instead of
SelectedValue. Apparently the combobox column for a DGV binds to
SelectedValue, so you have to make your own ComboBoxItemColumn type.

Does your class have a ToString option?

When you say the sort on the Order column no longer works, do you mean the
column in the grid, or the entries in the combobox aren't sorted?

Robin S.
-----------------------------------------------------
Steve Bugden said:
Hi Robin,

Thankyou for your reply.

From your reply:
If you send Brian Noyes a specific e-mail, he will probably answer it,
and
may be able to help you if your message is short and specific enough.

If you figure it out, please post back. And if *I* figure it out, I'll
post
back. Although I won't have time to look at it until next week.

The solution provided by Bart in a previous reply works fine. The only
slight thing is that the sort on the Order column no longer works. I
assume
that this is because my orders collection does not yet support sort
functionality, where as previously the ToString method was used on the
Order
object when binding to a textbox column.

To recap, I have a collection of Persons, where each person can place one
order, selected from a list. Not a realistic solution I know but I am
just
prototyping at the moment.

Although Bart's solution works very well, I have to admit to not fully
understanding what is going on, and that makes me uncomfortable. I think
it
would require a serious amount of work on my part to understand it, I am
not
sure if it will be worth it when I look at the capabilities of some of
the
3rd party controls.

I agree wholeheartedly with you regarding the use of 3rd party products
by
the way but when I look at the benefits I have to admit they are so
useful.

There are so many products out there but just taking a look at this
gallery
of capabilities from infragistics:
http://www.infragistics.com/dotnet/netadvantage/winforms/wingrid.aspx#Gallery

I haven't seen this kind of functionality from the DataGridView. I am
sure
it is possible to achieve a lot, but the 3rd party grids have so much
functionality built in.

I agree it is a dependancy. I was hoping to minimise this by using
standard
interfaces like IBindingList etc.

Please let me know your thoughts.

Best Regards,

Steve.

RobinS said:
Ah, I get it. I haven't bound a combobox to my dgv yet, although I *am*
binding a list of objects, and finally have all the add/change/delete
capabilities working.

Just out of curiousity, does your class have a ToString method? I
vaguely
remember adding a ToString method to the class for my business object
had
some impact on some control I was binding it to, although it might have
been a listbox instead of a combobox. Still, it's free to try it.

I personally have an aversion to 3rd party components, because I don't
want
to have to be dependent on something I have to pay for, but a lot of
people
use them.

If you send Brian Noyes a specific e-mail, he will probably answer it,
and
may be able to help you if your message is short and specific enough.

If you figure it out, please post back. And if *I* figure it out, I'll
post
back. Although I won't have time to look at it until next week.

Robin S.
----------------------------------
Steve Bugden said:
Hi Robin,

THanks for the book tip. That is actually the book I have been
following,
couldn't see how to bind a collection of custom objects to a combo on
a
grid
though.

I am not sure that the DataGridView is the way to go. Some of the 3rd
party
products seem to have such fantastic capabilities.

Steve.

:

Check out Brian Noyes' book, "Data Binding with Windows Forms 2.0".
It
chock-full of cool stuff about data binding.

Robin S.
Ts'i mahnu uterna ot twan ot geifur hingts uto.
----------------------------------------------------------
message
Hi Bart,

Thankyou very much for the excellent answer.

Though I will need to study binding a bit more to fully understand
what's
going on.

Best Regards,

Steve

:

Hi,

message
Hi,

I have bound a collection of type IBindingList to a
DataGridView.

Each object in the collection contains various string
properties,
Customer
Name, Contact Name etc. It also contains a property 'MyOrder' of
custom
type
'Order'.

The Order class simply contains properties like OrderID,
OrderName
etc.

I add the columns to the Grid of type DataGridViewTextBoxColumn
for
the
strings and DataGridViewComboBoxColumn for the 'Order' object,
the
code
for
the combo column is as follows:

DataGridViewComboBoxColumn cboCustmomerOrder = new
DataGridViewComboBoxColumn();
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.Name = "OrderName";
//cboCustmomerOrder.ValueType = Order;
cboCustmomerOrder.DataSource = m_Cust.OrderCol;
this.dataGridView1.Columns.Add(cboCustmomerOrder);

The datasource is set to a collection of type Order
(List<Order>)
Everything displays OK and I can make selections from the
dropdowns.

When I try to tab away however, I get the following error:
[System.FormatException] = {"Invalid cast from 'System.String'
to
'BusinessComponentExample.Order'."}

I have spent ages trying to find out how to handle this but so
far
only
found that the error can be trapped as follows:

private void dataGridView1_DataError(object sender,
DataGridViewDataErrorEventArgs e)
{
if (e.Exception != null &&
e.Context ==
DataGridViewDataErrorContexts.Commit)
{
//Do something
}
}

Obviously I need to cast to type 'Order', but my question is
how?

Hope this all makes sense, please let me know if not.

If you want to use SelectedItem binding instead of SelectedValue
then
AFAIK
you need to make your own DGVComboBoxColumn, eg.:

public class DGVComboBoxItmColumn : DataGridViewComboBoxColumn
{
public DGVComboBoxItmColumn()
{
CellTemplate = new DGVComboBoxItmCell();
}
}

public class DGVComboBoxItmCell : DataGridViewComboBoxCell
{
private PropertyDescriptor displayProp;

private CurrencyManager ListManager
{
get
{
BindingMemberInfo bmi = new
BindingMemberInfo(base.DisplayMember);
if (DataGridView != null)
{
return (CurrencyManager)
DataGridView.BindingContext[DataSource,
bmi.BindingPath];
}
return null;
}
}

private PropertyDescriptor DisplayProp
{
get
{
if (displayProp == null)
{
displayProp =
ListManager.GetItemProperties().Find(DisplayMember,
true);
}
return displayProp;
}
}

protected override object GetFormattedValue(object value, int
rowIndex,
ref DataGridViewCellStyle cellStyle, TypeConverter
valueTypeConverter,
TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts
context)
{
if (value == null || value == cellStyle.DataSourceNullValue)
return "";

return base.GetFormattedValue(DisplayProp.GetValue(value),
rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}

public override object ParseFormattedValue(object
formattedValue,
DataGridViewCellStyle cellStyle, TypeConverter
formattedValueTypeConverter,
TypeConverter valueTypeConverter)
{
foreach (object item in ListManager.List)
{
if ((string)DisplayProp.GetValue(item) ==
(string)formattedValue)
return item;
}

return base.ParseFormattedValue(formattedValue, cellStyle,
formattedValueTypeConverter, valueTypeConverter);
}
}

And then set it up like:

DataGridViewComboBoxItmColumn cboCustmomerOrder = new
DataGridViewComboBoxItmColumn();
cboCustmomerOrder.Name = "CustomerOrderComboBox";
cboCustmomerOrder.HeaderText = "Order";
cboCustmomerOrder.DataPropertyName = "MyOrder";
cboCustmomerOrder.DataSource = new BindingSource(m_Cust.OrderCol);
cboCustmomerOrder.DisplayMember = "OrderName";

this.dataGridView1.Columns.Add(cboCustmomerOrder);


HTH,
Greetings



Would be delighted to get an answer or a pointer to a good
tutorial.
Couldn't find any that explain how to do this.

Steve
 

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