Search code examples
c#winformsentity-frameworkdatagridviewbindingsource

Entity Framework: C# Winforms bindingsource delete on datagridview, but tag isDeleted field as true only (not delete)


I am currently working on a C# Winforms application with Entity Framework 5.

My problem is how to do a delete (which only tag isDeleted field as true) to an item on the bindingsource binded to an entity.

This is a screenshot of my form:

Enroll Medication Form

The DataGridView is bound to enrollmedsBindingSource. See this code of form load which fills the binding source:

    private void EnrollMedicationFrm_Load(object sender, EventArgs e)
    {
        context.enrollmeds.Where(adm => adm.FK_Admission == _SelectedPKAdm && adm.isDeleted == false).ToList();
        enrollmedsBindingSource.DataSource = context.enrollmeds.Local;
    }

As you can see on the above code, I filtered the data to display only the data which isDeleted is set to false.

Below is the code for my delete button:

    private void DeleteBtn_Click(object sender, EventArgs e)
    {
        if (enrollmedsDataGridView.CurrentRow == null)
        {
            MessageBox.Show("No item selected.", "System Alert", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        else
        {
            enrollmedsBindingSource.Remove(enrollmedsBindingSource.Current);
        }
    }

This code removes the item from the database if I call context.SaveChanges(); on save button.

Below is the code for save button:

    private void SaveBtn_Click(object sender, EventArgs e)
    {
        this.enrollmedsBindingSource.EndEdit();
        context.enrollmeds.Local
            .Where(a => a.C__PK_EnrollMeds == 0)
            .ToList().ForEach(i =>
            {
                i.FK_DC_Patient = pxdetails.pxDC.PK_Datacenter;
                i.FK_DC_userAdd = mainfrm.PK_DC_UserLoggedIn;
                i.AddDateTime = currdatetime;
                i.FK_Admission = pxdetails.adm.PK_Admission;
            });
        this.context.SaveChanges();
        enrollmedsDataGridView.Refresh();
        this.Dispose();
    }

What I want to do, is to remove the entry on the DataGridView (from user's view) but only tag the isDeleted field is true in the database (for audit purposes).

Note: The save button only clicked once the user is done on all the changes, so the form need to capture what is deleted (isDeleted), changed, and added upon saving.


Solution

  • You should set IsDeleted property of your entity to true and the call SaveChanges. For example, if you have a Product entity:

    var p = (Product)bindingSource.Current;
    p.IsDeleted = true;
    db.SaveChanges();
    

    Then if you are not going to reload data, you can remove the item from list to not show it:

    bs.RemoveCurrent();
    db.Entry(p).State = EntityState.Detached;
    

    Or you can reload data:

    db.Products.Where(x => x.IsDeleted == false).Load();
    bindingSource.DataSource = db.Products.Local;
    

    Note

    If you are not going to save changes immediately, you need to do something else after setting IsDeletet to true:

    • You can stop working connected to context and use a BindingList<T> or ObservableCollection<T> for data-binding and track data changes yourself. Then you can simply have a list of deleted items to set their IsDeleted property to true when saving changes.

    • As another option, after setting IsDeleetd to true, you can change the appearance of deleted rows in DataGridView. For example, you can handle RowPostPaint event of DataGridView and draw a red strikeout like over the row.