Hi,
I have a win grid with the new row template at the top and combo box outside the panel of the grid. When i click on the new row template, start editing it and leave before filling all the fields (i.e. i click on some other field outside grid panel), the new row gets added to the grid which is undesirable as few of the mandatory fields are left blank. The new row needs to be validated before getting added to the grid.
I added this event BeforeRowUpdate and doing the following to validate the fields.
Though i am able to validate this way, but the partially filled new row is getting lost after this instead of being retained.
void gridOwner_BeforeRowUpdate(object sender, CancelableRowEventArgse)
{
if (e.Row.IsAddRow)
foreach ( UltraGridCell item in e.Row.Cells)
if (item.Value.ToString().Trim().Length <= 0 && !item.Column.Hidden)
MessageBox.Show("Please select a value for " + item.Column.Header.Caption.ToString());
e.Cancel = true;
break;
}
There fore, i am looking for some way to validate the new row before adding to the grid and even if the validation fails, the new row should not be discarded rather it should be held in the template where it is entered.
Thanks in advance,
Parthiban Sekar
Hello ,
I could suggest you to use BeforeRowDeactivate event and to put your validation code there. So in this event you should have code like:
if (ultraGrid1.ActiveRow.IsAddRow)
foreach (UltraGridCell item in ultraGrid1.ActiveRow.Cells)
ultraGrid1.ActiveCell = item;
ultraGrid1.PerformAction(UltraGridAction.EnterEditMode);
Also if you want to prevent user to commit AddRow pressing Enter (if the validation was not passed), then you should add the following code in load event of the form in order to modify default behavior of UltraGrid for pressing Enter key when the active row is AddRow
foreach (GridKeyActionMapping key in ultraGrid1.KeyActionMappings)
if (key.KeyCode == Keys.Enter && key.ActionCode == UltraGridAction.CommitRow && key.StateRequired == (UltraGridState.AddRow| UltraGridState.RowDirty))
key.StateRequired = UltraGridState.RowDirty;
key.StateDisallowed = UltraGridState.AddRow;
Please let me know if you have any further questions.
Hristo,
Thanks for your input.
I am able to validate using "BeforeRowDeactivate" or "BeforeRowDeactivate".
What i am interested in is to retain the new row in the new template if it fails validation (If it passes, it would be added to grid as usual).
But, by using neither of the above said two events, i was not able to retain the new row which fail validation.
Regards,
Some more points on "BeforeRowDeactivate" are as follows.
grid.ActiveRow.IsAddRow is false when i edit a new row and it is getting triggered before the edit and validation is not happening after the edit .
Kindly help out.
Thanks,
Hello,
Have you tried to implement my suggestions in a simple sample and what’s happens after you ran this sample? I have implemented the code snippet which I have provided you in a small sample, please run the sample and enter some text in a column Col0 , press TAB key, try to click on the template add row, press "Enter" key in order to close message dialog, press "Escape" key twice in order to decline changes.
Please let me know if you have any further questions or I am missing something.
Not able to open the attached sample. I have VS2008.
Btw, i have implemented everything you suggested. But the event BeforeRowDeactivate is not getting triggered after the edit
and
grid.ActiveRow.IsAddRow is false when i edit the new row (The event gets triggered when i click on new row template)
I have modify my sample to work with Visual Studio 2008, now you should be able to run and test the sample.
I really appreciate your efforts to help me.
To replicate what i am facing, please do the following changes.
1. Add a combo below the grid ( or wherever but away from the grid panel )
2. Now run the app, start editing the new row template but dont enter all fields , now click on the drop down (outside grid panel).
For me the validation did not happen and row got added to the grid.
The modified sln is attached.
Well, here's what I did
Dim thisBand As UltraGridBand = e.Row.BandUltraGrid1.ActiveRow = UltraGrid1.ActiveRowScrollRegion.FirstRowe.Row.Delete(False)Dim row As UltraGridRow = thisBand.AddNew()
UltraGrid1.ActiveCell = row.Cells(activecellKey)
I now have the thought though that if the AddNew row is the first row being added to the band that UltraGrid1.ActiveRowScrollRegion.FirstRow will probably fail?
Since it's a child band it will always have a parent row, so your suggestion of getting the reference to the Parent row is probably a more robust solution, and the code actually instantiates a new AddNew row and makes it active so it should end up in the right place.
I'll implement and post back.
It seems like you need another row in the same collection to activate in order to provide the proper context. So what you could do is... before you call e.Row.Delete, access e.Row.ParentCollection and see if there are any other rows in the collection besides the one you are about to delete. If so, you could store that row in a variable and activate it right before you call AddNew on the Band. Of course, the problem with that is that the row being deleted might be the last row in the collection. So if there are no other rows, and the row being deleted is a child row, then you could store a reference to it's Parent row and that should be sufficient to provide context.
Actually, now that I think about it, you might want to just check for the Parent Row first. If there is one, store it and then activate it right before you call AddNew. If there is no parent, then presumably there won't be a problem since you are dealing with a root-level row and no context is needed.
Resurrecting this old thread, I'm trying to adapt this example to a grid which has several bands from a hierarchical datasource.
From what I understand here, there is a validation performed. When the validation fails, the values already entered are stored, the row being created is deleted, a new row is created with AddRow, and the new row is populated with the values which were stored.
void ultraGrid1_BeforeRowUpdate(object sender, CancelableRowEventArgs e) { if (ultraGrid1.ActiveRow.IsAddRow) { e.Cancel = ValidateRowFall(ultraGrid1.ActiveRow); if (!e.Cancel) return; ultraGrid1.BeginUpdate(); ultraGrid1.BeforeRowUpdate -= new CancelableRowEventHandler(ultraGrid1_BeforeRowUpdate); string activecellKey = ultraGrid1.ActiveCell.Column.Key; Dictionary<string, object> rolItems = new Dictionary<string, object>(); foreach (UltraGridCell cell in e.Row.Cells) rolItems.Add(cell.Column.Key, cell.Value); e.Row.Delete(false); UltraGridRow row =e.Row.Band.AddNew(); foreach (UltraGridCell cell in e.Row.Cells) row.Cells[cell.Column.Key].SetValue(rolItems[cell.Column.Key], true); ultraGrid1.ActiveCell = row.Cells[activecellKey]; ultraGrid1.BeforeRowUpdate += new CancelableRowEventHandler(ultraGrid1_BeforeRowUpdate); ultraGrid1.EndUpdate(); ultraGrid1.PerformAction(UltraGridAction.EnterEditMode); } }
However ... when e.Row.Delete(false); is executed and e.row is in a child band, it appears the grid doesn't have an active row and fires an error
"Not enough context to add a new row. Either a row in this band or the parent band has to be active to provide for enough context."
Any quick fix to select a row to become active in the child band so the code can finish?
Sorry, Figured that ENTER key issue out. Thanks again,
Thanks Hristo,
Thats what i exactly need!
I just need one more thing.
In my grid, when i press "Enter" key, no action or event occurs as of now but it happens in your sample.
Could you tell me what i need to do to enable Row adding on pressing ENTER?