DataGridView - Defaulting value in combo box column

Posts   
 
    
Posts: 254
Joined: 16-Nov-2006
# Posted on: 18-Jun-2007 11:15:48   

LLBLGen 2.0.7.424 SelfServicing

I'm using a combo box column in a DataGridView which is bound to a binding source bound to an EntityCollection e.g. which presents a list of priorities.

The data grid view is bound to a binding source which is bound to an EntityCollection. The main entity bound to the DataGridView has a PriorityId column which specifies the priority in the drop down.

I can successfully default the combo box column using code such as the following


DataGridViewComboBoxColumn priorityColumn = issuesDataGridView.Columns["PriorityId"] as DataGridViewComboBoxColumn;
priorityColumn.DefaultCellStyle.NullValue            = priorities[0].Name;

However the value of PriorityId isn't set in the data store. It only seems to be set if you actually select the drop down explicitly in the data grid view. I then noticed the DataSourceNullValue property and tried this


priorityColumn.DefaultCellStyle.DataSourceNullValue = priorities[0].PriorityId;

however this didn't work and still saved NULL into the database.

jbb avatar
jbb
User
Posts: 267
Joined: 29-Nov-2005
# Posted on: 18-Jun-2007 15:10:38   

Hello,

is your combobox column is the only column that has a null value? Could you update the other fields?

Posts: 254
Joined: 16-Nov-2006
# Posted on: 18-Jun-2007 15:18:02   

Other fields are being updated correctly, it's just two fields which are combo boxes are not being updated unless I explicitly change the selection of them.

jbb avatar
jbb
User
Posts: 267
Joined: 29-Nov-2005
# Posted on: 18-Jun-2007 15:39:12   

Hello,

How did you bind the content of your combobox(on which event)?

Posts: 254
Joined: 16-Nov-2006
# Posted on: 18-Jun-2007 15:57:24   

I don't quite follow you in relation to which event.

However I configured the data binding from the combo box to the binding source through the designer i.e. editing the columns in the DataGridView and specifying the properties DataSource, DisplayMember and ValueMember.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 19-Jun-2007 20:55:02   

However the value of PriorityId isn't set in the data store. It only seems to be set if you actually select the drop down explicitly in the data grid view. I then noticed the DataSourceNullValue property and tried this

To set the value you obviously have to select a value, I don't think that's that odd. Or am I not understanding teh scenario?

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 19-Jun-2007 20:57:25   

It's certainly very odd.

Developers usually provide defaults for the sole purpose of not requiring users to explicitly enter those values unless they require different values other than the default. You should n't have to explicitly set them.

In fact as I'm writing this post wouldn't it be tedious if I had to select Black in the Color drop down and Normal in the size drop down, to ensure a valid value is saved.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-Jun-2007 10:59:45   

MattAdamson wrote:

It's certainly very odd.

Developers usually provide defaults for the sole purpose of not requiring users to explicitly enter those values unless they require different values other than the default. You should n't have to explicitly set them.

In fact as I'm writing this post wouldn't it be tedious if I had to select Black in the Color drop down and Normal in the size drop down, to ensure a valid value is saved.

Yes, that would be silly. simple_smile

the thing is though: if you didn't have a combo-box in place, the cell would be empty. Grids work very simple: the user interacts with a row and the data behind the row goes into edit mode. Then the user interacts with a cell, and the data entered into the cell is passed on to the data object behind the row.

So if you paint a combobox into a cell, nothing really happens, unless you deliberately select a value in that combobox yourself the minute the user enters that row AND the cell doesn't have a value. then the manual selection will set the value in the cell and the grid will thus pass it on to the data object behind the row. So no action in cell == no action on the data object.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 20-Jun-2007 11:06:48   

You should work for microsoft Frans, with a brilliant explanation of why something doesn't work which should.

a) I'm not convinced this isn't an issue in the LLBLGenDataSource control however to help isolate this further it would probably help if I created a simple application which used a SqlDataSource binding directly to the database, and using a combo box bound to another SqlDataSource.

b) Even if it can't work through simple data binding it should be possible to set the value through one of the custom data binding events although I don't know which one, there are obviously many events on the combo box, grid, LLBLGenDataSource and binding source rage

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 20-Jun-2007 11:10:44   

MattAdamson wrote:

You should work for microsoft Frans, with a brilliant explanation of why something doesn't work which should.

heh wink

a) I'm not convinced this isn't an issue in the LLBLGenDataSource control however to help isolate this further it would probably help if I created a simple application which used a SqlDataSource binding directly to the database, and using a combo box bound to another SqlDataSource.

erm... We're talking winforms here, right? That's what I was thinking... not webforms. So the datasource isn't used in this scenario. Web binding works completely different. (e.g. : no currency manager, nothing is kept in sync for you)

b) Even if it can't work through simple data binding it should be possible to set the value through one of the custom data binding events although I don't know which one, there are obviously many events on the combo box, grid, LLBLGenDataSource and binding source rage

Ok, first things first: 'DataGridView' is a winforms control, now you're talking about a llblgenprodatasource. that's webforms simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 20-Jun-2007 11:26:01   

Sorry, yes definitely win forms, I would be interested to see how this works in web forms however for now lets just focus on win forms.

So in relation to this, only two BindingSource objects, one for the entities bound to the grid and one for entries bound to the combobox.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 22-Jun-2007 10:51:06   

MattAdamson wrote:

Sorry, yes definitely win forms, I would be interested to see how this works in web forms however for now lets just focus on win forms.

So in relation to this, only two BindingSource objects, one for the entities bound to the grid and one for entries bound to the combobox.

Ok, but I still think not setting the entries combo box to an actually value is the cause of the fact that the field isn't set.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 15-Jul-2007 23:51:40   

Ah interesting I thought I had a solution to this when I reviewed Brian Noyes excellent "Data Binding with Windows Forms 2.0" book again.

In it he mentions a techinque of using the AddingNew event handler of the BindingSource object to return a new object, at which time you could default some property values according to your requirements. Therefore I added this handler

        private void defectsBindingSource_AddingNew(object sender, AddingNewEventArgs e)
        {
            DefectEntity defect  = new DefectEntity();

            defect.DefectType      = defectTypes[0];
            defect.DefectSeverity   = defectSeverities[0];

            e.NewObject = defect;
        }

However after executing thie code I received an exception from this source

        /// <summary>
        /// Not supported. Use AddNew() or add a new object to the related entity collection.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        int IList.Add( object value )
        {
            if( value == null )
            {
                // design time databinding.
                IEntityCore newEntity = this.AddNew();
                return this.IndexOf((TEntity)newEntity);
            }
            throw new NotSupportedException( "Add a new object to the related collection instead, or use IBindingList.AddNew() on this object." );
        }

In the EntityViewBase LLBLGen class. I don't quite understand why this method is not supported?

You can see a detailed call stack below

" at SD.LLBLGen.Pro.ORMSupportClasses.EntityViewBase`1.System.Collections.IList.Add(Object value)\r\n at System.Windows.Forms.BindingSource.Add(Object value)\r\n at System.Windows.Forms.BindingSource.AddNew()\r\n at System.Windows.Forms.CurrencyManager.AddNew()\r\n at System.Windows.Forms.DataGridView.DataGridViewDataConnection.AddNew()\r\n at System.Windows.Forms.DataGridView.DataGridViewDataConnection.OnNewRowNeeded()\r\n at System.Windows.Forms.DataGridView.OnRowEnter(DataGridViewCell& dataGridViewCell, Int32 columnIndex, Int32 rowIndex, Boolean canCreateNewRow, Boolean validationFailureOccurred)\r\n at System.Windows.Forms.DataGridView.SetCurrentCellAddressCore(Int32 columnIndex, Int32 rowIndex, Boolean setAnchorCellAddress, Boolean validateCurrentCell, Boolean throughMouseClick)\r\n at System.Windows.Forms.DataGridView.OnCellMouseDown(HitTestInfo hti, Boolean isShiftDown, Boolean isControlDown)\r\n at System.Windows.Forms.DataGridView.OnCellMouseDown(DataGridViewCellMouseEventArgs e)\r\n at System.Windows.Forms.DataGridView.OnMouseDown(MouseEventArgs e)\r\n at

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Jul-2007 10:59:59   

What's the exception you get with that stacktrace? Just a stacktrace isn't really helpful wink

databinding is request-response, so if nothing is done from the control side, nothing will happen.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 17-Jul-2007 19:04:24   

NotSupportedException, although you can infer this from the code

/// <summary>
        /// Not supported. Use AddNew() or add a new object to the related entity collection.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        int IList.Add( object value )
        {
            if( value == null )
            {
                // design time databinding.
                IEntityCore newEntity = this.AddNew();
                return this.IndexOf((TEntity)newEntity);
            }
            throw new NotSupportedException( "Add a new object to the related collection instead, or use IBindingList.AddNew() on this object." );
        }

If the top stack frame is IList.Add this is the only place the exception could be thrown from

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 18-Jul-2007 11:42:51   

I can successfully default the combo box column using code such as the following

Code:

DataGridViewComboBoxColumn priorityColumn = issuesDataGridView.Columns["PriorityId"] as DataGridViewComboBoxColumn; priorityColumn.DefaultCellStyle.NullValue = priorities[0].Name;

You want to select a default item from the comboBox when you are inserting a new row into the grid, correct? I've just came across the following links: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=296498&SiteID=1 http://www.thescripts.com/forum/thread505731.html Hope they can be useful.

Posts: 254
Joined: 16-Nov-2006
# Posted on: 18-Jul-2007 20:31:13   

Hi Walaa,

No this doesn't help however thanks for your efforts in finding this. CellFormatting actually only changes the presentation of the cell and doesn't change the underlying value persisted.

I'd still like an answer from Frans on why the IList.Add implementation in the object isn't complete i.e. a NotSupportedException is thrown, presumably if this is fixed, this should work fine.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 19-Jul-2007 10:30:47   

This is because EntityView(2) doesnt have an Add() capability, the collection has, but the view has not, except via its IBindingList.AddNew() routine.

If you want to add a new entity to the view, use that. The thing is that the view is just that: a view.

IBindingList is implemented otherwise new rows aren't possible to add via a grid. This is the only supported way to add new rows to the view.

So either: 1) call AddNew on the view or 2) grab the related collection and add the entity to that collection.

If you opt for 2, be sure the view's DataChangeAction is set to a setting which supports refreshes of the view after the related collection was changed simple_smile

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 19-Jul-2007 17:12:20   

The DataSource property of the BindingSource is set to an object which is an entity collection. Therefore it's the BindingSource control which is calling these methods, so how can I change this behaviour.

I've also discussed this with Brian who wrote the Data Binding book, he thinks this should be supported in the collection.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 19-Jul-2007 18:27:36   

Of course it's supported in the collection, but the collection implements IListSource, which returns the entity view instead, as the collection is bound via the entity view, not directly.

It's a silly method in this context really. take a look at DataView.IList.Add. simple_smile There, you'll get an exception if you pass in an object to add. Isn't that the same thing as you get now?

The collection isn't directly bound to the bindingsource, which is IMHO the reason why this confusion exists. The collection supports Add, no problem, the issue is with the entityview, which is what the bindingsource is dealing with because of the IListSource. The behavior of the EntityView(2) is the same as DataView's implementation, and in databinding-land that's equal to obeying the 'standard'.

Frans Bouma | Lead developer LLBLGen Pro