I'm adding a row in a two way bound xamDataGrid via an ObservableCollection.
When the user clicks an add button, I instantiate a new object of the type in the collection and stuff it with values and make it the ActiveDataItem which I can see on the screen. Because the text boxes in my detail screen are bound to the ActiveDataItem in the grid, those boxes are populated with the new data. So far so good.
Then when the user starts changing data in the text boxes, the data in the grid changes which is fine. When the user clicks on the save button, I add the ActiveDataItem to my database and get a new id, and because I'm using two way databinding, the new id shows up in the detail text box and then in the id column in the grid.
So, everything is now great. The row has been added to my database, and it is also showing in the grid which is exactly what I want. The problem is now if I click on any other row in the database, the new row I added disappears. How do I fix this?
Thank you.
Hello Mike,
I have been looking into your post and I am not sure what exactly you are doing. The ‘AllowAddNew’ property only works with DataSource that does implement the ‘IBindingList’ and ‘IBindingListAllowNew’ interfaces :
http://help.infragistics.com/NetAdvantage/WPF/2011.2/CLR4.0/?page=InfragisticsWPF4.DataPresenter.v11.2~Infragistics.Windows.DataPresenter.FieldLayoutSettings~AllowAddNew.html
I am not able to reproduce your scenario using Observable Collection as a data source because of the reasons mentioned above.
If I have misunderstood you in any way, feel free to tell me.
Here is what I am doing. When the user clicks on the add button, the follow code executes:
private void bAdd_Click( object sender, RoutedEventArgs e ) { try { // // Builds the undo stack in the object // ( this.dgPDUsers.ActiveDataItem as PDUser ).BeginEdit(); PDUser p = new PDUser() { PDUserID = -1, Password = "change me please", FirstName = "Change me", LastName = "Change me", Name = "Me, Change", LockedOut = 0, ActiveName = "Yes", Active = 1, Deleted = 0 }; // // Add the new patient to the list. // ( this.dgPDUsers.DataSource as ObservableCollection<PDUser> ).Add( p ); // // highlight the new row. // DataRecord dr = this.dgPDUsers.GetRecordFromDataItem( p, false ); this.dgPDUsers.BringRecordIntoView( dr ); this.SetActiveRecord( dr.Index ); // // Highlight selected clinics // this.SetSelectedClinics(); // // Highlight selected roles // this.SetSelectedRoles(); // // Set passwords // this.txtPassword.Password = ( this.dgPDUsers.ActiveDataItem as PDUser ).Password; this.txtPasswordVerify.Password = ( this.dgPDUsers.ActiveDataItem as PDUser ).Password; // // Set the mode and call mode manager // this.SetMode( Mode.Add ); this.ModeManager(); // // Send begin add event // this.AppData.Events.OnBeginAdd( new BeginAddEventArgs( this.ToString(), this.AppData.CurrentLoggedInPDUser ) ); } catch( Exception ex ) { MessageBox.Show( ex.Message + ex.StackTrace, "Add PDUser Error", MessageBoxButton.OK, MessageBoxImage.Error ); } }
Just for clarity I am posting my SetActiveRecord() which is the code below.
private void SetActiveRecord( int SelectedRow ) { try { if( this.dgPDUsers.Records.Count > 0 ) { // // Why oh why Infragistics... // this.dgPDUsers.SelectedItems.Records.Clear(); this.dgPDUsers.Records[ SelectedRow ].IsSelected = true; this.dgPDUsers.Records[ SelectedRow ].IsActive = true; this.dgPDUsers.ActiveRecord = this.dgPDUsers.Records[ SelectedRow ]; this.dgPDUsers.ActiveDataItem = this.dgPDUsers.Records[ SelectedRow ]; this.dgPDUsers.BringRecordIntoView( this.dgPDUsers.Records[ SelectedRow ] ); } } catch( Exception ) { throw; } }
Now we have a record in the grid which is at the bottom and visible with an ID of -1. Because the text boxes are bound two ways to the ActiveDataItem in the grid, the values we set in the class are also visible. When I make edits to the text boxes, the changes are also reflected in the grid as well. This is as expected and works the way I want it to.
Next the user clicks save and the following code is executed.
private void Add() { try { ( this.dgPDUsers.ActiveDataItem as PDUser ).Add(); if( !( this.dgPDUsers.ActiveDataItem as PDUser ).IsValid ) { // // Build error message string for display // MessageBox.Show( this.BuildErrorMessage( "The PD User could not be added because of the following errors: " ), "Add Error Message", MessageBoxButton.OK, MessageBoxImage.Information ); } else { // // Cleans up the undo stack in the object // ( this.dgPDUsers.ActiveDataItem as PDUser ).EndEdit(); // // Set Mode // this.SetMode( Mode.View ); // // Send the end add event // this.AppData.Events.OnEndAdd( new EndAddEventArgs( this.ToString(), this.AppData.CurrentLoggedInPDUser ) ); // // Call mode manager to redraw UI // this.ModeManager(); } } catch( Exception ) { throw; } }
This code adds the class to the database and an ID is assigned. Since the object is two way bound, when the ID property is changed with the new ID, it is also reflected in both the grid and in the ID text box. Again, this is expected and works the way I want it to.
So, now I have what I want in the grid with the user input values and the ID assigned by the database. However the issue for me is that once I click on any row in the grid, the newly added row disappears. I am using an ObservableCollection to bind to the grid.
I don't want the users to be editing data in the grid because it only is a subset of the detail, something that provides enough information to be useful, but not every data point that needs to be edited.
If this issue is perplexing you after reviewing my details, is it possible for you run it by your colleagues for an additional perspective? I'm also providing my XAML code as that might also be helpful.
<igDP:XamDataGrid Grid.Row="0" HorizontalAlignment="Stretch" x:Name="dgPDUsers" DataSource="{Binding DataContext.PDUsers, ElementName=ManageUserViewModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" IsSynchronizedWithCurrentItem="True" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" Loaded="dgPDUsers_Loaded" Margin="0" SelectedItemsChanged="dgPDUsers_SelectedItemsChanged"> <igDP:XamDataGrid.FieldLayouts> <igDP:FieldLayout Key="Expanded"> <igDP:Field Name="PDUserID" Label="User ID" Width="65" IsPrimary="True" /> <igDP:Field Name="Name" Label="Name" Width="105" Visibility="Collapsed" IsScrollTipField="True" /> <igDP:Field Name="FirstName" Label="First Name" Width="105" /> <igDP:Field Name="LastName" Label="Last Name" Width="105"/> <igDP:Field Name="LockedOut" Label="Locked Out" Width="90" /> <igDP:Field Name="ActiveName" Label="Active" Width="80" /> </igDP:FieldLayout> </igDP:XamDataGrid.FieldLayouts> <igDP:XamDataGrid.FieldSettings> <igDP:FieldSettings CellClickAction="SelectRecord" LabelClickAction="SortByMultipleFields" AllowEdit="True" AllowRecordFiltering="True" /> </igDP:XamDataGrid.FieldSettings> <igDP:XamDataGrid.FieldLayoutSettings> <igDP:FieldLayoutSettings AutoGenerateFields="False" HighlightAlternateRecords="True" AllowDelete="False" FilterClearButtonLocation="RecordSelector" FilterRecordLocation="OnTopFixed" FilterUIType="Default" /> </igDP:XamDataGrid.FieldLayoutSettings> </igDP:XamDataGrid>
Thank you for your help, Yanko.
Regards,
Mike Malter
Ah, AllowAddNew was not set in my FieldLayoutSettings. I'll try that and see what happens.