Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / General / December 2005

Tip: Looking for answers? Try searching our database.

Binding a Collection as a component

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Ruben - 26 Dec 2005 23:51 GMT
I have a collection (PersonCollection inherits collectionbase and implements
ITypedList it's a collection of Person objects) this collection also
implements the IComponent interface, so I can drag the collection from the
toolbar to the form editor. Now the problem is when I add a new property to
the Person class, wich type is another collection (it also inherits
collectionbase and implements ITypedList) when I try to bind the new
collection to a text box or select the datamember property of the grid, it
throws an error "The specified method is not compatible"

I tryed everything and couldn't solve it, please help me.
Bart Mermuys - 27 Dec 2005 23:14 GMT
Hi,

>I have a collection (PersonCollection inherits collectionbase and
>implements
[quoted text clipped - 8 lines]
>
> I tryed everything and couldn't solve it, please help me.

To get the properties of the items of a child-collection it will ask the
parent-collection for them using ITypedList.GetItemProperties, listAccessors
forms a path of properties to the child-collection.

And for some unknown reason IBindingList.AddNew must also be implemented, on
the other hand a custom collection without IBindingList isn't worth that
much.  So if you haven't already you should implement IBindingList.

At the end i posted an example, to get basic support for hierarchical custom
collections both at design and runtime.

You can also find an example here (the ITypedList isn't sufficiently
implemented for hierarchical custom collections):
http://msdn.microsoft.com/msdnmag/issues/05/08/CollectionsandDataBinding/default.aspx

If you tried any of the code and still have problems, then post the code for
your custom item and collection.

And if you are using NET2.0, then use BindingList<T>, this already implement
IBindingList and ITypedList is handled by putting a BindingSource between
the collection and control.

HTH,
Greetings

public class PersonCollection : CollectionBase, ITypedList, IComponent,
IBindingList
{
 #region Typed Methods
 public int Add(Person p )
 {
   return List.Add(p);
 }

 public int IndexOf(Person p )
 {
   return List.IndexOf(p);
 }

 public void Remove(Person p)
 {
   List.Remove(p);
 }

 public Person this[int i]
 {
   get { return (Person)List[i]; }
   set { List[i] = value; }
 }
 #endregion

 #region CollectionBase overrides & notification
 private void OnListChanged(ListChangedType t, int OldIndex, int NewIndex)
 {
   if ( ListChanged!=null )
     ListChanged(this, new ListChangedEventArgs(t, OldIndex, NewIndex));
 }

 protected override void OnSetComplete(int index, object oldValue, object
newValue)
 {
   OnListChanged(ListChangedType.ItemChanged, index, index);
 }

 protected override void OnInsertComplete(int index, object value)
 {
   OnListChanged(ListChangedType.ItemAdded, index, index);
 }

 protected override void OnClearComplete()
 {
   OnListChanged(ListChangedType.Reset, -1, -1);
 }

 protected override void OnRemoveComplete(int index, object value)
 {
   OnListChanged(ListChangedType.ItemDeleted, index, index);
 }
 #endregion

 #region ITypedList
 public PropertyDescriptorCollection GetItemProperties(
PropertyDescriptor[] listAccessors )
 {
   if ( listAccessors == null || listAccessors.Length == 0 )
   {
      PropertyDescriptorCollection pdc =
TypeDescriptor.GetProperties(typeof(Person));
      return pdc;
   }
   else
   {
     ITypedList childCol = null;
     if ( Count > 0 )
       childCol = (ITypedList)  listAccessors[0].GetValue( List[0] );
     else
       childCol = (ITypedList)
            Activator.CreateInstance(listAccessors[0].PropertyType);

     // strip one property
     PropertyDescriptor[] listAccessors_1 =
        new PropertyDescriptor[listAccessors.Length-1];

     Array.Copy( listAccessors, 1, listAccessors_1, 0,
listAccessors_1.Length);

     return childCol.GetItemProperties(listAccessors_1);
   }
 }

 public string GetListName( PropertyDescriptor[] listAccessors )
 {
   if ( listAccessors == null || listAccessors.Length ==0 )
     return GetType().Name;
   else
     return listAccessors[listAccessors.Length-1].PropertyType.Name;
 }
 #endregion

 #region IBindingList Members

 public event System.ComponentModel.ListChangedEventHandler ListChanged;

 public bool SupportsChangeNotification
 {
   get { return true; }
 }

 public bool AllowEdit
 {
   get { return true; }
 }

 public bool AllowNew
 {
   get { return true; }
 }

 public bool AllowRemove
 {
   get { return true; }
 }

 public object AddNew()
 {
   Person p = new Person("new");
   int idx = List.Add(p);
   // warning: if Person doesn't implement IEditableObject then you need to
   // fire itemadded twice, but its already fired once because of List.Add,
so
   // this is the second time, if they do implement IEditableObject  then
you need
   // to call this when IEditableObject.EndEdit is called on a new item.
   OnListChanged(ListChangedType.ItemAdded, idx, idx);
   return p;
 }

 public PropertyDescriptor SortProperty
 {
   get { return null; }
 }

 public int Find(PropertyDescriptor property, object key)
 {
   return 0;
 }

 public bool SupportsSorting
 {
   get { return false; }
 }

 public bool IsSorted
 {
   get { return false; }
 }

 public bool SupportsSearching
 {
   get { return false; }
 }

 public System.ComponentModel.ListSortDirection SortDirection
 {
   get { return new System.ComponentModel.ListSortDirection (); }
 }

 public void RemoveSort()  {  }
 public void AddIndex(PropertyDescriptor property)  {  }
 public void ApplySort(PropertyDescriptor property,
System.ComponentModel.ListSortDirection direction)  {  }
 public void RemoveIndex(PropertyDescriptor property)  {  }

 #endregion

 #region IComponent Members
 private ISite site;

 public event System.EventHandler Disposed;

 public ISite Site
 {
   get  {   return site;  }
   set  { site = value; }
 }

 #endregion

 #region IDisposable Members
 public void Dispose()
 {
   if (Disposed!=null) Disposed(this, EventArgs.Empty);
 }
 #endregion
}

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.