2006-12-26 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Binding.cs
index dfd5872ab3eabd8acbf7e5cfaaa62088c527d354..7fe7b29b1e89c9b9f6f71ebda8ceb1939cce8e15 100644 (file)
@@ -40,13 +40,9 @@ namespace System.Windows.Forms {
                private Control control;
 
                private BindingManagerBase manager;
-               private PropertyDescriptor prop_desc;
+               private PropertyDescriptor control_property;
                private PropertyDescriptor is_null_desc;
 
-               private EventDescriptor changed_event;
-               private EventHandler property_value_changed_handler;
-               private object event_current; // The manager.Current as far as the changed_event knows
-
                private object data;
                private Type data_type;
 
@@ -124,18 +120,17 @@ namespace System.Windows.Forms {
                        if (control == this.control)
                                return;
 
-                       prop_desc = TypeDescriptor.GetProperties (control).Find (property_name, true);                  
-                       
-                       if (prop_desc == null)
+                       control_property = TypeDescriptor.GetProperties (control).Find (property_name, true);                   
+
+                       if (control_property == null)
                                throw new ArgumentException (String.Concat ("Cannot bind to property '", property_name, "' on target control."));
-                       if (prop_desc.IsReadOnly)
+                       if (control_property.IsReadOnly)
                                throw new ArgumentException (String.Concat ("Cannot bind to property '", property_name, "' because it is read only."));
                                
-                       data_type = prop_desc.PropertyType; // Getting the PropertyType is kinda slow and it should never change, so it is cached
+                       data_type = control_property.PropertyType; // Getting the PropertyType is kinda slow and it should never change, so it is cached
                        control.Validating += new CancelEventHandler (ControlValidatingHandler);
 
                        this.control = control;
-                       control.DataBindings.Add (this);
                }
 
                internal void Check (BindingContext binding_context)
@@ -143,33 +138,29 @@ namespace System.Windows.Forms {
                        if (control == null || control.BindingContext == null)
                                return;
 
-                       Console.WriteLine ("data source  {0}   member name:  {1}",
-                                          data_source, data_member);
                        manager = control.BindingContext [data_source, data_member];
 
                        manager.AddBinding (this);
                        manager.PositionChanged += new EventHandler (PositionChangedHandler);
-
-                       WirePropertyValueChangedEvent ();
+                       manager.CurrentChanged += new EventHandler (CurrentChangedHandler);
 
                        is_null_desc = TypeDescriptor.GetProperties (manager.Current).Find (property_name + "IsNull", false);
 
-                       PullData ();
+                       PushData ();
                }
 
-               internal void PushData ()
+               internal void PullData ()
                {
-                       if (IsBinding == false)
+                       if (IsBinding == false || manager.Current == null)
                                return;
 
-                       data = prop_desc.GetValue (control);
-                       data = FormatData (data);
+                       data = control_property.GetValue (control);
                        SetPropertyValue (data);
                }
 
-               internal void PullData ()
+               internal void PushData ()
                {
-                       if (IsBinding == false || manager.Current == null)
+                       if (manager == null || manager.IsSuspended || manager.Current == null)
                                return;
 
                        if (is_null_desc != null) {
@@ -182,12 +173,9 @@ namespace System.Windows.Forms {
 
                        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 = ParseData (manager.Current, manager.Current.GetType ());
+                       } else {
+                               data = ParseData (pd.GetValue (manager.Current), pd.PropertyType);
                        }
 
                        data = FormatData (data);
@@ -196,12 +184,12 @@ namespace System.Windows.Forms {
 
                internal void UpdateIsBinding ()
                {
-                       PullData ();
+                       PushData ();
                }
 
                private void SetControlValue (object data)
                {
-                       prop_desc.SetValue (control, data);
+                       control_property.SetValue (control, data);
                }
 
                private void SetPropertyValue (object data)
@@ -209,43 +197,32 @@ namespace System.Windows.Forms {
                        PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (binding_member_info.BindingField, true);
                        if (pd.IsReadOnly)
                                return;
+                       data = ParseData (data, pd.PropertyType);
                        pd.SetValue (manager.Current, data);
                }
 
-               private void CurrentChangedHandler ()
+               private void CurrentChangedHandler (object sender, EventArgs e)
                {
-                       if (changed_event != null) {
-                               changed_event.RemoveEventHandler (event_current, property_value_changed_handler);
-                               WirePropertyValueChangedEvent ();
-                       }
-               }
-
-               private void WirePropertyValueChangedEvent ()
-               {
-                       if (manager.Current == null)
-                               return;
-                       EventDescriptor changed_event = TypeDescriptor.GetEvents (manager.Current).Find (property_name + "Changed", false);
-                       if (changed_event == null)
-                               return;
-                       property_value_changed_handler = new EventHandler (PropertyValueChanged);
-                       changed_event.AddEventHandler (manager.Current, property_value_changed_handler);
-
-                       event_current = manager.Current;
-               }
-
-               private void PropertyValueChanged (object sender, EventArgs e)
-               {
-                       PullData ();
+                       PushData ();
                }
 
                private void ControlValidatingHandler (object sender, CancelEventArgs e)
                {
-                       PullData ();
+                       object old_data = data;
+
+                       // If the data doesn't seem to be valid (it can't be converted,
+                       // is the wrong type, etc, we reset to the old data value.
+                       try {
+                               PullData ();
+                       } catch {
+                               data = old_data;
+                               SetControlValue (data);
+                       }
                }
 
                private void PositionChangedHandler (object sender, EventArgs e)
                {
-                       PullData ();
+                       PushData ();
                }
 
                private object ParseData (object data, Type data_type)