diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingGroup.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingGroup.cs index 0cef67b8e2c..8712c9a327d 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingGroup.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/BindingGroup.cs @@ -382,9 +382,18 @@ public void CancelEdit() } // update targets - for (int i=_bindingExpressions.Count - 1; i>=0; --i) + for (int i=_bindingExpressions.Count-1; i>=0; --i) { - _bindingExpressions[i].UpdateTarget(); + // a re-entrant callout can shrink the collection - see + // https://github.com/dotnet/wpf/issues/1690 + if (i >= _bindingExpressions.Count) + continue; + + BindingExpressionBase bindingExpression = _bindingExpressions[i]; + if (bindingExpression.BindingGroup != this) + continue; + + bindingExpression.UpdateTarget(); } // also update dependent targets. These are one-way bindings that @@ -1133,7 +1142,16 @@ private bool ObtainConvertedProposedValues() bool result = true; for (int i=_bindingExpressions.Count-1; i>=0; --i) { - result = _bindingExpressions[i].ObtainConvertedProposedValue(this) && result; + // a re-entrant callout can shrink the collection - see + // https://github.com/dotnet/wpf/issues/1690 + if (i >= _bindingExpressions.Count) + continue; + + BindingExpressionBase bindingExpression = _bindingExpressions[i]; + if (bindingExpression.BindingGroup != this) + continue; + + result = bindingExpression.ObtainConvertedProposedValue(this) && result; } return result; @@ -1146,7 +1164,16 @@ private bool UpdateValues() for (int i=_bindingExpressions.Count-1; i>=0; --i) { - result = _bindingExpressions[i].UpdateSource(this) && result; + // a re-entrant callout can shrink the collection - see + // https://github.com/dotnet/wpf/issues/1690 + if (i >= _bindingExpressions.Count) + continue; + + BindingExpressionBase bindingExpression = _bindingExpressions[i]; + if (bindingExpression.BindingGroup != this) + continue; + + result = bindingExpression.UpdateSource(this) && result; } if (_proposedValueBindingExpressions != null) @@ -1174,10 +1201,17 @@ private bool CheckValidationRules() // check rules attached to the bindings for (int i=_bindingExpressions.Count-1; i>=0; --i) { - if (!_bindingExpressions[i].CheckValidationRules(this, _validationStep)) - { + // a re-entrant callout can shrink the collection - see + // https://github.com/dotnet/wpf/issues/1690 + if (i >= _bindingExpressions.Count) + continue; + + BindingExpressionBase bindingExpression = _bindingExpressions[i]; + if (bindingExpression.BindingGroup != this) + continue; + + if (!bindingExpression.CheckValidationRules(this, _validationStep)) result = false; - } } // include the bindings for proposed values, for the last two steps