// Jackson Harper jackson@ximian.com
+using System.Data;
using System.Collections;
using System.Globalization;
using System.ComponentModel;
public class BindingContext : ICollection, IEnumerable {
private Hashtable managers;
+ private EventHandler onCollectionChangedHandler;
- private class DataSourceEntry {
+ private class HashKey {
+ public object source;
+ public string member;
- private object source;
- private Hashtable members;
- // private BindingManagerBase default_manager;
-
- public DataSourceEntry (object source)
+ public HashKey (object source, string member)
{
this.source = source;
- members = new Hashtable ();
- }
-
- public BindingManagerBase AddMember (string member)
- {
- BindingManagerBase res = members [member] as BindingManagerBase;
- if (res != null)
- return res;
- res = CreateBindingManager (source, member);
- members [member] = res;
- return res;
- }
-
- public void AddMember (string member, BindingManagerBase manager)
- {
- members [member] = manager;
- }
-
- public bool Contains (string member)
- {
- return members.Contains (member);
- }
- }
-
- private class ManagerEntry {
-
- private object source;
- private WeakReference member_ref;
-
- private int member_hash;
-
- public ManagerEntry (object source, string member)
- {
- this.source = source;
- if (member == null)
- member = String.Empty;
-
- member_hash = member.ToLower (CultureInfo.InvariantCulture).GetHashCode ();
- if (member_hash == 0)
- member_hash = 1;
- member_ref = new WeakReference (member, false);
- }
-
- public override bool Equals (object b)
- {
- ManagerEntry o = (ManagerEntry) b;
-
- return (o.source == source && o.member_ref.Target == member_ref.Target);
+ this.member = member;
}
public override int GetHashCode ()
{
- return member_hash * source.GetHashCode ();
+ return source.GetHashCode() ^ member.GetHashCode ();
}
- public override string ToString ()
+ public override bool Equals (object o)
{
- return source.ToString () + " + " + (member_ref.Target == null ? " -- null --" : member_ref.Target.ToString ());
+ HashKey hk = o as HashKey;
+ if (hk == null)
+ return false;
+ return hk.source == source && hk.member == member;
}
}
}
public bool IsReadOnly {
- get {
- return false;
- }
+ get { return false; }
}
public BindingManagerBase this [object dataSource] {
- get {
- return this [dataSource, String.Empty];
- }
+ get { return this [dataSource, String.Empty]; }
}
- public BindingManagerBase this [object data_source, string data_member] {
+ public BindingManagerBase this [object dataSource, string dataMember] {
get {
- DataSourceEntry ds = managers [data_source] as DataSourceEntry;
- if (ds == null) {
- ds = new DataSourceEntry (data_source);
- managers [data_source] = ds;
- }
- return ds.AddMember (data_member);
+ if (dataSource == null)
+ throw new ArgumentNullException ("dataSource");
+ if (dataMember == null)
+ dataMember = String.Empty;
+
+ HashKey key = new HashKey (dataSource, dataMember);
+ BindingManagerBase res = managers [key] as BindingManagerBase;
+
+ if (res != null)
+ return res;
+
+ res = CreateBindingManager (dataSource, dataMember);
+ if (res == null)
+ return null;
+ managers [key] = res;
+ return res;
}
}
- private static BindingManagerBase CreateBindingManager (object data_source,
- string data_member)
+ private BindingManagerBase CreateBindingManager (object data_source, string data_member)
{
- if (data_source is IList ||
- data_source is IListSource ||
- data_source is IBindingList) {
- CurrencyManager res = new CurrencyManager (data_source, data_member);
- return res;
+ if (data_member == "") {
+ if (IsListType (data_source.GetType ()))
+ return new CurrencyManager (data_source);
+ else
+ return new PropertyManager (data_source);
}
+ else {
+ BindingMemberInfo info = new BindingMemberInfo (data_member);
- return new PropertyManager (data_source, data_member);
+ BindingManagerBase parent_manager = this[data_source, info.BindingPath];
+
+ PropertyDescriptor pd = parent_manager == null ? null : parent_manager.GetItemProperties ().Find (info.BindingField, true);
+
+ if (pd == null)
+ throw new ArgumentException (String.Format ("Cannot create a child list for field {0}.", info.BindingField));
+
+ if (IsListType (pd.PropertyType))
+ return new RelatedCurrencyManager (parent_manager, pd);
+ else
+ return new RelatedPropertyManager (parent_manager, info.BindingField);
+ }
+ }
+
+ bool IsListType (Type t)
+ {
+ return (typeof (IList).IsAssignableFrom (t)
+ || typeof (IListSource).IsAssignableFrom (t));
}
#region Public Instance Methods
public bool Contains (object dataSource, string dataMember)
{
- DataSourceEntry ds = managers [dataSource] as DataSourceEntry;
- if (ds == null)
- return false;
- return ds.Contains (dataMember);
+ if (dataSource == null)
+ throw new ArgumentNullException ("dataSource");
+ if (dataMember == null)
+ dataMember = String.Empty;
+ HashKey key = new HashKey (dataSource, dataMember);
+ return managers [key] != null;
}
#endregion // Public Instance Methods
throw new ArgumentNullException ("dataSource");
if (listManager == null)
throw new ArgumentNullException ("listManager");
- DataSourceEntry ds = managers [dataSource] as DataSourceEntry;
- if (ds == null) {
- ds = new DataSourceEntry (dataSource);
- managers [dataSource] = ds;
- }
- ds.AddMember (String.Empty, listManager);
+
+ HashKey key = new HashKey (dataSource, String.Empty);
+ managers [key] = listManager;
}
protected internal void Clear ()
managers.Clear ();
}
- protected virtual void OnCollectionChanged(System.ComponentModel.CollectionChangeEventArgs ccevent)
+ protected virtual void OnCollectionChanged (CollectionChangeEventArgs ccevent)
{
- if (CollectionChanged != null) {
- CollectionChanged (this, ccevent);
+ if (onCollectionChangedHandler != null) {
+ onCollectionChangedHandler (this, ccevent);
}
}
protected internal void Remove (object dataSource)
{
+ if (dataSource == null)
+ throw new ArgumentNullException ("dataSource");
+
RemoveCore (dataSource);
OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, dataSource));
}
protected virtual void RemoveCore (object dataSource)
{
- managers.Remove (dataSource);
+ HashKey[] keys = new HashKey [managers.Keys.Count];
+ managers.Keys.CopyTo (keys, 0);
+
+ for (int i = 0; i < keys.Length; i ++) {
+ if (keys[i].source == dataSource)
+ managers.Remove (keys[i]);
+ }
}
#endregion // Protected Instance Methods
#region Events
- public event CollectionChangeEventHandler CollectionChanged;
+#if NET_2_0
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+#endif
+ public event CollectionChangeEventHandler CollectionChanged {
+ add { throw new NotImplementedException (); }
+ remove { /* nothing to do here.. */ }
+ }
#endregion // Events
#region ICollection Interfaces
}
int ICollection.Count {
- get {
- return managers.Count;
- }
+ get { return managers.Count; }
}
bool ICollection.IsSynchronized {
- get {
- return false;
- }
+ get { return false; }
}
object ICollection.SyncRoot {
- get {
- return null;
- }
+ get { return null; }
}
#endregion // ICollection Interfaces
#region IEnumerable Interfaces
- [MonoTODO]
+ [MonoTODO ("our enumerator is slightly different. in MS's implementation the Values are WeakReferences to the managers.")]
IEnumerator IEnumerable.GetEnumerator() {
- throw new NotImplementedException();
+ return managers.GetEnumerator ();
}
#endregion // IEnumerable Interfaces
-
- private ManagerEntry CreateEntry (object dataSource, string dataMember)
- {
- return new ManagerEntry (dataSource, dataMember);
- }
}
}