You could just make your list actually expose the needed interfaces for a DataTable (derive from IBindingList on the list, IEditableObject on the items), then you don't need to create a DataTable at all!
Marc Sample class below (Outlook syntax checker in scope): public class ListOfLines : ArrayList, IBindingList { public class OneLine : IEditableObject { public OneLine() { } #region IEditableObject private void OnListChanged() { int index = m_ParentCollection.IndexOf(this); m_ParentCollection.OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); } public void BeginEdit() {} public void CancelEdit() {} public void EndEdit() {} #region IEditableObject_Impl private ListOfLines m_ParentCollection; // used for notifications internal ListOfLines ParentCollection { get {return m_ParentCollection;} set { m_ParentCollection = value; } } #endregion IEditableObject_Impl #endregion IEditableObject #region YourPropertiesHere private string m_GroupKey; private int m_Quantity; private string m_Description; #region Properties public string SortKey { get { return m_SortKey; } set { m_SortKey = value;} } public int Quantity { get { return m_Quantity; } set { m_Quantity = value; } } public string Description { get { return m_Description; } set { m_Description = value; } } #endregion Properties #endregion YourPropertiesHere public class Comparer : System.Collections.IComparer { public int Compare(object x, object y) { OneLine first = (OneLine)x; OneLine second = (OneLine)y; return first.SortKey.CompareTo(second.SortKey); } } } private OneLine.Comparer m_Comparer = new OneLine.Comparer(); private bool m_MustResort = false; public override int Add(object record) { OneLine sumLine = record as OneLine; if (sumLine == null) { throw new ArgumentException("Element to add must be of type OneLine", "record"); } return this.Add(sumLine); } public override void Insert(int index, object record) { this.Insert(index, record); } public int Add(OneLine record) { int insertIndex; insertIndex = base.Add(record); record.ParentCollection = this; OnInsertComplete(base.Count - 1, record); return insertIndex; } public void Insert(int index, OneLine record) { base.Insert(index, (object)record); record.ParentCollection = this; OnInsertComplete(index, record); } public new OneLine this[int idx] { get { SortList(); return (OneLine) base[idx]; } } public OneLine this[string key] { get { foreach (OneLine curLine in this) { if (curLine.GroupKey == key) { return curLine; } } return null; } } public int IndexOf(OneLine record) { SortList(); return base.IndexOf(record); } public override System.Collections.IEnumerator GetEnumerator() { SortList(); return base.GetEnumerator(); } public override System.Collections.IEnumerator GetEnumerator(int index, int count) { SortList(); return base.GetEnumerator(index, count); } public override System.Collections.ArrayList GetRange(int index, int count) { SortList(); return base.GetRange(index, count); } public override void Clear() { if (this.Count > 0) { OneLine first = this[0]; base.Clear(); OnRemoveComplete(0, first); } } public override void Remove(object obj) { int indexof = base.IndexOf(obj); base.Remove(obj); OnRemoveComplete(indexof, obj); } public override void RemoveAt(int index) { OneLine first = this[index]; base.RemoveAt(index); OnRemoveComplete(index, first); } public override void RemoveRange(int index, int count) { OneLine first = this[index]; base.RemoveRange(index, count); OnRemoveComplete(index, first); } protected void SortList() { if (m_MustResort) { base.Sort(m_Comparer); m_MustResort = false; } } public bool AllowEdit { get { return true; }} public bool AllowNew { get { return false; }} public bool AllowRemove { get { return true; }} private ListChangedEventHandler listChangedHandler; public event ListChangedEventHandler ListChanged { add { listChangedHandler += value; } remove { listChangedHandler -= value; } } internal void OnListChanged(ListChangedEventArgs args) { if (listChangedHandler != null) { listChangedHandler(this, args); } } protected virtual void OnRemoveComplete(int index, object value) { m_MustResort = true; OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index) ); } protected virtual void OnInsertComplete(int index, object value) { m_MustResort = true; OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index) ); } public object AddNew() { throw new NotSupportedException(); } public void AddIndex(PropertyDescriptor pd) { throw new NotSupportedException(); } public void ApplySort(PropertyDescriptor pd, ListSortDirection dir) { throw new NotSupportedException(); } public int Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); } public bool IsSorted { get { return false; }} public void RemoveIndex(PropertyDescriptor pd) { throw new NotSupportedException(); } public void RemoveSort() { throw new NotSupportedException(); } public ListSortDirection SortDirection { get { throw new NotSupportedException(); }} public PropertyDescriptor SortProperty { get { throw new NotSupportedException(); }} public bool SupportsChangeNotification {get { return true; }} public bool SupportsSearching { get { return false; }} public bool SupportsSorting { get { return false; }} } =================================== This list is hosted by DevelopMentorŪ http://www.develop.com Some .NET courses you may be interested in: NEW! Guerrilla ASP.NET, 26 Jan 2004, in Los Angeles http://www.develop.com/courses/gaspdotnetls View archives and manage your subscription(s) at http://discuss.develop.com