URGENT: comboBox that is bound to same bindingContext as datagridView

Posts   
 
    
yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 04-Feb-2006 02:13:31   

version 1.0.2005.1 final (self-servicing) VS2005 winforms


Hiya, this is pretty URGENT.

I have a comboBox that is bound to same bindingContext as my datagridView. The bindingContext is bound to an entityCollection. (TblProductCollection) The entityCollection contains a field mapped to a related field. (productTypeName)

When the the comboBox displayMember is "productTypeID", the user selects a row in the datagrid, the combobox correctly reflects the selected item. I can change the comboBox selection and save changes to the database.

Great, But I obviously want to display the "productTypeNAME" rather than the "productTypeID" in the comboBox.

So, I change the comboBox "displayMember"

FROM "productTypeID"

TO "productTypeNAME"

However, when I select an item from the comboBox:

1) the datgridView does not reflect the selection. 2) the change is not persisted to the database, despite the SAME "SaveMulti()" method call as before.

My question, why would changing the "displayMember" of the comboBox cause any change whatsoever in the databinding behaviour?

many thanks, yogi

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39896
Joined: 17-Aug-2003
# Posted on: 04-Feb-2006 11:20:40   

The entity in which producttypename is located, does that exist? If not, first set the related entity. Otherwise lazy loading will fetch the entity and nothing's there so a new one is offered but that's not added to the productcollection entity as that would lead to phantom inserts.

Frans Bouma | Lead developer LLBLGen Pro
yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 04-Feb-2006 12:03:22   

hi Otis,

The entity in which producttypename is located, does that exist? If not, first set the related entity.

I'm not sure what you mean. If you mean, does the datagridView successfully display the related entity column, ie"producttypename", then yes.

I can also confirm that the combobox is correctly populated with the correct producttypename values.However, when I select a row in the datagridVew, then obviously the combobox selected value becomes numeric, reflecting the fact that it is bound to

"productTypeID",

rather than "productTypeNAME"

maybe it's better if I post the code.


           currProducts.GetMulti(null);  //populate entityColection

            productsBindingSource.DataSource = currProducts;
            dgvProducts.DataSource = productsBindingSource;

    
          TblProductTypeCollection productTypeColl= new TblProductTypeCollection();
          productTypeColl.GetMulti(null);

          cboReturnsProductType.DisplayMember = "productTypeName";                      
          cboReturnsProductType.DataSource = productTypeColl;
          cboReturnsProductType.DataBindings.Add("text", productsBindingSource, "productTypeId");
 }


Does this clarify?

many thanks,

yogi

JimHugh
User
Posts: 191
Joined: 16-Nov-2005
# Posted on: 04-Feb-2006 18:24:19   

Normally you would not add a databinding to a combobox text property, instead you would set the DisplayMember and ValueMember properties.


         cboReturnsProductType.DataSource = productTypeColl;
         cboReturnsProductType.DisplayMember = "productTypeName";
         cboReturnsProductType.ValueMember = "productTypeID";

to use early binding of the Value and Display, you may want to use:


         cboReturnsProductType.DataSource = productTypeColl;
         cboReturnsProductType.DisplayMember = productTypeFieldIndex.productTypeName.toString();
         cboReturnsProductType.ValueMember = productTypeFieldIndex.productTypeID.toString();

yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 05-Feb-2006 12:03:06   

hiya Jim,

Yes, I understand how to bind to a combobox.However, with my code, I am using a bindingContext.Therefore the values in this combobobox must:

1) reflect the currently selected row in the datagridView 2) be able to update the database when changed.

the code below works with a textbox.My question is, how do i make it work with a combobox?



currProducts.GetMulti(null); //populate entityColection

productsBindingSource.DataSource = currProducts;
dgvProducts.DataSource = productsBindingSource;

txtProduct.DataBindings.Add("text", productsBindingSource, "productName");

Many thanks, yogi

JimHugh
User
Posts: 191
Joined: 16-Nov-2005
# Posted on: 05-Feb-2006 15:05:56   

currProducts.GetMulti(null); //populate entityColection

productsBindingSource.DataSource = currProducts;
dgvProducts.DataSource = productsBindingSource;

cboReturnsProductType.DataSource = productsBindingSource;
cboReturnsProductType.DisplayMember = productTypeFieldIndex.productTypeName.toString();
cboReturnsProductType.ValueMember = productTypeFieldIndex.productTypeID.toString();

yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 05-Feb-2006 16:02:52   

cheers Jim,

sorry to drag this one out, but I can't seem to get intellisense to find the "productTypeName" of my "productTypeFieldIndex"

I have included the "factoryClasses" namespace, but it still can't find it :-( All it can find is the "TblProductTypeFields"

So, I try this:


cboReturnsProductType.DisplayMember =  TblProductTypeFields.ProductTypeName.ToString(); 

<error> datamember "SD" can't be foud on the datasource. </error>

I'm not sure why the "TblProductTypeFieldIndex" isn't visible via intellisense.I can see that it DOES exist in the generated code.

Any advice appreciated.

many thanks,

yogi

JimHugh
User
Posts: 191
Joined: 16-Nov-2005
# Posted on: 05-Feb-2006 17:47:51   

What using statements do you have at the top of your source file?

The *FieldIndex are at top of the LLBL generated namespace

e.g.

Northwind.Data.CustomerIDFieldIndex

yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 06-Feb-2006 21:47:58   

spot on Jim,

I had to add the project name to my using statements. The combobox seems to correctly reflect the selected row in the datagridVew.

Happy days so far...What I don't understand is why the underlying database isn't updated when I change the selection of the combobox?

1) bindingSource is bound to entityCollection 2) datagridView is bound to bindingSource 3) combobox is bound to bindingSource

I use the combobox_selectedIndexChanged event.

  private void cboReturnsProductType_SelectedIndexChanged(object sender, EventArgs e)
        {
            currProducts.SaveMulti();
        }

No joy, I'm just looking for the easiest way to do this.

Any advice appreciated.

cheers, yogi

JimHugh
User
Posts: 191
Joined: 16-Nov-2005
# Posted on: 06-Feb-2006 22:56:50   

Since you are not leaving the combobox before saving the collection, that bound column is still in edit mode.

One solution would be to move the Save to a separate button.

Another might be to force an EndEdit.


private void cboReturnsProductType_SelectedIndexChanged(object sender, EventArgs e)
        {
            bindingSource1.EndEdit();
            currProducts.SaveMulti();
        }

yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 07-Feb-2006 00:19:19   

hiya Jim,

No joy. I tried both approaches, but none of them updated the database. I do notice that the combobox contains a productType for every product in the datagridView..

ie,

productId productName productType 1 ham_baguette baguette 2 chicken_wrap wrap 3 veg_wrap wrap

combobox would contain: baguette
wrap wrap ?why is this duplicated?

I also notice that, eg, If I select the ham baguette, the comboBox correctly displays "baguette"

However, with the COMBOBOX, if I select the "wrap" productType, then the datagridView selected row automatically jumps to the second row.

I'd have thought that: 1) the datagridView selected row should not change. 2) the productType name in the datagridView should change, to reflect the change in the combobox that is bound to the SAME bindingSource

I'm not sure why any of the above hapens..I think I'm losing this one :-(

Any ideas?

many thanks, yogi

JimHugh
User
Posts: 191
Joined: 16-Nov-2005
# Posted on: 07-Feb-2006 06:45:41   

The Datasource of the combox should point to a the list of available items that can be chosen for that column in the Datasource bound to the DataGridView.

They should normally be two different collections.

So in your scenario, I would guess that the DataGridView should have a list of items in an Order. One of the columns of the Order would be the ProductID. The ProductID would be selected from a list of available Products.

yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 07-Feb-2006 19:28:47   

hiya Jim.

The Datasource of the combox should point to a the list of available items that can be chosen for that column in the Datasource bound to the DataGridView.

They should normally be two different collections.

Yes, but how could the datagridView be linked to the combobox data UNLESS I set a bindingSource?

If I simply set the dataSource of the combobox to tblProductTypeName collection, then it: 1) WILL correctly display the productTypeNames 2) WILL NOT bear any relation to the selected row in the datagridView...

So in your scenario, I would guess that the DataGridView should have a list of items in an Order. One of the columns of the Order would be the ProductID. The ProductID would be selected from a list of available Products.

mY DataGridView contains a list of products. productId, productName, productTypeId I have added a field based on a related entity "ProductTypeName"

Therefore, do I DELETE the productId column and work with the productTypeName column only?The user has absolutely NO interest in the productTypeId.

I need to be able to update the productTypeName column in the datagridView, via the combobox that resides outwith the datagridView.

This is starting to seem like a tall order :-(

That said, I really appreciate the help.

many thanks,

yogi

JimHugh
User
Posts: 191
Joined: 16-Nov-2005
# Posted on: 07-Feb-2006 20:14:58   

Yes, but how could the datagridView be linked to the combobox data UNLESS I set a bindingSource?

If I simply set the dataSource of the combobox to tblProductTypeName collection, then it: 1) WILL correctly display the productTypeNames 2) WILL NOT bear any relation to the selected row in the datagridView...

mY DataGridView contains a list of products. productId, productName, productTypeId I have added a field based on a related entity "ProductTypeName"

Therefore, do I DELETE the productId column and work with the productTypeName column only?The user has absolutely NO interest in the productTypeId.

I need to be able to update the productTypeName column in the datagridView, via the combobox that resides outwith the datagridView.

Got it, I can see the larger picture now.

Remember that the DataGridView is bound to the Products bindingsource. The ComboBox also needs to be bound to the Products bindingsource.

You are correct that the end user does not care or need to see the ProductTypeID.

You need to add a DataBinding to the combobox SelectedValue using DataBindings.Add


currProducts.GetMulti(null); //populate entityColection

productsBindingSource.DataSource = currProducts;
dgvProducts.DataSource = productsBindingSource;

cboReturnsProductType.DataSource = productTypeBindingSource;
cboReturnsProductType.DisplayMember = productTypeFieldIndex.productTypeName.toString();
cboReturnsProductType.ValueMember = productTypeFieldIndex.productTypeID.toString();

cboReturnsProductType.DataBindings.Add(New System.Windows.Forms.Binding("SelectedValue", this.productsBindingSource, productTypeFieldIndex.productTypeID.toString, True));


yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 08-Feb-2006 00:56:12   

Aah Jim, you're a gem.

Cheers for sticking with me. At the risk of tempting fate, it all seems to work fine sunglasses

Mainly due to your help.

All the best, yogi