From e28362e46d38ca2a579ab9748cffbefd28b7dad4 Mon Sep 17 00:00:00 2001 From: Chris Toshok Date: Fri, 27 Apr 2007 19:38:33 +0000 Subject: [PATCH] 2007-04-27 Chris Toshok * BindingManagerBase.cs: fill in CurrentItemChanged (and have an internal handler that can be invoked from our subclasses.) Also, add a comment to PushData about how we need to fix it. * CurrencyManager.cs: tons of changes here. trying to get things matching the behavior of .net wrt event orders (ItemChanged, CurrentChanged, PositionChanged.) I've implemented a private .net symbol (ChangeRecordState) that appears in stack traces because it's actually easier to do this than to effective inline all its various behaviors at every call site. * RelatedPropertyManager.cs: guard against an exception here by not using parent.Current if the position is set to -1 (if the parent datasource is cleared, for instance). * Binding.cs: don't parse data in PushData (this might be wrong, but it jives with MS's behavior.) Also, don't call PushData when we get a CurrentChanged event. svn path=/trunk/mcs/; revision=76401 --- .../System.Windows.Forms/Binding.cs | 10 +- .../System.Windows.Forms/BindingManagerBase.cs | 14 ++- .../System.Windows.Forms/ChangeLog | 21 ++++ .../System.Windows.Forms/CurrencyManager.cs | 126 +++++++++++++++++---- .../System.Windows.Forms/RelatedPropertyManager.cs | 8 +- 5 files changed, 145 insertions(+), 34 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Binding.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Binding.cs index 7fe7b29b1e8..22a17feb533 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Binding.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Binding.cs @@ -142,7 +142,6 @@ namespace System.Windows.Forms { manager.AddBinding (this); manager.PositionChanged += new EventHandler (PositionChangedHandler); - manager.CurrentChanged += new EventHandler (CurrentChangedHandler); is_null_desc = TypeDescriptor.GetProperties (manager.Current).Find (property_name + "IsNull", false); @@ -173,9 +172,9 @@ namespace System.Windows.Forms { PropertyDescriptor pd = TypeDescriptor.GetProperties (manager.Current).Find (binding_member_info.BindingField, true); if (pd == null) { - data = ParseData (manager.Current, manager.Current.GetType ()); + data = manager.Current; } else { - data = ParseData (pd.GetValue (manager.Current), pd.PropertyType); + data = pd.GetValue (manager.Current); } data = FormatData (data); @@ -201,11 +200,6 @@ namespace System.Windows.Forms { pd.SetValue (manager.Current, data); } - private void CurrentChangedHandler (object sender, EventArgs e) - { - PushData (); - } - private void ControlValidatingHandler (object sender, CancelEventArgs e) { object old_data = data; diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/BindingManagerBase.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/BindingManagerBase.cs index 851c182e926..309139e11c6 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/BindingManagerBase.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/BindingManagerBase.cs @@ -44,6 +44,9 @@ namespace System.Windows.Forms { #region Protected Instance Fields protected EventHandler onCurrentChangedHandler; protected EventHandler onPositionChangedHandler; +#if NET_2_0 + internal EventHandler onCurrentItemChangedHandler; +#endif #endregion // Protected Instance Fields #region Public Instance Properties @@ -130,6 +133,11 @@ namespace System.Windows.Forms { if (pulling_data) return; + // XXX + // this is wrong, since UpdateIsBinding ends up emitting ItemChanged, which causes PushData to be called, which + // gets us infinite recursion. for now, comment out the call to PushData in CurrencyManager.OnItemChanged to, but + // this really needs fixing here. + UpdateIsBinding (); foreach (Binding binding in Bindings) binding.PushData (); @@ -174,8 +182,12 @@ namespace System.Windows.Forms { } #if NET_2_0 + public event EventHandler CurrentItemChanged { + add { onCurrentItemChangedHandler += value; } + remove { onCurrentItemChangedHandler -= value; } + } + public event BindingCompleteEventHandler BindingComplete; - public event EventHandler CurrentItemChanged; public event BindingManagerDataErrorEventHandler DataError; #endif #endregion // Events diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog index 5c6877eea27..1896a5ec0e3 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog @@ -1,3 +1,24 @@ +2007-04-27 Chris Toshok + + * BindingManagerBase.cs: fill in CurrentItemChanged (and have an + internal handler that can be invoked from our subclasses.) Also, + add a comment to PushData about how we need to fix it. + + * CurrencyManager.cs: tons of changes here. trying to get things + matching the behavior of .net wrt event orders (ItemChanged, + CurrentChanged, PositionChanged.) I've implemented a private .net + symbol (ChangeRecordState) that appears in stack traces because + it's actually easier to do this than to effective inline all its + various behaviors at every call site. + + * RelatedPropertyManager.cs: guard against an exception here by + not using parent.Current if the position is set to -1 (if the + parent datasource is cleared, for instance). + + * Binding.cs: don't parse data in PushData (this might be wrong, + but it jives with MS's behavior.) Also, don't call PushData when + we get a CurrentChanged event. + 2007-04-27 Andreia Gaita * WebBrowser.cs, diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/CurrencyManager.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/CurrencyManager.cs index 3ad73d54e7a..cc013632116 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/CurrencyManager.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/CurrencyManager.cs @@ -57,8 +57,11 @@ namespace System.Windows.Forms { public override object Current { get { - if (listposition == -1 || listposition >= list.Count) + if (listposition == -1 || listposition >= list.Count) { + Console.WriteLine ("throwing exception from here"); + Console.WriteLine (Environment.StackTrace); throw new IndexOutOfRangeException ("list position"); + } return list [listposition]; } } @@ -175,17 +178,14 @@ namespace System.Windows.Forms { public override void AddNew () { - if (list as IBindingList == null) - throw new NotSupportedException (); + IBindingList ibl = list as IBindingList; - (list as IBindingList).AddNew (); - - EndCurrentEdit (); + if (ibl == null) + throw new NotSupportedException (); - listposition = list.Count - 1; + ibl.AddNew (); - OnCurrentChanged (EventArgs.Empty); - OnPositionChanged (EventArgs.Empty); + ChangeRecordState (list.Count - 1, true, true, true, true); } @@ -245,16 +245,25 @@ namespace System.Windows.Forms { protected internal override void OnCurrentChanged (EventArgs e) { - BeginEdit (); - if (onCurrentChangedHandler != null) { onCurrentChangedHandler (this, e); } + +#if NET_2_0 + // don't call OnCurrentItemChanged here, as it can be overridden + if (onCurrentItemChangedHandler != null) { + onCurrentItemChangedHandler (this, e); + } +#endif + } #if NET_2_0 protected override void OnCurrentItemChanged (EventArgs e) { + if (onCurrentItemChangedHandler != null) { + onCurrentItemChangedHandler (this, e); + } } #endif @@ -262,6 +271,12 @@ namespace System.Windows.Forms { { if (ItemChanged != null) ItemChanged (this, e); + +#if fales + // XXX see the commend in BindingManagerbase.PushData + if (listposition != -1) + PushData (); +#endif } protected virtual void OnPositionChanged (EventArgs e) @@ -293,14 +308,38 @@ namespace System.Windows.Forms { foreach (Binding binding in Bindings) binding.UpdateIsBinding (); + ChangeRecordState (listposition, false, false, true, false); + OnItemChanged (new ItemChangedEventArgs (-1)); } + private void ChangeRecordState (int newPosition, + bool validating, + bool endCurrentEdit, + bool firePositionChanged, + bool pullData) + { + if (endCurrentEdit) + EndCurrentEdit (); + + int old_index = listposition; + + listposition = newPosition; + + if (listposition >= list.Count) + listposition = list.Count - 1; + + if (listposition != -1) + OnCurrentChanged (EventArgs.Empty); + + if (firePositionChanged) + OnPositionChanged (EventArgs.Empty); + } + private void UpdateItem () { // Probably should be validating or something here if (listposition != -1) { - EndCurrentEdit (); } else if (list.Count > 0) { @@ -336,34 +375,73 @@ namespace System.Windows.Forms { { switch (e.ListChangedType) { case ListChangedType.PropertyDescriptorAdded: + OnMetaDataChanged (EventArgs.Empty); +#if ONLY_1_1 + // um... + OnMetaDataChanged (EventArgs.Empty); +#endif + break; case ListChangedType.PropertyDescriptorDeleted: case ListChangedType.PropertyDescriptorChanged: OnMetaDataChanged (EventArgs.Empty); break; case ListChangedType.ItemDeleted: - if (listposition == e.NewIndex) { - listposition = e.NewIndex - 1; - OnCurrentChanged (EventArgs.Empty); + if (list.Count == 0) { + /* the last row was deleted */ + listposition = -1; + UpdateIsBinding (); + +#if NET_2_0 OnPositionChanged (EventArgs.Empty); + OnCurrentChanged (EventArgs.Empty); +#endif + } + else if (e.NewIndex <= listposition) { + /* the deleted row was either the current one, or one earlier in the list. + Update the index and emit PositionChanged, CurrentChanged, and ItemChanged. */ + ChangeRecordState (e.NewIndex, + false, false, e.NewIndex != listposition, false); + } + else { + /* the deleted row was after the current one, so we don't + need to update bound controls for Position/Current changed */ } - + OnItemChanged (new ItemChangedEventArgs (-1)); break; case ListChangedType.ItemAdded: - if (listposition == -1) { - /* do we need this logic up above in ItemDeleted as well? */ - listposition = e.NewIndex == 0 ? 0 : e.NewIndex - 1; - OnPositionChanged (EventArgs.Empty); - OnCurrentChanged (EventArgs.Empty); + if (list.Count == 1) { + /* it's the first one we've added */ + ChangeRecordState (e.NewIndex, + false, false, true, false); - UpdateIsBinding (); + OnItemChanged (new ItemChangedEventArgs (-1)); + } + else { +#if NET_2_0 + if (e.NewIndex <= listposition) { + ChangeRecordState (listposition, + false, false, false, false); + OnItemChanged (new ItemChangedEventArgs (-1)); + OnPositionChanged (EventArgs.Empty); + } + else { + OnItemChanged (new ItemChangedEventArgs (-1)); + } +#else + OnItemChanged (new ItemChangedEventArgs (-1)); +#endif } - OnItemChanged (new ItemChangedEventArgs (-1)); break; case ListChangedType.ItemChanged: - if (editing) + if (editing) { +#if NET_2_0 + if (e.NewIndex == listposition) + OnCurrentItemChanged (EventArgs.Empty); +#endif OnItemChanged (new ItemChangedEventArgs (e.NewIndex)); + } break; default: PushData (); diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs index c67610ec196..23f694951a2 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RelatedPropertyManager.cs @@ -44,7 +44,13 @@ namespace System.Windows.Forms { void parent_PositionChanged (object sender, EventArgs args) { - SetDataSource (parent.Current); + if (parent.Position == -1) { + SetDataSource (null); + } + else { + SetDataSource (parent.Current); + } + OnCurrentChanged (EventArgs.Empty); } } -- 2.11.4.GIT