In .:
authorChris Toshok <toshok@novell.com>
Tue, 20 Jun 2006 16:01:14 +0000 (16:01 -0000)
committerChris Toshok <toshok@novell.com>
Tue, 20 Jun 2006 16:01:14 +0000 (16:01 -0000)
2006-06-20  Chris Toshok  <toshok@ximian.com>

* System.Windows.Forms.dll.sources: add RelatedPropertyManager.cs
and RelatedCurrencyManager.cs.

In System.Windows.Forms:
2006-06-20  Chris Toshok  <toshok@ximian.com>

* BindingContext.cs: rewrite the CreateBindingManager code to
handle navigation paths more or less properly.  This could
definitely stand some more work, in particular to push the
recursion up to the toplevel.  But that relies on fixes in other
places (System.Data comes to mind).

Also, move to a flat hashtable (and encode the twolevel nature of
the dictionary into the hash key).  This lets us implement the
IEnumerable.GetEnumerator method.

* RelatedCurrencyManager.cs: new class.  Update our view based on
our relation and our parent CurrencyManager's position.

* CurrencyManager.cs: split out some logic from the ctor into
SetView, so it can be called from the new RelatedCurrencyManager
subclass.

* RelatedPropertyManager.cs: new class.  Update our datasource
based on the position of our parent CurrencyManager.

* PropertyManager.cs: split out some logic from the ctor into
SetDataSource, so it can be called from the new RelatedDataSource
subclass.  Also, make the Current getter return the value
of the PropertyDescriptor, not the data_source.

* Binding.cs: no need to duplicate the string splitting code here.

svn path=/trunk/mcs/; revision=61878

mcs/class/Managed.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms.dll.sources
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Binding.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/BindingContext.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/PropertyManager.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedCurrencyManager.cs [new file with mode: 0644]
mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs [new file with mode: 0644]

index 674c101ef0d5ec94d25ec5f12004e0e15bd195e0..7006aed662dacb9b2fe54b157f2f1a6711a45962 100644 (file)
@@ -1,3 +1,8 @@
+2006-06-20  Chris Toshok  <toshok@ximian.com>
+
+       * System.Windows.Forms.dll.sources: add RelatedPropertyManager.cs
+       and RelatedCurrencyManager.cs.
+
 2006-06-12  Wade Berrier <wberrier@novell.com>
 
        * Makefile: Update for dialog-question3.png -> dialog-question.png rename
index 46ff38110a981071cc3a9672d39ded10fda3e844..49d4ea953a5f1bc4cf2c14519369e3841962fe9c 100644 (file)
@@ -413,6 +413,8 @@ System.Windows.Forms/QueryContinueDragEventHandler.cs
 System.Windows.Forms/QuestionEventArgs.cs
 System.Windows.Forms/QuestionEventHandler.cs
 System.Windows.Forms/RadioButton.cs
+System.Windows.Forms/RelatedCurrencyManager.cs
+System.Windows.Forms/RelatedPropertyManager.cs
 System.Windows.Forms/RichTextBox.cs
 System.Windows.Forms/RichTextBoxFinds.cs
 System.Windows.Forms/RichTextBoxScrollBars.cs
index 9bc9e54e23734bd566c619b7767318981ccd448e..dfd5872ab3eabd8acbf7e5cfaaa62088c527d354 100644 (file)
@@ -36,9 +36,6 @@ namespace System.Windows.Forms {
                private object data_source;
                private string data_member;
 
-               private string row_name;
-               private string col_name;
-
                private BindingMemberInfo binding_member_info;
                private Control control;
 
@@ -60,12 +57,6 @@ namespace System.Windows.Forms {
                        data_source = dataSource;
                        data_member = dataMember;
                        binding_member_info = new BindingMemberInfo (dataMember);
-
-                       int sp = data_member != null ? data_member.IndexOf ('.') : -1;
-                       if (sp != -1) {
-                               row_name = data_member.Substring (0, sp);
-                               col_name = data_member.Substring (sp + 1, data_member.Length - sp - 1);
-                       }
                }
                #endregion      // Public Constructors
 
@@ -152,13 +143,9 @@ namespace System.Windows.Forms {
                        if (control == null || control.BindingContext == null)
                                return;
 
-                       string member_name = data_member;
-                       if (row_name != null)
-                               member_name = row_name;
-
                        Console.WriteLine ("data source  {0}   member name:  {1}",
-                                       data_source, member_name);
-                       manager = control.BindingContext [data_source, member_name];
+                                          data_source, data_member);
+                       manager = control.BindingContext [data_source, data_member];
 
                        manager.AddBinding (this);
                        manager.PositionChanged += new EventHandler (PositionChangedHandler);
@@ -193,18 +180,15 @@ namespace System.Windows.Forms {
                                }
                        }
 
-                       if (row_name != null && col_name != null) {
-                               PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (col_name, true);
-                               object pulled = pd.GetValue (manager.Current);
-                               data = ParseData (pulled, pd.PropertyType);
-                       } else if (data_member != null) {
-                               PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (data_member, true);
-                               object pulled = pd.GetValue (manager.Current);
-                               data = ParseData (pulled, pd.PropertyType);
-                       } else {
+                       PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (binding_member_info.BindingField, true);
+                       if (pd == null) {
                                object pulled = manager.Current;
                                data = ParseData (pulled, pulled.GetType ());
                        }
+                       else {
+                               object pulled = pd.GetValue (manager.Current);
+                               data = ParseData (pulled, pd.PropertyType);
+                       }
 
                        data = FormatData (data);
                        SetControlValue (data);
@@ -222,10 +206,7 @@ namespace System.Windows.Forms {
 
                private void SetPropertyValue (object data)
                {
-                       string member_name = data_member;
-                       if (col_name != null)
-                               member_name = col_name;
-                       PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (member_name, true);
+                       PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (binding_member_info.BindingField, true);
                        if (pd.IsReadOnly)
                                return;
                        pd.SetValue (manager.Current, data);
index 5efff41575d0dedda0fe96d7ea3bdad3d9837c36..46ae969623a5944bbe49732172312b1a89222bb3 100644 (file)
@@ -36,43 +36,29 @@ namespace System.Windows.Forms {
        public class BindingContext : ICollection, IEnumerable {
 
                private Hashtable managers;
-               private object null_data_source = new object ();
+               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 ();
+                               this.member = member;
                        }
 
-                       public BindingManagerBase AddMember (string member)
+                       public override int GetHashCode ()
                        {
-                               if (member == null)
-                                       member = String.Empty;
-                               BindingManagerBase res = members [member] as BindingManagerBase;
-                               if (res != null)
-                                       return res;
-                               res = CreateBindingManager (source, member);
-                               Console.WriteLine ("CREATED BINDING MANAGER:   {0}", res);
-                               if (res == null)
-                                       return null;
-                               members [member] = res;
-                               return res;
+                               return source.GetHashCode() + member.GetHashCode ();
                        }
 
-                       public void AddMember (string member, BindingManagerBase manager)
+                       public override bool Equals (object o)
                        {
-                               members [member] = manager;
-                       }
-
-                       public bool Contains (string member)
-                       {
-                               return members.Contains (member);
+                               HashKey hk = o as HashKey;
+                               if (hk == null)
+                                       return false;
+                               return hk.source == source && hk.member == member;
                        }
                }
 
@@ -82,107 +68,172 @@ namespace System.Windows.Forms {
                }
 
                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] {
                        get {
-                               DataSourceEntry ds = GetEntry (data_source, data_member, true);
-                               return ds.AddMember (data_member);
-                       }
-               }
+                               if (data_source == null)
+                                       throw new ArgumentNullException ("data_source");
+                               if (data_member == null)
+                                       data_member = String.Empty;
 
-               private DataSourceEntry GetEntry (object data_source, string data_member, bool create)
-               {
-                       if (data_source == null)
-                               throw new ArgumentNullException ("data_source");
-                               
-                       DataSourceEntry ds = managers [data_source] as DataSourceEntry;
-                       if (ds == null && create) {
-                               ds = new DataSourceEntry (data_source);
-                               managers [data_source] = ds;
-                       }
+                               HashKey key = new HashKey (data_source, data_member);
+                               BindingManagerBase res = managers [key] as BindingManagerBase;
 
-                       return ds;
-               }
+                               if (res != null)
+                                       return res;
 
-               private static BindingManagerBase CreateBindingManager (object data_source, 
-                       string data_member)
-               {
-                       if (data_source is IList || 
-                               data_source is IListSource ||
-                               data_source is IBindingList) {
-                               return CreateCurrencyManager (data_source, data_member);
+                               res = CreateBindingManager (data_source, data_member);
+                               Console.WriteLine ("CREATED: {0}", res);
+                               if (res == null)
+                                       return null;
+                               managers [key] = res;
+                               return res;
                        }
-
-                       return new PropertyManager (data_source, data_member);
                }
 
-               private static CurrencyManager CreateCurrencyManager (object data_source, string data_member)
+               private BindingManagerBase CreateBindingManager (object data_source, string data_member)
                {
-                       IList list = null;
-
-                       if (data_source is IList) {
-                               list = (IList) data_source;
-                       } else if (data_source is IListSource) {
-                               list = ((IListSource) data_source).GetList ();
-                       } else {
-                               throw new Exception ("Attempted to create currency manager " +
-                                       "from invalid type: " + data_source.GetType ());
-                       }
+#if true
+                       /* the following is gross and special cased
+                          and needs to die.  a more proper
+                          implementation would be something like
+                          what's down below in the #else section,
+                          where the recursion over the nagivation
+                          path is at the toplevel.
+                       */
 
                        DataTable table = data_source as DataTable;
                        if (table == null && data_source is DataView)
                                table = ((DataView) data_source).Table;
 
                        DataSet dataset = data_source as DataSet;
-                       if (table == null && dataset != null) {
-                               string table_name = data_member;
-                               int sp = data_member != null ? data_member.IndexOf ('.') : -1;
-                               if (sp != -1) {
-                                       table_name = data_member.Substring (0, sp);
-                                       data_member = data_member.Substring (sp + 1);
-                               }
-                               if (dataset != null && table_name != String.Empty) {
-                                       Console.WriteLine ("TABLE NAME:  {0}   data member:   {1}", table_name, data_member);
-                                       table = dataset.Tables [table_name];
+                       if (table != null) {
+                               return new CurrencyManager (new DataView (table));
+                       }
+                       else if (data_member != "" && dataset != null) {
+                               BindingMemberInfo info = new BindingMemberInfo (data_member);
+
+                               if (info.BindingPath == "") {
+                                       table = dataset.Tables [info.BindingField];
                                        if (table == null)
-                                               throw new ArgumentException (String.Format ("Specified data member table {0} does not exist in the data source DataSet", data_member));
-                                       if (data_member != table_name) {
-                                               /*
-                                               Console.WriteLine ("CHECKING FOR COLUMN:   {0}", data_member);
-                                               DataColumn col = table.Columns [data_member];
-                                               DataRelation rel = (col == null ? dataset.Relations [data_member] : null);
-                                               Console.WriteLine ("COLUMN:   {0}    RELATION:  {1}", col, rel);
-                                               if (rel == null && col == null)
-                                                       throw new ArgumentException (String.Format ("Specified data member {0} does not exist in the data table {1}", data_member, table_name));
-
-                                               // FIXME: hmm, in such case what should we do?
-                                               */
-                                               table = null;
-                                               list = null;
+                                               throw new ArgumentException (String.Format ("Specified data member table `{0}' does not exist in the data source DataSet", info.BindingField));
+
+                                       return new CurrencyManager (new DataView (table));
+                               }
+                               else {
+                                       Console.WriteLine ("Getting parent_manager for {0}", info.BindingPath);
+                                       CurrencyManager parent_manager = (CurrencyManager) this[data_source, info.BindingPath];
+
+                                       table = ((DataView)parent_manager.data_source).Table;
+
+                                       DataColumn col = table.Columns [info.BindingField];
+                                       DataRelation rel = dataset.Relations [info.BindingField];
+
+                                       if (col != null) {
+                                               Console.WriteLine ("+ creating related property manager for column {0}", info.BindingField);
+                                               return new RelatedPropertyManager (parent_manager, info.BindingField);
+                                       }
+                                       else if (rel != null) {
+                                               Console.WriteLine ("+ creating related currency manager for relation {0}", info.BindingField);
+                                               return new RelatedCurrencyManager (parent_manager, rel);
                                        }
+                                       else 
+                                               throw new ArgumentException (String.Format ("Specified data member {0} does not exist in the data table {1}",
+                                                                                           info.BindingField, table.TableName));
+
                                }
                        }
+                       else if (data_source is IList) {
+                               IList list = (IList)data_source;
 
-                       Console.WriteLine ("DATA TABLE:   {0}", table);
-                       
-                       if (table != null) {
-                               Console.WriteLine ("CREATING VIEW ON:  {0}", table.TableName);
-                               list = new DataView (table);
+                               if (data_member == "") {
+                                       return new CurrencyManager (list);
+                               }
+                               else {
+                                       CurrencyManager parent_manager = (CurrencyManager) this[data_source, ""];
+
+                                       if (parent_manager.Count == 0 ||
+                                           TypeDescriptor.GetProperties (parent_manager.GetItem (0)).Find (data_member, true) == null) {
+                                               throw new ArgumentException ("Cannot create a child list for field {0}", data_member);
+                                       }
+                                               
+
+                                       Console.WriteLine ("creating related property manager for column {0} on an IList source", data_member);
+                                       return new RelatedPropertyManager (parent_manager, data_member);
+                               }
+                       } else if (data_source is IListSource) {
+                               return new CurrencyManager (((IListSource) data_source).GetList ());
+                       }
+                       else {
+                               /* must be a property */
+                               Console.WriteLine ("creating PropertyManager");
+                               return new PropertyManager (data_source, data_member);
                        }
+#else
+                       if (data_member == "") {
+                               if (data_source is DataSet) {
+                                       return new CurrencyManager (new DataViewManager ((DataSet)data_source));
+                               }
+                               else if (data_source is DataTable) {
+                                       return new CurrencyManager (new DataView ((DataTable)data_source));
+                               }
+                               else if (data_source is DataView) {
+                                       return new CurrencyManager ((DataView)data_source);
+                               }
+                               else if (data_source is IListSource) {
+                                       return new CurrencyManager (((IListSource) data_source).GetList ());
+                               }
+                               else if (data_source is IList) {
+                                       return new CurrencyManager ((IList) data_source);
+                               }
+                               else {
+                                       return new PropertyManager (data_source, data_member);
+                               }
+                       }
+                       else {
+                               int dot = data_member.LastIndexOf ('.');
+                               string current_field = dot == -1 ? data_member : data_member.Substring (dot + 1);
+                               string parent_path = dot == -1 ? "" : data_member.Substring (0, dot);
+
+                               Console.WriteLine ("Getting parent_manager for {0}", parent_path);
+                               BindingManagerBase parent_manager = this[data_source, parent_path];
+                               CurrencyManager cm = parent_manager as CurrencyManager;
+
+                               PropertyDescriptor pd = parent_manager == null ? null : parent_manager.GetItemProperties ().Find (current_field, true);
+
+                               if (pd != null) {
+                                       Console.WriteLine ("parent_manager.GetItemProperties returned property descriptor for {0}", pd.Name);
+                                       if (cm != null) {
+                                               if (cm.data_source is DataViewManager)
+                                                       return new RelatedCurrencyManager (cm, );
+                                               else
+                                                       return new RelatedPropertyManager (cm, current_field);
+                                       }
+                               }
+                               else {
+                                       /* null property.  extra checks here, for e.g. DataRelations */
+                                       if (cm != null) {
+                                               if (cm.data_source is DataViewManager) {
+                                                       DataSet ds = ((DataViewManager)cm.data_source).DataSet;
+                                                       DataRelation rel = ds.Relations [current_field];
+
+                                                       if (rel != null) {
+                                                               Console.WriteLine ("+ creating related currency manager for relation {0}", current_field);
+                                                               return new RelatedCurrencyManager (cm, rel);
+                                                       }
+                                               }
+                                       }
+                               }
 
-                       if (list == null)
-                               return null;
-                       return new CurrencyManager (list);
+                               throw new ArgumentException (String.Format ("Cannot create a child list for field {0}", current_field));
+                       }
+#endif
                }
 
                #region Public Instance Methods
@@ -193,11 +244,13 @@ namespace System.Windows.Forms {
 
                public bool Contains (object dataSource, string dataMember)
                {
-                       DataSourceEntry ds = GetEntry (dataSource, dataMember, false);
-                       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
 
@@ -215,8 +268,9 @@ namespace System.Windows.Forms {
                                throw new ArgumentNullException ("dataSource");
                        if (listManager == null)
                                throw new ArgumentNullException ("listManager");
-                       DataSourceEntry ds = GetEntry (dataSource, String.Empty, true);
-                       ds.AddMember (String.Empty, listManager);
+
+                       HashKey key = new HashKey (dataSource, String.Empty);
+                       managers [key] = listManager;
                }
 
                protected internal void Clear ()
@@ -230,27 +284,39 @@ namespace System.Windows.Forms {
                        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;
+               public event CollectionChangeEventHandler CollectionChanged {
+                       add { throw new NotImplementedException (); }
+                       remove { /* nothing to do here.. */ }
+               }
                #endregion      // Events
 
                #region ICollection Interfaces
@@ -280,9 +346,9 @@ namespace System.Windows.Forms {
                #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
        }
index 909f59e439b9d55f0aa6f71212e5dc571d06c0f7..be2ed4a71afa5f2aa8ca721bb2763123e77481d5 100644 (file)
@@ -1,3 +1,32 @@
+2006-06-20  Chris Toshok  <toshok@ximian.com>
+
+       * BindingContext.cs: rewrite the CreateBindingManager code to
+       handle navigation paths more or less properly.  This could
+       definitely stand some more work, in particular to push the
+       recursion up to the toplevel.  But that relies on fixes in other
+       places (System.Data comes to mind).
+
+       Also, move to a flat hashtable (and encode the twolevel nature of
+       the dictionary into the hash key).  This lets us implement the
+       IEnumerable.GetEnumerator method.
+
+       * RelatedCurrencyManager.cs: new class.  Update our view based on
+       our relation and our parent CurrencyManager's position.
+
+       * CurrencyManager.cs: split out some logic from the ctor into
+       SetView, so it can be called from the new RelatedCurrencyManager
+       subclass.
+
+       * RelatedPropertyManager.cs: new class.  Update our datasource
+       based on the position of our parent CurrencyManager.
+
+       * PropertyManager.cs: split out some logic from the ctor into
+       SetDataSource, so it can be called from the new RelatedDataSource
+       subclass.  Also, make the Current getter return the value
+       of the PropertyDescriptor, not the data_source.
+
+       * Binding.cs: no need to duplicate the string splitting code here.
+
 2006-06-19  Peter Dennis Bartok  <pbartok@novell.com> 
 
        * Control.cs:
index ea27ef69a07f765319db0a7d95d25ab440e4971a..d8a7c99983802b1d3dbcac3465d81248c8207575 100644 (file)
@@ -40,9 +40,18 @@ namespace System.Windows.Forms {
 
                internal PropertyManager (object data_source, string property_name)
                {
-                       this.data_source = data_source;
                        this.property_name = property_name;
 
+                       SetDataSource (data_source);
+               }
+
+               internal void SetDataSource (object new_data_source)
+               {
+                       if (prop_desc != null)
+                               prop_desc.RemoveValueChanged (data_source, new EventHandler (PropertyChangedHandler));
+
+                       data_source = new_data_source;
+
                        prop_desc = TypeDescriptor.GetProperties (data_source).Find (property_name, true);
 
                        if (prop_desc == null)
@@ -52,7 +61,7 @@ namespace System.Windows.Forms {
                }
 
                public override object Current {
-                       get { return data_source; }
+                       get { return prop_desc == null ? null : prop_desc.GetValue (data_source); }
                }
 
                public override int Position {
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedCurrencyManager.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedCurrencyManager.cs
new file mode 100644 (file)
index 0000000..c228fa7
--- /dev/null
@@ -0,0 +1,54 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2006 Novell, Inc.
+//
+// Authors:
+//     Chris Toshok (toshok@ximian.com)
+//
+
+using System;
+using System.Data;
+using System.Reflection;
+using System.Collections;
+using System.ComponentModel;
+
+namespace System.Windows.Forms {
+       [DefaultMember("Item")]
+       internal class RelatedCurrencyManager : CurrencyManager {
+
+               CurrencyManager parent;
+               DataRelation rel;
+
+               public RelatedCurrencyManager (CurrencyManager parent, DataRelation rel)
+                       : base (((DataView)parent.data_source)[parent.Position].CreateChildView (rel))
+               {
+                       this.parent = parent;
+                       this.rel = rel;
+
+                       parent.PositionChanged += new EventHandler (parent_PositionChanged);
+               }
+
+               private void parent_PositionChanged (object sender, EventArgs args)
+               {
+                       SetDataSource (((DataView)parent.data_source)[parent.Position].CreateChildView (rel));
+               }
+       }
+}
+
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs
new file mode 100644 (file)
index 0000000..ff0f586
--- /dev/null
@@ -0,0 +1,49 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (c) 2006 Novell, Inc.
+//
+// Authors:
+//     Chris Toshok    <toshok@ximian.com>
+
+using System;
+using System.Collections;
+using System.ComponentModel;
+
+namespace System.Windows.Forms {
+
+       internal class RelatedPropertyManager : PropertyManager {
+
+               CurrencyManager parent;
+
+               public RelatedPropertyManager (CurrencyManager parent, string property_name)
+                       : base (parent.GetItem (parent.Position), property_name)
+               {
+                       this.parent = parent;
+                       parent.PositionChanged += new EventHandler (parent_PositionChanged);
+               }
+
+               void parent_PositionChanged (object sender, EventArgs args)
+               {
+                       SetDataSource (parent.GetItem (parent.Position));
+                       OnCurrentChanged (EventArgs.Empty);
+               }
+       }
+}
+