Hello,
My grid provides the AddNew record, but additionally I want the user to be able to create a new record by a keyboard shortcut and a ribbon button.In the code behind the following code is executed when the user initiates this command:
grid.ExecuteCommand(DataPresenterCommands.EndEditModeAndCommitRecord);grid.ActiveRecord = grid.RecordManager.CurrentAddRecord;grid.ExecuteCommand(DataPresenterCommands.CellFirstInRecord);grid.ExecuteCommand(DataPresenterCommands.StartEditMode);
This commits and current editing, activates the AddNewRecord line and puts the first cell in edit mode.So far - so good.
Unfortunately the underlying business object is not initialized by this action.Only when the user starts typing, the object is created and initialized.How can I bring the grid to do this initializing on its own?
Thank you for any hint.
BTW: how can I paste code with syntax highlighting?I even tried the paste-from-word thing, but after inserting the coloring and formatting is gone...
Hello J_Feuerstein,
By default the XamDataGrid does not create the underlying record for the AddNewRecord until there is actual data entered into the cell. It doesn't make sense to create the item if there is no data for it. When the user presses the keyboard shortcut or ribbon button, what is the exact behavior you are looking for? If all you want to do is have a new record created you can do this via a view model command which then adds a new item to the underlying datasource. If your datasource implements INotifyCollectionChanged then a new record will be added to the XamDataGrid automatically.
I coded the following hack to get the wanted behavior.It is ugly, but works. Maybe you have a better suggestion...
private void AddNewTimeBookingEntry() { var grid = TimeBookingDataGrid; if (grid.RecordManager.CurrentAddRecord == grid.ActiveRecord) return; // commit any current edit action and set the active record to the AddNew row grid.ExecuteCommand(DataPresenterCommands.EndEditModeAndCommitRecord); grid.ActiveRecord = grid.RecordManager.CurrentAddRecord; var record = grid.ActiveRecord; if (record == null) return; // get the DataRecord of the AddNewRow var dataRecord = record as DataRecord; if (dataRecord == null || !dataRecord.IsAddRecord) return; // only proceed if there is not DataItem assocciated so far if (dataRecord.DataItem != null) return; // get the first ValueEditor from the available cells // which has a simply constructable value type var valueEditor = dataRecord.Cells .Select(CellValuePresenter.FromCell) .Where(x => x != null) .Select(x => x.Editor) .FirstOrDefault(x => x.ValueType.IsPrimitive || x.ValueType.IsValueType); if (valueEditor == null) return; // if the value type is nullable, fetch the underlying type instead var valueType = valueEditor.ValueType.IsNullable() ? Nullable.GetUnderlyingType(valueEditor.ValueType) : valueEditor.ValueType; // create a dummy instance of the value type var initialValue = Activator.CreateInstance(valueType); // simulate input of the dummy value and cancel it again // this forces the grid to create the underlying data instance. valueEditor.StartEditMode(); valueEditor.Value = initialValue; valueEditor.EndEditMode(acceptChanges: false, force: true); // get the first field which has a TabStop var orderedFields = TimeBookingDataGrid.FieldLayouts.First() .Fields.OrderBy(x => x.ActualPosition.Column); var firstTabStopField = orderedFields.FirstOrDefault(x => (bool)x.GetValue(FieldTabStopBehavior.EnabledProperty)); // get the cell from the current record according to the field // and activate it var firstTabStopCell = dataRecord.Cells.FirstOrDefault(x => x.Field.Equals(firstTabStopField)); grid.ActiveCell = firstTabStopCell; // start edit mode for the user grid.ExecuteCommand(DataPresenterCommands.StartEditMode); }
private void AddNewTimeBookingEntry() { var grid = TimeBookingDataGrid; if (grid.RecordManager.CurrentAddRecord == grid.ActiveRecord) return;
// commit any current edit action and set the active record to the AddNew row grid.ExecuteCommand(DataPresenterCommands.EndEditModeAndCommitRecord); grid.ActiveRecord = grid.RecordManager.CurrentAddRecord;
var record = grid.ActiveRecord; if (record == null) return;
// get the DataRecord of the AddNewRow var dataRecord = record as DataRecord; if (dataRecord == null || !dataRecord.IsAddRecord) return;
// only proceed if there is not DataItem assocciated so far if (dataRecord.DataItem != null) return;
// get the first ValueEditor from the available cells // which has a simply constructable value type var valueEditor = dataRecord.Cells .Select(CellValuePresenter.FromCell) .Where(x => x != null) .Select(x => x.Editor) .FirstOrDefault(x => x.ValueType.IsPrimitive || x.ValueType.IsValueType); if (valueEditor == null) return;
// if the value type is nullable, fetch the underlying type instead var valueType = valueEditor.ValueType.IsNullable() ? Nullable.GetUnderlyingType(valueEditor.ValueType) : valueEditor.ValueType; // create a dummy instance of the value type var initialValue = Activator.CreateInstance(valueType);
// simulate input of the dummy value and cancel it again // this forces the grid to create the underlying data instance. valueEditor.StartEditMode(); valueEditor.Value = initialValue; valueEditor.EndEditMode(acceptChanges: false, force: true);
// get the first field which has a TabStop var orderedFields = TimeBookingDataGrid.FieldLayouts.First() .Fields.OrderBy(x => x.ActualPosition.Column); var firstTabStopField = orderedFields.FirstOrDefault(x => (bool)x.GetValue(FieldTabStopBehavior.EnabledProperty)); // get the cell from the current record according to the field // and activate it var firstTabStopCell = dataRecord.Cells.FirstOrDefault(x => x.Field.Equals(firstTabStopField)); grid.ActiveCell = firstTabStopCell;
// start edit mode for the user grid.ExecuteCommand(DataPresenterCommands.StartEditMode); }
Hello Rob,
thank you for response.The default behavior may be suitable in many cases.But my data object is initialized with default values on each field.When the user starts input in any cell, the default value for this cell is instantly overwritten.
Further I want to use the built-in AddNewRow feature.When I go the way you suggest by adding the new record to the vievmodel collection,it is a row like any other. For example canceling edit will not remove it automatically,and it is not located where the empty AddNewRow is.
My goal is that even when the user only clicks on any cell of the empty AddNewRow,instantly the data object is instantiated and the clicked column is in edit mode with the default data of this column.But it has to stay in add-new mode, not commited in any way.
Hope you can give me a hint on this.Thanks a lot.