|
Cool code, but I'm having a slight problem when adding a new record.
I have a three column DataGrid. The second column has the DataGridComboBox Column. When I add a new record at the bottom of the grid, if I select the ComboBox control first, then try to move to the last field, the ComboBox offsets horizontally to the right covering the column that I would like to edit. If I select the third column first, it works fine.
Can anyone tell me what I'm doing wrong here (see code below)?
private void SetDataGridStyle()
{
// create the TableStyle
this.dgTSRequirements = new System.Windows.Forms.DataGridTableStyle();
this.dgTSRequirements.MappingName = "BUSINESS_REQUIREMENT";
// add the first normal TextBox ColumnStyle
this.dgCSRequirementID = new DataGridTextBoxColumn();
this.dgCSRequirementID.MappingName = "BUSINESS_REQUIREMENT_ID";
this.dgCSRequirementID.Width = 60;
this.dgCSRequirementID.HeaderText = "Number";
this.dgTSRequirements.GridColumnStyles.Add(this.dgCSRequirementID);
// add the ComboBox ColumnStyle
this.dgCSRequirementType = new DataGridComboBoxColumn("BUSINESS_REQUIREMENT_TYPE", this.dataSet11.BUSINESS_REQUIREMENT_TYPE, "BUSINESS_REQUIREMENT_TYPE", "BUSINESS_REQUIREMENT_TYPE"this.dataGrid1);
this.dgCSRequirementType.Width = 128;
this.dgCSRequirementType.HeaderText = "Type";
this.dgCSRequirementType.NullText = "2";
this.dgTSRequirements.GridColumnStyles.Add(this.dgCSRequirementType);
// add the third normal TextBox Column
this.dgCSRequirement = new DataGridTextBoxColumn();
this.dgCSRequirement.MappingName = "BUSINESS_REQUIREMENT";
this.dgCSRequirement.Width = 600;
this.dgCSRequirement.HeaderText = "Requirement";
this.dgTSRequirements.GridColumnStyles.Add(this.dgCSRequirement);
// add the TableStyle to the DataGrid
this.dataGrid1.TableStyles.Add(this.dgTSRequirements);
}
I'm stumped on why when adding a new row to the DataGrid the ComboBox column does an offset to the right obscuring the third row so data cannot be added?
Thanks
|
|
|
|
|
The readonly property of DataGridComboBoxColumn does not seem to be implemented. The following code compiles, but there is no apparent change to the behavior of the column:
DataGridComboBoxColumn myCol = new DataGridComboBoxColumn( "foo", myTable, "Name", "Value", myDGrid);
myCol.NullText = "1";
myCol.HeaderText = "Event Type";
myCol.ReadOnly = true;
myStyle.GridColumnStyles.Add(myCol);
How might I change the code so that, for example, the ComboBox is grayed-out (like the DataGridTextBoxColumn) and does not show the drop-down list then readonly is set to true?
Thanks,
B the ComboBoxColumn
|
|
|
|
|
Hi,
First thanks for the code, it's great.
I just had this problem : when I edit the combobox it works fine, but...
When I click in another populated row, everything is ok.
But when I click in the new row (at the bottom) while editing, this exception is raised : System.FormatException and the debugger stops at this line :
if (instantText!=null)
but instantText IS null
Do you know what the problem may be ?
Thanks
David
|
|
|
|
|
Hi, well I have not seen that error, but I have had others that came up that didn't make sence but I did a few changes ahead of time and like magic it works. I looked in my Edit, which is the only place there is a reference to "instantText", and I have a few more changes:
I had an error which came up if the value was Null, I forget the specifics but this line of code fixed it:
if( (GetText(GetColumnValueAtRow(source, rowNum)) != "") && ((GetText(GetColumnValueAtRow(source, rowNum)) != null)) )
{
_comboBox.SelectedValue = GetText(GetColumnValueAtRow(source, rowNum));
}
It might be realted give it a shot.
|
|
|
|
|
i think the better fix would be instead of
if( (GetText(GetColumnValueAtRow(source, rowNum)) != "") && ((GetText(GetColumnValueAtRow(source, rowNum)) != null)) )
{
_comboBox.SelectedValue = GetText(GetColumnValueAtRow(source, rowNum));
}
you need
_comboBox.SelectedValue = GetColumnValueAtRow(source, rowNum);
without any checks
De O Bolonn
|
|
|
|
|
That's what I did originally, I think, but when I did this, if the GetColumnValueAtRow(source,rowNum) = null, then I think, the _comboBox goes to 0 instead of -1. There was a bug in there somewhere, so I had to add the GetText and the if. And it worked.
It's been awhile so I can't remember the exact bug.
|
|
|
|
|
the error is not within the code...
I had the same problem, untill i found out that my NullText was a string, where it should have been an integer...
so the mapping was this way:
DataGridComboBoxColumn cl = new DataGridComboBoxColumn("type",types,"Type","ID",dgBalen);
with "Type" the string to show, and "ID" the integer value...
Nulltext should be a string containing a value for "ID" (integer in this case)
this solved my problem right away...
|
|
|
|
|
I was using the code that you modified for this posting, that code was so buggy, you really cleaned it up well!
I modified the dropdownlist to a dropdown so the user can add his own info.
It worked with a few modifications:
1) Change the dropdownlist to dropdown in the constructor
2) Change: object _value = _comboBox.SelectedValue;
To: object _value = _comboBox.Text;
in Commit
(allows user data to be saved)
3) Add: _comboBox.Text=GetText(GetColumnValueAtRow(source, rowNum));
at the end of Edit.
(this allows the combobox to show the user data that was previously
entered, and he can now scroll up/down without losing his field)
4) Paint()
I deleted most of it, since it compare the data to the combobox, but if
the user entered data the combobox will not find a match. So I just force
the write everytime by doing this:
string _text = GetText(GetColumnValueAtRow(source, rowNum));
PaintText(g, bounds, _text, alignToRight);
These are the only 2 lines now in Paint.
That's it!
Hope this helps someone else!
If you see any bugs in my modifications, please let me know!
Thanks
|
|
|
|
|
I added a few more changes:
1)
Edit():
Change:
_comboBox.SelectedValue = GetText(GetColumnValueAtRow(source, rowNum));
To:
// Added this if statement to handle an error when the text field was null
if( (GetText(GetColumnValueAtRow(source, rowNum)) != "") && ((GetText(GetColumnValueAtRow(source, rowNum)) != null)) )
{
_comboBox.SelectedValue = GetText(GetColumnValueAtRow(source, rowNum));
}
2)
The .Visible will force the comboBox to be selected at Index 0, but will not display that value. When the user clicks off of the cell (without selecting a dropdown value) the Comit method will save whatever was selected, which would always be whatever was at Index 0. So, we force the Index back to -1, unselected.
After this line: _comboBox.Visible = true;
Add: _comboBox.SelectedIndex=-1;
I also had probs in the Comit() method. Problem was that if you clicked anywhere in the grid the combobox would trigger and whatever value was at index zero of the comboBox would auto-populate the cell. Also if the user did not enter any data the combobox would write a null to the dataSet and trigger the .HasChanges flag. So now this method checks before hand and if the cell in the dataSet is the same as the attepmted save the save will abort.
But now there is no way a user can enter a null, so a null must be included in the drop-down.
Here is the entire method:
///
/// Standard override
///
/// <param name="dataSource" />
/// <param name="rowNum" />
/// <returns>
protected override bool Commit(CurrencyManager dataSource,int rowNum)
{
//if(!_inEdit)
//{
// return true;
//}
// BugFix: Replaced the above if with the if below.
// We had the problem that the combobox would alter the DataSet when in fact it should not.
// This will not abort when the user has not typed anything and the Selected index is -1 (which we set from a proir bugfix)
if(((_comboBox.SelectedIndex==-1)&&(_comboBox.Text=="")) || !_inEdit)
{
Abort(rowNum);
return true;
}
try
{
//object _value = _comboBox.SelectedValue;
object _value = _comboBox.Text;
if(NullText.Equals(_value))
{
_value = System.Convert.DBNull;
}
// Added the if below which will not write a null if the data in the field is the same
// This will avoid setting the .hasChanges flag.
if(this.GetColumnValueAtRow(dataSource, rowNum)!=_value)
this.SetColumnValueAtRow(dataSource, rowNum, _value);
}
catch
{
// This catch will catch when a user enters the wrong data type.
// We store a null value then return true
this.SetColumnValueAtRow(dataSource, rowNum, System.DBNull.Value);
return true;
//return false;
}
finally
{
_inEdit=false;
_comboBox.Hide();
}
return true;
}
The commented out code was code from the original author.
I hope this helps someone.
|
|
|
|
|
I know you've made corrections since this, can you please post them?
Thanks so much!!!
|
|
|
|
|
Hello,
I have arequirement where I am supposed to wrap the text shown in a cell in the datagrid. What actually needs to be done is that the cell should grow in height to show its entire content.
Can anyone out there help me please ?
Jay.
|
|
|
|
|
This is a great piece of code! Thank you very much for sharing it!
Here's a couple things that I had to figure out that I hope will help others as they build this into their projects:
When setting the NullText property, note that this is really the default index of the ComboBox. So you'll probably want to set it to "0" so the first item will be selected when inserting new rows. I guess I didn't understand that from the article.
The first parameter of the constructor, "colName" must be the name of the column in the dataset that is being updated. The HeaderText property is set by default to this name, but you can change it if you want the column's name to appear differently in the DataGrid.
Again, thanks for the code!
|
|
|
|
|
I encountered this problem, but I don't think your suggestion is the best solution. It assumes that there's a value in the combobox corresponding to the value "0". In my case there wasn't and there's always the chance of your values "evolving" in the future, and we'd prefer to make this all data driven and not need to rebuild code when data changes.
I've changed the Edit method to detect null values, and to automatically select the first combobox choice in that case (which is a lousy way to do it, but is the default behavior for lists in any case).
object colval = GetColumnValueAtRow(source, rowNum);
if (colval != System.DBNull.Value )
{
_comboBox.SelectedValue = GetText( colval );
}
else
{
if (_comboBox.Items.Count > 0)
{
_comboBox.SelectedIndex = 0;
}
else
{
}
}
(note that last "else"; I haven't decided what to do when the combobox contains no choices)
|
|
|
|
|
Hi
Thanks for this code. It works fine. However, I do have one question: when using a ComboBox control it is usually possible to use the alt and down keys to open the dropdown and then the up and down keys to navigate through the item. This doesn't work with this implementation, because the keys responde to the DataGrid control and not to the ComboBox control. Any ideas how to implement this behaviour for our in-place-comboBox?
Thanks, Patrick
|
|
|
|
|
In your combo box constructor I think. i'v just copied from antoher project so I might have it backwards:
const int WM_KEYUP = 0x101;
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if(m.Msg == WM_KEYUP)
{
//ignore keyup to avoid problem with tabbing & dropdownlist;
return;
}
base.WndProc(ref m);
}
|
|
|
|
|
I made a minor change to the source, so as to get the alternating color effect:
.
.
.
in the Paint override....
PaintText(g, bounds, _text, alignToRight, rowNum%2 > 0);
}
// Helper functions
private void PaintText(Graphics g ,Rectangle bounds, string text,bool alignToRight, bool bAlternate)
{
Color clrBack = bAlternate ? this.DataGridTableStyle.AlternatingBackColor : this.DataGridTableStyle.BackColor;
Brush _backBrush = new SolidBrush(clrBack);
.
.
.
.
|
|
|
|
|
Hi, it realy works well , but i found a prob needed to fix.
I use this in a datagrid control to display a table such as TaskTable containing TaskName and TaskManger. I allow user to add a new task on the grid. Now, in the new line(last line on the grid with * on rowheader), click the combox to select a Manager, then move out the mouse, the comboxColumn Style's Commit function hasn't been invoked.
This is a real bug!! Please check it yourself.
|
|
|
|
|
I've recently discovered the same problem. Apparently, the inEdit property is not set to True on new entries. I'm trying to resolve the problem. If anyone's figured this out, please let us know here!
|
|
|
|
|
Has anyone got the solution to this bug?
If yes please mail me at swarup.agrawal@gmail.com
|
|
|
|
|
This is a great tool, but it tends to overwrite values in the cell if they're not in the lookup table. Is there a way to modify it so that we don't restrict cell values to one of the values in the lookup table?
|
|
|
|
|
Hi Jan,
I am converting your code to VB, but am running into a type conversion problem at the following line:
RectangleF _rectF = _rect;
In VB, I am typing:
Dim _rectF as RectangleF = _rect
Unfortunately, the compiler is telling me that Rectangle cannot be converted to RectangleF. Any help for this situation?
Thanks.
JT
|
|
|
|
|
The RectangleF structure is needed for the drawstring, but only the integer part is used this time. So, you might be able to copy all the members instead of copying the entire struct.
I reused the code myselves and i don't know VB, so i am not sure about this.
|
|
|
|
|
|
Hi,
I found that this works.
Dim _rectF As RectangleF = RectangleF.op_Implicit(_rect)
MW
|
|
|
|
|
Class DataGridComboBoxColumn inherits from DataGridColumnStyle,
but that's an abstract class.
Did you build it with the beta version?
Joan
|
|
|
|
|