views:

381

answers:

2

Hi folks. It's a pleasure to see how much knowledge people have on here, it's a treasure of a place. I've seen myself writing code for DataGridView events - and using DataSource to a backend prepared DataTable object.

Sometimes the user can remove rows, update them etc. and the underlying data will need validation checks again.

Let's assume we have a person class

class Person {
    public string FirstName { get; set; }       
}

Let's say some other part of the code deals with creating an array of Person.

class Processor {
       public static Person[] Create()
       {
           ....
           ....
           return person[];
       }
}

And this information would appear on a DataGridView for user viewing. I've tried something like this:

public static DataTable ToTable(List<Person> list)
{   ...   }

And had this method in the Person class .. which I would think it'd belong to. Then I would bind the DataGridView to that DataTable and the user will then see that data and do their tasks.

But I've thought of using BindingList<> which I'm not so educated on yet.. would I still have the same capability of sorting the DataGridView like it does with DataTable as a DataSource? Would BindingList be implemented by a container class like "PersonCollection" or would the Person class implement itself? I would like to fire some events to be able to modify the collection in a clean way without having to reset datasources, etc. Where the user experience could really be affected.

I understand that modifying the DataSource DataTable is the good way. But sometimes I need to fire methods in the corresponding class that that specific row refers to, and had an ugly extra hidden column which would hold a reference to the existing object somewhere else (the Person reference).

If you guys know a better design solution, I would be more than happy to hear it. Thanks in advance,

PS. After reading "The Pragmatic Programmer", I just can't stop thinking critically about code!

Leo B.

+2  A: 

Create a business object class. Implement INotifyPropertyChanged. Look at the code below:

public class Employee:INotifyPropertyChanged
    {
        public Employee(string Name_, string Designation_, DateTime BirthDate_)
        {
            this.Name = Name_;
            this.Designation = Designation_;
            this.BirthDate = BirthDate_;
        }


        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        [DisplayName("Employee Name")]
        public string Name
        {
            get { return this._Name; }

            set
            {
                if (value != this._Name)
                {
                    this._Name = value;
                    NotifyPropertyChanged("Name");
                }
            }
        }
        private string _Name = string.Empty;

        [DisplayName("Employee Designation")]
        public string Designation
        {
            get { return this._Designation; }

            set
            {
                if (value != this._Designation)
                {
                    this._Designation = value;
                    NotifyPropertyChanged("Designation");
                }
            }
        }
        private string _Designation = string.Empty;

        public DateTime BirthDate
        {
            get { return this._BirthDate; }

            set
            {
                if (value != this._BirthDate)
                {
                    this._BirthDate = value;
                    NotifyPropertyChanged("BirthDate");
                }
            }
        }
        private DateTime _BirthDate = DateTime.Today;

        [DisplayName("Age")]
        public int Age
        {
            get
            {
                return DateTime.Today.Year - this.BirthDate.Year;
            }
        }
  }

Create your custom collection:

public class EmployeeCollection:BindingList<Employee>
    {
        public new void  Add(Employee emp)
        {
            base.Add(emp);
        }

        public void SaveToDB()
        {
           //code to save to db
        }
    }

Set the data source:

 _employeeStore = new EmployeeCollection(); 
this.dataGridView1.DataBindings.Add("DataSource", this, "EmployeeStore");

Now if you want to add an employee to your datagridview,

Employee employee = new Employee(textBoxName.Text, textBoxDesignation.Text, dateTimePicker1.Value);            
_employeeStore.Add(employee);

This is very clean. You just play with business object and don't touch the UI.

P.K
INotifyPropertyChanged is to ensure that the changes you make to the list flow to the UI. further you can also have your BO class implement IDataErrorInfo to have custom error information which the UI can capture. This way you will have all your validation in Business logic code.
P.K
When you do DataBindings.Add.. we assume there is a property in the Form object called EmployeeStore, correct?
lb
Can't sort the datagrid automatically like I did with DataTable though..:(
lb
I've looked at sorting - overriding BindingList sorting func - yeeks!But this looks good.
lb
yes you will have to create a propery called EmployeeStore which returns _employeeStore.
P.K
+1  A: 

Havent read you question fully, bbut you might want to take a look at my Project ModelShredder, which provides a convinient and fast ToDataTable method

Johannes Rudolph
That's pretty.I think I need a lot of power over how the members are read into the table.. it's not a simple member-to-column transfer; I need to manually call business methods as variables are changed in the UI.And "Modifying an anonimous method will stop the current debugging session.." is very annoying.Thanks for the hint, I'll keep in mind.
lb
You certainly have control over how your model is translated to a DataTable via a DataLoadOption like interface. I will add support for Translating Objects to simple DataSets (Table with relations, think of simple reverse ORM) soon
Johannes Rudolph
That sounds good - keep me posted.
lb