From: <mcu...@us...> - 2014-11-21 16:29:24
|
Revision: 1550 http://sourceforge.net/p/orm/code/1550 Author: mcurland Date: 2014-11-21 16:29:21 +0000 (Fri, 21 Nov 2014) Log Message: ----------- Bug fixes: * Dragging fact types shapes from the model browser with attached role names and constraint shapes was creating multiple instances of each shape. This was a bad side effect of changes introduced and [1508] and [1527]. The MultiShapeUtility.ForceMultipleShapes directive is now removed and replaced with MultiShapeUtility.AllowMultipleShapes between creation and fixup of a new child shape resulting from an object browser drag operation. * Added modality checks to the intersection of simple mandatory and single column subset constraints. There was no handling for this. This was a targeted fix and does not fix mandatory modality issues with other set comparison constraints. * Don't serialized references to roles in the orm:PlayedRoles element if those roles are defined in an alternate partition. Continuation of work on [1519]. Modified Paths: -------------- trunk/ORMModel/Framework/FrameworkServices.cs trunk/ORMModel/ObjectModel/Constraint.cs trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.cs trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.xml trunk/ORMModel/ShapeModel/ORMDiagram.cs trunk/ORMModel/Shell/ORMDocView.cs Modified: trunk/ORMModel/Framework/FrameworkServices.cs =================================================================== --- trunk/ORMModel/Framework/FrameworkServices.cs 2014-08-07 06:25:14 UTC (rev 1549) +++ trunk/ORMModel/Framework/FrameworkServices.cs 2014-11-21 16:29:21 UTC (rev 1550) @@ -380,9 +380,9 @@ #endregion // AutomatedElementFilterService class #region ICreateSignalTransactionItems /// <summary> - /// Some model changes are used solely trigger other behavior within + /// Some model changes are used solely to trigger other behavior within /// a transaction. However, the system does not distinguish between - /// these changes an normal changes. If a signal occurs without a normal + /// these changes and normal changes. If a signal occurs without a normal /// change, then a transaction may appear to be meaningful to the user /// by displaying in the undo/redo stack even when no significant changes /// have occurred. A domain model class can implement this interface to @@ -400,7 +400,7 @@ /// </summary> /// <returns>Enumeration of domain property id/callback function pairs. /// If a callback function is not provided, then all changes of this - /// type can be ignored. Otherwise, the return true from the registered + /// type can be ignored. Otherwise, return true from the registered /// predicate to support a change.</returns> IEnumerable<KeyValuePair<Guid, Predicate<ElementPropertyChangedEventArgs>>> GetSignalPropertyChanges(); } Modified: trunk/ORMModel/ObjectModel/Constraint.cs =================================================================== --- trunk/ORMModel/ObjectModel/Constraint.cs 2014-08-07 06:25:14 UTC (rev 1549) +++ trunk/ORMModel/ObjectModel/Constraint.cs 2014-11-21 16:29:21 UTC (rev 1550) @@ -1459,6 +1459,8 @@ { return; } + IHasAlternateOwner toAlternateOwner; + object constraintOwner = (null == (toAlternateOwner = setConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner; int validationCount = validations.Count; ConstraintModality modality = setConstraint.Modality; for (int iValidation = 0; iValidation < validationCount; ++iValidation) @@ -1493,7 +1495,8 @@ IConstraint eligibleConstraint = eligibleSequence.Constraint; if (eligibleConstraint.ConstraintStorageStyle == ConstraintStorageStyle.SetConstraint && (modalityChange || validationInfo.TestModality(eligibleConstraint.Modality, modality)) && - Array.IndexOf<ConstraintType>(validationInfo.ConstraintTypesInPotentialConflict, constraintType) != -1) + Array.IndexOf<ConstraintType>(validationInfo.ConstraintTypesInPotentialConflict, constraintType) != -1 && + constraintOwner == ((null == (toAlternateOwner = eligibleConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner)) { // The delayed validation mechanism automatically takes care of any duplicate requests FrameworkDomainModel.DelayValidateElement(eligibleSequence, DelayValidateSetConstraintSubsetPattern); @@ -1504,6 +1507,36 @@ } break; default: + if (modalityChange) + { + // must also be validated. + IList<Role> roles = setConstraint.RoleCollection; + int roleCount = roles.Count; + for (int i = 0; i < roleCount; ++i) + { + Role selectedRole = roles[i]; + LinkedElementCollection<ConstraintRoleSequence> sequences = selectedRole.ConstraintRoleSequenceCollection; + int sequenceCount = sequences.Count; + for (int j = 0; j < sequenceCount; ++j) + { + ConstraintRoleSequence eligibleSequence = sequences[j]; + IConstraint eligibleConstraint; + if (eligibleSequence != setConstraint && + -1 != Array.IndexOf<ConstraintType>(validationInfo.ConstraintTypesInPotentialConflict, (eligibleConstraint = eligibleSequence.Constraint).ConstraintType)) + { + if (validationInfo.DomainRoleToError.HasValue) { + DelayValidateConstraintPatternError(setConstraint); + } + if (validationInfo.IntersectingDomainRoleToError.HasValue && + constraintOwner == ((null == (toAlternateOwner = eligibleConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner)) + { + DelayValidateConstraintPatternError(eligibleConstraint); + } + } + + } + } + } // Isn't a SetConstraint, move on break; } @@ -1563,7 +1596,7 @@ { IConstraint intersectingConstraint = intersectingSequence.Constraint; if (validationInfo.TestModality(modality, intersectingConstraint.Modality) && - (validationInfo.ConstraintTypesInPotentialConflict as IList<ConstraintType>).Contains(intersectingConstraint.ConstraintType)) + -1 != Array.IndexOf(validationInfo.ConstraintTypesInPotentialConflict, intersectingConstraint.ConstraintType)) { SetConstraint intersectingSetConstraint = (SetConstraint)intersectingSequence; LinkedElementCollection<Role> intersectingRoles = intersectingSetConstraint.RoleCollection; @@ -4715,7 +4748,7 @@ if (intersectingConstraint != setComparisonConstraint && constraintOwner == ((null == (toAlternateOwner = intersectingConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner) && validationInfo.TestModality(currentModality, intersectingConstraint.Modality) && - (validationInfo.ConstraintTypesInPotentialConflict as IList<ConstraintType>).Contains(intersectingConstraint.ConstraintType)) + -1 != Array.IndexOf<ConstraintType>(validationInfo.ConstraintTypesInPotentialConflict, intersectingConstraint.ConstraintType)) { if (constraintsToCheck == null) { @@ -4936,6 +4969,8 @@ object constraintOwner = (null == (toAlternateOwner = setComparisonConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner; int validationCount = validations.Count; ConstraintModality constraintModality = setComparisonConstraint.Modality; + LinkedElementCollection<SetComparisonConstraintRoleSequence> comparisonConstraintSequences = null; + int comparisonConstraintSequencesCount = 0; for (int iValidation = 0; iValidation < validationCount; ++iValidation) { IntersectingConstraintValidation validationInfo = validations[iValidation]; @@ -4962,8 +4997,11 @@ } break; case IntersectingConstraintPattern.SetComparisonConstraintSuperset: - LinkedElementCollection<SetComparisonConstraintRoleSequence> comparisonConstraintSequences = setComparisonConstraint.RoleSequenceCollection; - int comparisonConstraintSequencesCount = comparisonConstraintSequences.Count; + if (comparisonConstraintSequences == null) + { + comparisonConstraintSequences = setComparisonConstraint.RoleSequenceCollection; + comparisonConstraintSequencesCount = comparisonConstraintSequences.Count; + } for (int i = 0; i < comparisonConstraintSequencesCount; ++i) { SetComparisonConstraintRoleSequence comparisonConstraintSequence = comparisonConstraintSequences[i]; @@ -4985,7 +5023,7 @@ if (eligibleConstraint != setComparisonConstraint && constraintOwner == ((null == (toAlternateOwner = eligibleConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner) && (modalityChange || validationInfo.TestModality(constraintModality, eligibleConstraint.Modality)) && - (validationInfo.ConstraintTypesInPotentialConflict as IList<ConstraintType>).Contains(eligibleConstraint.ConstraintType) && + -1 != Array.IndexOf<ConstraintType>(validationInfo.ConstraintTypesInPotentialConflict, eligibleConstraint.ConstraintType) && !matchCallback(eligibleConstraint)) { return; @@ -4994,6 +5032,48 @@ } } break; + default: + if (modalityChange) + { + if (comparisonConstraintSequences == null) + { + comparisonConstraintSequences = setComparisonConstraint.RoleSequenceCollection; + comparisonConstraintSequencesCount = comparisonConstraintSequences.Count; + } + for (int i = 0; i < comparisonConstraintSequencesCount; ++i) + { + SetComparisonConstraintRoleSequence comparisonConstraintSequence = comparisonConstraintSequences[i]; + LinkedElementCollection<Role> sequenceRoles = comparisonConstraintSequence.RoleCollection; + int sequenceRoleCount = sequenceRoles.Count; + for (int j = 0; j < sequenceRoleCount; ++j) + { + Role selectedRole = sequenceRoles[j]; + LinkedElementCollection<ConstraintRoleSequence> sequences = selectedRole.ConstraintRoleSequenceCollection; + int sequenceCount = sequences.Count; + for (int k = 0; k < sequenceCount; ++k) + { + ConstraintRoleSequence eligibleSequence = sequences[k]; + IConstraint eligibleConstraint = eligibleSequence.Constraint; + if (eligibleConstraint != setComparisonConstraint && + -1 != Array.IndexOf<ConstraintType>(validationInfo.ConstraintTypesInPotentialConflict, eligibleConstraint.ConstraintType)) + { + if (validationInfo.DomainRoleToError.HasValue && + !matchCallback(setComparisonConstraint)) + { + return; + } + if (validationInfo.IntersectingDomainRoleToError.HasValue && + constraintOwner == ((null == (toAlternateOwner = eligibleConstraint as IHasAlternateOwner)) ? null : toAlternateOwner.UntypedAlternateOwner) && + !matchCallback(eligibleConstraint)) + { + return; + } + } + } + } + } + } + break; } } } @@ -11771,7 +11851,7 @@ //Implication new IntersectingConstraintValidation( IntersectingConstraintPattern.SubsetImpliedByMandatory, - IntersectingConstraintPatternOptions.None, + IntersectingConstraintPatternOptions.IntersectingConstraintModalityNotStronger, null, SetComparisonConstraintHasEqualityOrSubsetImpliedByMandatoryError.SetComparisonConstraintDomainRoleId, ConstraintType.Subset), @@ -11787,7 +11867,7 @@ //Bad ORM new IntersectingConstraintValidation( IntersectingConstraintPattern.SubsetContradictsMandatory, - IntersectingConstraintPatternOptions.None, + IntersectingConstraintPatternOptions.IntersectingConstraintModalityNotStronger, MandatoryConstraintHasNotWellModeledSubsetAndMandatoryError.MandatoryConstraintDomainRoleId, // UNDONE: CONSTRAINTINTERSECTION: This should be a many relationship SubsetConstraintHasNotWellModeledSubsetAndMandatoryError.SubsetConstraintDomainRoleId, ConstraintType.Subset), @@ -11986,7 +12066,7 @@ //Implication new IntersectingConstraintValidation( IntersectingConstraintPattern.SubsetImpliedByMandatory, - IntersectingConstraintPatternOptions.None, + IntersectingConstraintPatternOptions.IntersectingConstraintModalityNotWeaker, SetComparisonConstraintHasEqualityOrSubsetImpliedByMandatoryError.SetComparisonConstraintDomainRoleId, null, ConstraintType.SimpleMandatory), @@ -11994,7 +12074,7 @@ //Bad ORM new IntersectingConstraintValidation( IntersectingConstraintPattern.SubsetContradictsMandatory, - IntersectingConstraintPatternOptions.IntersectingConstraintModalityIgnored, + IntersectingConstraintPatternOptions.IntersectingConstraintModalityNotWeaker, SubsetConstraintHasNotWellModeledSubsetAndMandatoryError.SubsetConstraintDomainRoleId, MandatoryConstraintHasNotWellModeledSubsetAndMandatoryError.MandatoryConstraintDomainRoleId, // UNDONE: CONSTRAINTINTERSECTION: This should be a many relationship ConstraintType.SimpleMandatory), Modified: trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.cs =================================================================== --- trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.cs 2014-08-07 06:25:14 UTC (rev 1549) +++ trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.cs 2014-11-21 16:29:21 UTC (rev 1550) @@ -1619,15 +1619,21 @@ if (roleId == ObjectTypePlaysRole.PlayedRoleDomainRoleId) { string name = "Role"; - if (DomainRoleInfo.GetRolePlayer(elementLink, ObjectTypePlaysRole.PlayedRoleDomainRoleId) is SubtypeMetaRole) + CustomSerializedElementWriteStyle writeStyle = CustomSerializedElementWriteStyle.Element; + if (elementLink.Partition.AlternateId != null) { + name = ""; + writeStyle = CustomSerializedElementWriteStyle.NotWritten; + } + else if (DomainRoleInfo.GetRolePlayer(elementLink, ObjectTypePlaysRole.PlayedRoleDomainRoleId) is SubtypeMetaRole) + { name = "SubtypeMetaRole"; } else if (DomainRoleInfo.GetRolePlayer(elementLink, ObjectTypePlaysRole.PlayedRoleDomainRoleId) is SupertypeMetaRole) { name = "SupertypeMetaRole"; } - return new CustomSerializedElementInfo(null, name, null, CustomSerializedElementWriteStyle.Element, null); + return new CustomSerializedElementInfo(null, name, null, writeStyle, null); } if (roleId == EntityTypeHasPreferredIdentifier.PreferredIdentifierDomainRoleId) { Modified: trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.xml =================================================================== --- trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.xml 2014-08-07 06:25:14 UTC (rev 1549) +++ trunk/ORMModel/ObjectModel/ORMCore.SerializationExtensions.xml 2014-11-21 16:29:21 UTC (rev 1550) @@ -332,6 +332,24 @@ <se:Embed RelationshipName="ValueTypeHasValueConstraint" RoleName="ValueConstraint"/> </se:Container> <se:Link Name="Role" RelationshipName="ObjectTypePlaysRole" RoleName="PlayedRole"> + <se:ConditionalName Name="" WriteStyle="NotWritten"> + <plx:binaryOperator type="identityInequality"> + <plx:left> + <plx:callInstance name="AlternateId" type="property"> + <plx:callObject> + <plx:callInstance name="Partition" type="property"> + <plx:callObject> + <plx:nameRef name="elementLink" type="parameter"/> + </plx:callObject> + </plx:callInstance> + </plx:callObject> + </plx:callInstance> + </plx:left> + <plx:right> + <plx:nullKeyword/> + </plx:right> + </plx:binaryOperator> + </se:ConditionalName> <se:ConditionalName Name="SubtypeMetaRole"> <plx:binaryOperator type="typeEquality"> <plx:left> Modified: trunk/ORMModel/ShapeModel/ORMDiagram.cs =================================================================== --- trunk/ORMModel/ShapeModel/ORMDiagram.cs 2014-08-07 06:25:14 UTC (rev 1549) +++ trunk/ORMModel/ShapeModel/ORMDiagram.cs 2014-11-21 16:29:21 UTC (rev 1550) @@ -380,6 +380,7 @@ } Dictionary<object, object> topLevelContextInfo = null; object placementKey; + bool tightenPlacementKey = false; switch (placementOption) { case ORMPlacementOption.AllowMultipleShapes: @@ -387,6 +388,7 @@ break; case ORMPlacementOption.CreateNewShape: placementKey = MultiShapeUtility.ForceMultipleShapes; + tightenPlacementKey = true; break; default: placementKey = null; @@ -443,6 +445,12 @@ } if (shapeElement != null) { + if (tightenPlacementKey) + { + // We only want to force create the top level element, not its child elements. + topLevelContextInfo.Remove(placementKey); + topLevelContextInfo.Add(placementKey = MultiShapeUtility.AllowMultipleShapes, null); + } // Perform preliminary fixup if (null != beforeStandardFixupCallback) { @@ -450,7 +458,7 @@ } if (factType != null) { - FixupFactType(crossStoreCopy ? (FactType)element : factType, (FactTypeShape)shapeElement, false); + FixupFactType(crossStoreCopy ? (FactType)element : factType, shapeElement as FactTypeShape, false); } else if (objectType != null) { @@ -527,6 +535,7 @@ } Dictionary<object, object> topLevelContextInfo = null; object placementKey; + bool tightenPlacementKey = false; switch (placementOption) { case ORMPlacementOption.AllowMultipleShapes: @@ -534,6 +543,7 @@ break; case ORMPlacementOption.CreateNewShape: placementKey = MultiShapeUtility.ForceMultipleShapes; + tightenPlacementKey = true; break; default: placementKey = null; @@ -550,6 +560,12 @@ } if (shapeElement != null && fixupShapeCallback != null) { + if (tightenPlacementKey) + { + // We only want to force create the top level element, not its child elements. + topLevelContextInfo.Remove(placementKey); + topLevelContextInfo.Add(placementKey = MultiShapeUtility.AllowMultipleShapes, null); + } fixupShapeCallback(elementToPlace, shapeElement); } if (placementKey != null) @@ -585,12 +601,16 @@ } private void FixupFactType(FactType factType, FactTypeShape factTypeShape, bool childShapesMerged) { + if (factTypeShape == null) + { + return; + } bool duplicateShape = false; Objectification objectification = factType.Objectification; ObjectType nestingType = (objectification != null) ? objectification.NestingType : null; bool lookForNonDisplayedRelatedTypes = false; bool haveNonDisplayedRelatedTypes = false; - if (childShapesMerged && factTypeShape != null && IsMergingExternalStore) + if (childShapesMerged && IsMergingExternalStore) { // Override this setting if we're merging from an external store, which // can produce a merge of a shape that does not have all of the elements @@ -631,6 +651,13 @@ } } } + + // Make sure the role name shape visibility is correct. Visibility + // settings do not survive a merge operation, so we need to check + // this explicitly regardless of merge state. + factTypeShape.UpdateRoleNameDisplay(); + + // Handle other shapes related to roles. LinkedElementCollection<RoleBase> roleCollection = factType.RoleCollection; int roleCount = roleCollection.Count; int? unaryRoleIndex = FactType.GetUnaryRoleIndex(roleCollection); @@ -668,49 +695,19 @@ FixupRelatedLinks(DomainRoleInfo.GetElementLinks<ElementLink>(role, FactSetComparisonConstraint.FactTypeDomainRoleId)); } - // Make sure the role name shape visibility is correct. Visibility - // settings do not survive a merge operation, so we need to check - // this explicitly regardless of merge state. - factTypeShape.UpdateRoleNameDisplay(); - // Get the role value constraint and the link to it. RoleHasValueConstraint valueConstraintLink = RoleHasValueConstraint.GetLinkToValueConstraint(role); UnaryRoleCardinalityConstraint unaryRoleCardinality = (unaryRole == role) ? unaryRole.Cardinality : null; if (!childShapesMerged) { - // Pick up the role shape - //check if we have a specific shape or need to use the model element - if (factTypeShape == null) - { - FixUpLocalDiagram(factType, role); - } - else - { - FixUpLocalDiagram(factTypeShape as ShapeElement, role); - } - if (valueConstraintLink != null) { - if (factTypeShape == null) - { - FixUpLocalDiagram(factType, valueConstraintLink.ValueConstraint); - } - else - { - FixUpLocalDiagram(factTypeShape as ShapeElement, valueConstraintLink.ValueConstraint); - } + FixUpLocalDiagram(factTypeShape as ShapeElement, valueConstraintLink.ValueConstraint); } if (unaryRoleCardinality != null) { - if (factTypeShape == null) - { - FixUpLocalDiagram(factType, unaryRoleCardinality); - } - else - { - FixUpLocalDiagram(factTypeShape as ShapeElement, unaryRoleCardinality); - } + FixUpLocalDiagram(factTypeShape as ShapeElement, unaryRoleCardinality); } } // Role player links are not part of the merge hierarchy, add them for both @@ -725,14 +722,7 @@ LinkedElementCollection<ReadingOrder> orders = factType.ReadingOrderCollection; if (orders.Count != 0) { - if (factTypeShape == null) - { - FixUpLocalDiagram(factType, orders[0]); - } - else - { - FixUpLocalDiagram(factTypeShape as ShapeElement, orders[0]); - } + FixUpLocalDiagram(factTypeShape as ShapeElement, orders[0]); } } if (!duplicateShape) @@ -743,28 +733,10 @@ { if (!childShapesMerged) { - ObjectifiedFactTypeNameShape nameShape; ValueConstraint valueConstraint = nestingType.FindValueConstraint(false); ObjectTypeCardinalityConstraint cardinalityConstraint = nestingType.Cardinality; - if (factTypeShape == null) + if (factTypeShape.DisplayAsObjectType) { - foreach (ShapeElement newShape in FixUpLocalDiagram(factType, nestingType)) - { - if (null != (nameShape = newShape as ObjectifiedFactTypeNameShape)) - { - if (valueConstraint != null) - { - FixUpLocalDiagram(nameShape, valueConstraint); - } - if (cardinalityConstraint != null) - { - FixUpLocalDiagram(nameShape, cardinalityConstraint); - } - } - } - } - else if (factTypeShape.DisplayAsObjectType) - { if (valueConstraint != null) { FixUpLocalDiagram(factTypeShape, valueConstraint); @@ -774,16 +746,11 @@ FixUpLocalDiagram(factTypeShape, cardinalityConstraint); } } - else if (null != (nameShape = FixUpLocalDiagram(factTypeShape as ShapeElement, nestingType) as ObjectifiedFactTypeNameShape)) + else { - if (valueConstraint != null) - { - FixUpLocalDiagram(nameShape, valueConstraint); - } - if (cardinalityConstraint != null) - { - FixUpLocalDiagram(nameShape, cardinalityConstraint); - } + // If this creates an objectified fact type name shape it will fix up + // its own children. + FixUpLocalDiagram(factTypeShape as ShapeElement, nestingType); } } if (!duplicateShape || haveNonDisplayedRelatedTypes) @@ -794,6 +761,10 @@ } private void FixupObjectType(ObjectType objectType, ObjectTypeShape objectTypeShape, bool childShapesMerged) { + if (objectTypeShape == null) + { + return; + } bool duplicateShape = false; bool lookForNonDisplayedRelatedTypes = false; bool haveNonDisplayedRelatedTypes = false; @@ -828,7 +799,7 @@ { FixupObjectTypeLinks(objectType, haveNonDisplayedRelatedTypes); } - if (!childShapesMerged || (objectTypeShape != null && IsMergingExternalStore)) + if (!childShapesMerged || IsMergingExternalStore) { // If the shape comes from the local store the source shape should always be // in sync. However, if the shape comes from an external store, then it may not @@ -837,26 +808,11 @@ ObjectTypeCardinalityConstraint cardinalityConstraint; if (null != (valueConstraint = objectType.FindValueConstraint(false))) { - //check if we have a specific shape or need to use the model element - if (objectTypeShape == null) - { - FixUpLocalDiagram(objectType, valueConstraint); - } - else - { - FixUpLocalDiagram(objectTypeShape as ShapeElement, valueConstraint); - } + FixUpLocalDiagram(objectTypeShape as ShapeElement, valueConstraint); } if (null != (cardinalityConstraint = objectType.Cardinality)) { - if (objectTypeShape == null) - { - FixUpLocalDiagram(objectType, cardinalityConstraint); - } - else - { - FixUpLocalDiagram(objectTypeShape as ShapeElement, cardinalityConstraint); - } + FixUpLocalDiagram(objectTypeShape as ShapeElement, cardinalityConstraint); } } } Modified: trunk/ORMModel/Shell/ORMDocView.cs =================================================================== --- trunk/ORMModel/Shell/ORMDocView.cs 2014-08-07 06:25:14 UTC (rev 1549) +++ trunk/ORMModel/Shell/ORMDocView.cs 2014-11-21 16:29:21 UTC (rev 1550) @@ -685,6 +685,12 @@ /// </summary> protected override void OnSelectionChanged(EventArgs e) { + if (Store == null) + { + // This gets occasional calls during shutdown, especially if VS + // has been sitting for a while. Do a sanity check before proceeding. + return; + } base.OnSelectionChanged(e); CommandManager.UpdateCommandStatus(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |