0

I was doing some test about complex .NET databinding, and i need to have some advice in order to rollback changes made by the user. Let's assume, for example, that i've got 2 classes in my BL layer:

"Person" represent the core person object:

internal class Person{
  public String Name{get; set;}            
  public String Surname{get; set;}
  public int Age { get; set; }
 }

"PeopleList" represent the list of person object:

internal class PeopleList : List<Person> {

//Let's assume that this class has a whole bunch of function with a complex business logic in it.

    public Person[] getPeopleByName(String name)
    {
        return this.Where(x => String.Compare(name, x.Name, true) == 0).ToArray(); 
    }

    public Person[] getPeopleByAge(int age)
    {
        return this.Where(x => x.Age.Equals(age)).ToArray();
    }
}

Now i want to let user edit an instance of a PeopleList object through a form with a DataGridView. So i created a windows form application and in Load() event i did this:

 private void frmTest_Load(object sender, EventArgs e)
        {

            //Intialize _peopleList object 
            _peopleList = new PeopleList();
            this.initializePeopleWithTestData();

            //Initialize _peopleBindingList by passing PeopleList (it inherits from List<Of ?> and it implements IList interface)
            this._peopleBindingList = new BindingList<Person>( _peopleList);

            //Initialize _peopleBindingSource 
            this._peopleBindingSource = new BindingSource();
            this._peopleBindingSource.DataSource = this._peopleBindingList;
            this._peopleBindingSource.SuspendBinding(); //Let's suspend binding to avoid _peopleList to be modified. 

            //Set peopleBindingList as DataSource of the grid
            this.dgwPeople.DataSource = _peopleBindingSource;
        }

With the above-mentioned code i can see/edit/delete/add people in dgwPeople (that's my datagridview) without problem, but even if i called "SuspendBinding()" over the BindingSource, if the user edits the grid, the binding system immediately affects the data contained into my _peopleList object! And this is not good because in this way i loose the original version of my data and i can't rollback them no more if the user decide to cancel changes.!

In the simple binding there's a fantastic attribute "DataSourceUpdateMode" that let me decide when the binding has to affect the datasource. If i set it to "Never" i have to call explicitly the Write() method to commit changes. Is there something similar for the complex binding?

How can i avoid binding to affect my original data immediately in complex binding? Is there any way to rollback changes (apart from keep a clone copy of the original object)? Is there any pattern that helps in handling this kind of situations?

You can download my test solution (VS2012) here

Thanks in advance!

Kara
  • 6,115
  • 16
  • 50
  • 57
GiveEmTheBoot
  • 534
  • 9
  • 24
  • A DataTable will do this via AcceptChanges. Or in the class you could hold the original value or you could make a copy of the data in the class. I would add an AcceptChanges or RollBackChanges to the class. – paparazzo Nov 30 '13 at 14:25
  • Thank you for your response. Effectively your it's a quite elegant solution, but applicable only in certain contexts ...in real case business classes like "Person" and "PersonList" are usually in separate logic assemblies (so it's very difficult to make changes). Furthermore these assemblies hasn't got references to UI stuff, so i don't think it's a good idea let a business class implement UI-related methods/interface like "INotifiyPropertyChanged". Am i completely wrong? – GiveEmTheBoot Nov 30 '13 at 20:06
  • 1
    If INotifiyPropertyChanged is completely wrong then Microsoft got it completely wrong. Just how do you expect to bubble changes from the data layer to the UI if you don't implement INotifiyPropertyChanged? How is rollback a UI thing? – paparazzo Nov 30 '13 at 20:40
  • Ok, got it! And what about the peopleList object? If someone add/delete people to the list, how can I rollback changes? Do I need to implement AcceptChanges() and RollbackChanges() even in PeopleList class? If i do this, it turns out that i need to make a deep copy of my original list..is it the right approach? – GiveEmTheBoot Dec 01 '13 at 11:13
  • I would create a custom collection the implements List with those extentions – paparazzo Dec 01 '13 at 11:23

1 Answers1

1
internal class Person, iNotifyPropertyChanged
{
  // todo implement NotifyPropertyChanged 
  private string name;
  private string nameOrig;
  public String Name
  {
     get {return name; } 
     set 
     {
        if (name == value) return;
        name = value;
        NotifyPropertyChanged("Name");
     }
  }
  public void RollBack() { Name = nameOrig; }
  public void CommitChanges()  {  nameOrig = name; }            
  public Person (string Name) { name = Name; nameOrig = name; }
}
paparazzo
  • 44,497
  • 23
  • 105
  • 176