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); }
This is pretty much the only way that I can think of to get the functionality that you are looking for. Grabbing the editor and setting a value into it will cause the underlying data to be created. This is basically the approach I would end up suggesting. And you even have the code handle different value types which is awesome. This should prove useful to the community.
I know this is an old post but here is what I do with Infragistics WPF 22.1
private void btnAdd_Click(object sender, RoutedEventArgs e) { xamDataGrid1.FieldLayoutSettings.AllowAddNew = true; Dispatcher.BeginInvoke(new Action(() => {
// Force the creation of the addRecord and enter a value in the first field so that the default values of the underlying object are displayedCellValuePresenter.FromCell(xamDataGrid1.RecordManager.CurrentAddRecord.Cells[0]).Editor.StartEditMode(); CellValuePresenter.FromCell(xamDataGrid1.RecordManager.CurrentAddRecord.Cells[0]).Editor.Value = 0;
// Move to the next cell to exit the edition mode xamDataGrid1.ExecuteCommand(DataPresenterCommands.CellRight); xamDataGrid1.ExecuteCommand(DataPresenterCommands.CellLeft); }), DispatcherPriority.Background, null); }
Hi Community,
because my sample code above uses some of my own helper classes,you will not be able to use it.
I gained a lot of help from this forum so far,so I decided to create a sample application which demonstrates the instantly initializing AddNew record.
To even make it more useful,the complete logic is encapsulated in an interactivity behavior.
@Rob:Could you try to run this sample?If it works, you can mark this post as veryfied answer :-)