populate combobox and still have correct databindings

Posts   
 
    
yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 27-May-2006 23:19:08   

version 1.0.2005.1 final (self-servicing) VS2005 winforms


hiya,

I have a combobox that reflects the "condition" of a product, ie NEW or OLD

If I was using simple databinding, I would databind to the "productCondition" entityCollection. The cboProductCondition combobox would then correctly always contain only the items "NEW" and "OLD"

Unfortunately, the cboProductCondition is used as a filter to filter the contents of a datgridView.

eg, the user selects "OLD", then the datagridView will display all the OLD products within a particular product return.

So, does this mean that I need COMPLEX databinding?

The products in a datagridView are either NEW or OLD, In other words, mutually exclusive.

The datagridView will display either: all the NEW products that comprise a product return. OR, it will display all the OLD products that comprise a product return.

This will happen, depending on the productCondition that is selected in the cboProductCondition combobox. (using the selectedValue as a predicate)

<schema> returnId PK productId PK productConditionId PK productConditionName (added as a field mapped on a related field) </schema>

My problem,

If I use complex databinding, then the combobox will grab ALL the current values in the entityCollection...

eg. if there are 3 OLD items in the entityCollection, then the combobox will contain: "OLD " "OLD " "OLD "

...That is no use to me whatsoever.

So, how do I initially populate the combobox so that it:

1) only and always contains the items "New" and "old", regardless of what is in the entityCollection? 2) can use its "selectedValue" as a predicate to filter the datasource for the datagridView?

Below is what I have so far.At this stage, I understand the problem really well, and can clarify any ambiguity.

please help. flushed


 tblReturnCollection1.GetMulti(null); 
 parentBindingSource.DataSource = tblReturnCollection1;
            
IPredicateExpression filtReturnProductCondition = new PredicateExpression();
//returnId filter omitted for clarity.
filtReturnProductCondition.Add(PredicateFactory.CompareValue(TblReturnProductsFieldIndex.ReturnProductCondtionId, ComparisonOperator.Equal, (int)cboReturnProductCondition.SelectedValue)) ;

//So, in the above code, the cboReturnProductCondition hasn't yet been populated

tblReturnProductsCollection1.GetMulti(filtReturnProductCondition); 
childBindingSource.DataSource = tblReturnProductsCollection1;
dgvReturns.DataSource = childBindingSource;

cboReturnProductCondition.DataBindings.Clear();
cboReturnProductCondition.DataBindings.Add(new Binding("SelectedValue", this.childBindingSource, myProject.TblReturnProductsFieldIndex.ReturnProductCondtionId.ToString(), true));
            childBindingSourceProdCondition.DataSource = tblReturnProductsCollection1;
            cboReturnProductCondition.DataSource = childBindingSourceProdCondition;     

sparmar2000 avatar
Posts: 341
Joined: 30-Nov-2003
# Posted on: 28-May-2006 19:48:27   

1) only and always contains the items "New" and "old", regardless of what is in the entityCollection?

I assume that you have hardcoded this. When do the values not 'appear'?

yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 29-May-2006 00:20:25   

hiya,

No, I have not hard-coded this..If I use simple datatbinding and bind direclty to the "productCondition" entityCollection, then the combobox will only display the items NEW and OLD.

The problem is, I have to use complex databinding...becasue, for example, If I select a return that contains only OLD items.then if cboReturnProductCondition is set to NEW, the combobox won't automatically be set to OLD, to reflect the condition of the products in that specific return...

make sense?

yogi

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 29-May-2006 10:54:40   

Before I'll answer your question, please understand this: - Complex databinding is binding IList implementing objects to grids, listboxes and similar controls - Simple databinding is binding a property of a control to a property of an object, e.g. textbox.Text to myEntity.Name.

So it's not a matter of 'I first used simple databinding and now want to use/need to use complex databinding', in any situation it's either complex or simple databinding, but not both, so you can't bind a collection to a combobox using simple databinding, as you set a datasource property simple_smile .

I'll now look into your code.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 29-May-2006 11:11:17   

So, how do I initially populate the combobox so that it:

1) only and always contains the items "New" and "old", regardless of what is in the entityCollection?

Well, if you have 2 conditions, e.g. NEW and OLD, I'd hardcode these conditions in the combobox. However it can be fragile if you have more than two conditions, NEW, OLD, NOTRELEASEDYET, CURRENT, etc. later on. So it's good to read the conditions available currently in the database, so you'll always have all the values the user can filter on. You should then use a dyn. list to get the condition values available in the table. As you conditions are stored in a separate table, it can be 0 rows are in the products table with that condition. So if you want to have filters which show at least 1 row, you need a query like: SELECT conditionName FROM ProductConditions WHERE productConditionID IN ( SELECT productConditionId FROM products )

you can create a simply dynamic list to fetch this using a fieldcompareset predicate. If you just need the conditionnames, simply fetch the entities from the productcondition table, like you intended to do: simply call productConditionCollection.GetMulti(null); to get all the entities. Then bind that collection to the cboProductCondition combobox, where you set DisplayMember to ConditionName, and ValueMember to ProductConditionID.

Now, forget the binding you setup here:


cboReturnProductCondition.DataBindings.Add(new Binding("SelectedValue", this.childBindingSource, myProject.TblReturnProductsFieldIndex.ReturnProductCondtionId.ToString(), true));

As that binds the other way around, it's backwards: you use the combobox as a filter. So if the user selects NEW, it doesn't need the binding, as all entities in the grid will be NEW anyway.

2) can use its "selectedValue" as a predicate to filter the datasource for the datagridView?

Yes, well, not the 'SelectedValue', but data related to that. - You bind an event handler to SelectedIndexChanged of cboProductCondition. In that handler, you create the filter and re-fetch the products for the grid. You do that as follows:


private void cboProductCondition_SelectedIndexChanged(object sender, Eventargs e)
{
    if(cboProductCondition.SelectedValue==null)
    {
        return;
    }
    ProductConditionEntity selectedCondition = (ProductConditionEntity)cboProductCondition.SelectedValue;
    PredicateExpression filter = new PredicateExpression(
        ProductFields.ProductConditionId==selectedCondition.ProductConditionId);
    // fetch the products again, and rebind to the grid. 
    ...
}

Frans Bouma | Lead developer LLBLGen Pro
yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 29-May-2006 13:39:31   

hiya,

Ok, I think I understand most of it.

So it's good to read the conditions available currently in the database, so you'll always have all the values the user can filter on.

Ok, I'll store them in database, as before.

If you just need the conditionnames, simply fetch the entities from the productcondition table, like you intended to do: simply call productConditionCollection.GetMulti(null); to get all the entities. Then bind that collection to the cboProductCondition combobox, where you set DisplayMember to ConditionName, and ValueMember to ProductConditionID.

Agreed.All I need to do is ensure that the combobox always reflects the condition of the products in the datagridView..It doesn't matter if the combobox selectedValue does not match any of the product conditions within that particular return..if the combobox selectedValue does not match any of the product conditions within that particular return, thn the datagridview should be empty,,that's fine

However, I am having a problem with the following code:



TblReturnProductConditionEntity selectedCondition = (TblReturnProductConditionEntity)cboReturnProductCondition.SelectedValue;   

I get an error, because ( I think) that I am trying to cast an INT to a TblReturnProductConditionEntity.

I think I am nearly there. How can I get the above code to work?

many thanks,

yogi

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 29-May-2006 14:37:19   

Oh, my bad! flushed You have to use SelectedItem, not SelectedValue. SelectedItem is the object in the collection which corresponds with the selected value in the combobox.

Frans Bouma | Lead developer LLBLGen Pro
yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 29-May-2006 15:24:47   

thanks bud,

I should've spotted that, but my head's wasted at the minute. I have my filter slightly different, Is this the same thing?It seems to work the same.


PredicateExpression filter = new PredicateExpression(
        ProductFields.ProductConditionId==selectedCondition.ProductConditionId);    

my code...



 IPredicateExpression filter= new PredicateExpression();
 filter .Add(PredicateFactory.CompareValue(TblReturnProductsFieldIndex.ReturnProductCondtionId, ComparisonOperator.Equal, selectedCondition.ReturnProductCondtionId)); 


many thanks, yogi

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 29-May-2006 16:18:29   

Yes that's the same code simple_smile

Frans Bouma | Lead developer LLBLGen Pro
yogiberr
User
Posts: 432
Joined: 29-Jun-2005
# Posted on: 29-May-2006 18:05:04   

hiya,

Ok, good to know. Thanks all, for reading ad helping me out.

much appreciated..

yogisaurus sunglasses