Click here to Skip to main content
15,892,480 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am looking for solution to the issue of insert new or delete of a datagrid row that is not being identified or captured by simply checking dbcontext.changetracker.haschanges status. HasChanges picks up when user modifies existing datagrid row but (as I have read) insert and delete on a datagrids itemssource that is set using a collectionviewsource as in my case is not recognized by HasChanges. The numerous discussions on internet of this have so far not led me to the solution which must be a commmon one if this design is itself common. The reason for this is me and my lack of knowledge (this is my first WPF, MVVM EF app), so I would like to get a working example to review and learn from.

I bring in a list of items from the database that are used to populate combobox itemssource. The user may want add to, remove or modify this list so I have another view from which they can maintain this list. I can deal with the modify action because well thats automatically recognized when I use HasChanges, but am lost on how to identify that an insert or delete of a row has occurred. If I can understand how to determine or "capture" when this has occurred then I believe I know how to add/remove this from its class and can then save it to the database.

What I have tried:

I have tried all sorts of different binding options, xaml design of the datagrid and associated columns, read about messenger and Services. Appears that the more I look through internet the more complicated it appears.

One of my datagrids is as follows;

XML
<pre>        <DataGrid x:Name="siteDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True"  Grid.Column="0" Grid.Row="3"
                  ItemsSource="{Binding GeneralSitesViewSource, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="10,10,10,1" RowDetailsVisibilityMode="VisibleWhenSelected"
                  CellStyle="{StaticResource datagridcellstyle}" Height="110" Width="330">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="Site1Column" Binding="{Binding Site1}" Header="Site Name" Width="310"/>
            </DataGrid.Columns>
        </DataGrid>


Datagrid ItemsSource created as follows;

C#
private void FillGeneralSites()
                {
                    var q = (from a in Generalcontext.Sites
                             select a).ToList();
                _generalSites = new ObservableCollection<Site>(q);
GeneralSitesViewSource = CollectionViewSource.GetDefaultView(_generalSites);
GeneralSitesViewSource.SortDescriptions.Add(new SortDescription("Site1", ListSortDirection.Ascending));

        }
        public ICollectionView GeneralSitesViewSource { get; set; }
        private ObservableCollection<Site> _generalSites;
            public ObservableCollection<Site> GeneralSites
            {
                get
                {
                    return _generalSites;
                }
                set
                {
                    _generalSites = value;
                    OnPropertyChanged("GeneralSites");

                }
            }


Currently set up a check by using HasChanges only and if any modifications in which case save

C#
public bool CanClose()
{
    //check if saved context then return true or false etc

    if (Generalcontext.ChangeTracker.HasChanges())
    {
        MessageBoxResult msgresult = MessageBox.Show("Changes were not saved. Do you want to save your changes before exiting?", "EXIT WINDOW",
            MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
        if (msgresult == MessageBoxResult.Yes)
        {
            Generalcontext.SaveChanges();
            return true;
        }
        else if (msgresult == MessageBoxResult.No)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return true;
    }
}
Posted
Updated 12-Sep-20 12:56pm

1 solution

Too much "coupling". The Observable Collection doesn't interact with the data context. You add event handlers to the OC (i.e. CollectionChanged) that interact with the data context.

The entities in the OC should be "detached" from the DbContext if you want to maintain your sanity.
 
Share this answer
 
v2
Comments
Member 14892534 12-Sep-20 19:03pm    
Gerry appreciate you taking the time to reply. I will have to spend time digesting your advice. Is what this post is talking about the same as what you are suggesting? https://social.msdn.microsoft.com/Forums/en-US/b8f10fed-154d-4606-a777-dc6db578dd8d/observablecollection-and-oncollectionchanged?forum=wpf

If so that will get me going again.

Originally I wasnt using collectionviewsource for my datagrid itemssource but only observable collection but I saw a warning in VS immediate window about not good advice to use so I changed them all to collectionviewsource. that also allowed me to sort.
[no name] 12-Sep-20 20:40pm    
If you work with an ObservableCollection that contains entities that represent the dbContext but are detached, it's easier to "revert" and validate and manage the updates. The "changed" event tells you what's happening in the collection; you can decide to pass this on to the dbContext at you leisure. Otherwise, the attached entities in your dbContext get updated whether you want to or not; you then have to refresh from the DB.
Member 14892534 12-Sep-20 19:08pm    
actually if I stop trying to allow user to directly edit the row and instead get them to provide their new data if they want to add a row and then they click a submit button to add the row then its easier to manage. I wonder if this is better design as well as data input can be validated.

I think as a new coder I am suffering from lack of experience in design. Maybe I should at this stage go for simpler design which can make the coding easier rather than having a more advanced design which is still beyond my coding knowledge.
[no name] 12-Sep-20 20:45pm    
When a user wants to edit, I "show" a form or user control optimized for data entry / editing for the selected item. In the case of an add, I will "carry" data from a browsed item allowing simple "cloning" (if you will). The "data entry control / form" in effect "posts" to the OC.

"Grids" are great for browsing but rarely for complex data entry (and never faster).
Member 14892534 12-Sep-20 19:25pm    
I've got 25 lists that user may want to add to/modify. I dont want 25 views (windows) surely. Im going to try 25 datatemplates in a dictionary which give me the xaml for each list and swap those in and out of the 1 winow depending on which the user wants to modify. Will need 25 viewmodels but they will be simpler. I will test this out along with suggestion above to use event handlers and keep OC detached from DbContext.. at least will learn about dictionaries and datatempaltes and usercontrols and swapping views even if it fails.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900