/// <summary>
        /// Verifies that the expected collection events are raised from the <see cref="ValidationResultCollection"/>
        /// when <see cref="ValidationResultCollection.ReplaceErrors"/> is called for a property.
        /// </summary>
        /// <param name="member">The property that errors are being replaced for</param>
        /// <param name="replacementResults">The results to use as the replacement errors for the property for the replacement.</param>
        /// <param name="errorsChangedMembers">The array of member names to expect errors changed events for.</param>
        private static void VerifyPropertyReplacementEvents(string member, IEnumerable <ValidationResult> replacementResults, string[] errorsChangedMembers)
        {
            int           collectionChangedCount    = 0;
            int           hasErrorsChangedCount     = 0;
            List <string> propertyErrorsChangedList = new List <string>();

            Action          collectionChanged     = () => ++ collectionChangedCount;
            Action          hasErrorsChanged      = () => ++ hasErrorsChangedCount;
            Action <string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);

            collection.ReplaceErrors(member, replacementResults);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for first replacement");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "HasErrorsChanged count for first replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMembers.OrderBy(s => s)), "propertyErrorsChangedList for first replacement");

            collection.Add(new ValidationResult("Error", new string[] { member }));
            collectionChangedCount = 0;
            hasErrorsChangedCount  = 0;
            propertyErrorsChangedList.Clear();

            collection.ReplaceErrors(member, replacementResults);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for second replacement");
            Assert.AreEqual <int>(0, hasErrorsChangedCount, "HasErrorsChanged count for second replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMembers.OrderBy(s => s)), "propertyErrorsChangedList for second replacement");
        }
        public void ClearRaisesEvents()
        {
            int           collectionChangedCount    = 0;
            int           hasErrorsChangedCount     = 0;
            List <string> propertyErrorsChangedList = new List <string>();

            Action          collectionChanged     = () => ++ collectionChangedCount;
            Action          hasErrorsChanged      = () => ++ hasErrorsChangedCount;
            Action <string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);

            collection.Add(new ValidationResult("Property Error", new string[] { "Member" }));
            collection.Add(new ValidationResult("Entity Error", null));

            string[] errorsChangedMemberNames = new string[] { "Member", null };

            Assert.AreEqual <int>(2, collectionChangedCount, "collectionChangedCount after adding");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "hasErrorsChangedCount after adding");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList after adding");

            collectionChangedCount = 0;
            hasErrorsChangedCount  = 0;
            propertyErrorsChangedList.Clear();

            collection.Clear();

            // We only get one collection changed event because it's an atomic action
            Assert.AreEqual <int>(1, collectionChangedCount, "collectionChangedCount after clearing");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "hasErrorsChangedCount after clearing");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList after clearing");
        }
        /// <summary>
        /// Verifies that the expected collection events are raised from the <see cref="ValidationResultCollection"/>
        /// for validation results with the specified member names.
        /// </summary>
        /// <param name="validationResultMemberNames">
        /// The array of member names to create validation results for that will be
        /// added and removed from the collection.
        /// </param>
        /// <param name="errorsChangedMemberNames">The array of member names to expect errors changed events for.</param>
        private static void VerifyAddRemoveCollectionEvents(string[] validationResultMemberNames, string[] errorsChangedMemberNames)
        {
            int           collectionChangedCount    = 0;
            int           hasErrorsChangedCount     = 0;
            List <string> propertyErrorsChangedList = new List <string>();

            Action          collectionChanged     = () => ++ collectionChangedCount;
            Action          hasErrorsChanged      = () => ++ hasErrorsChangedCount;
            Action <string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);
            ValidationResult           vr1        = new ValidationResult("Error 1", validationResultMemberNames);

            collection.Add(vr1);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for first add");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "HasErrorsChanged count for first add");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for first add");

            collectionChangedCount = 0;
            hasErrorsChangedCount  = 0;
            propertyErrorsChangedList.Clear();

            ValidationResult vr2 = new ValidationResult("Error 2", validationResultMemberNames);

            collection.Add(vr2);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for second add");
            Assert.AreEqual <int>(0, hasErrorsChangedCount, "HasErrorsChanged count for second add");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for second add");

            collectionChangedCount = 0;
            hasErrorsChangedCount  = 0;
            propertyErrorsChangedList.Clear();

            collection.Remove(vr1);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for first remove");
            Assert.AreEqual <int>(0, hasErrorsChangedCount, "HasErrorsChanged count for first remove");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for first remove");

            collectionChangedCount = 0;
            hasErrorsChangedCount  = 0;
            propertyErrorsChangedList.Clear();

            collection.Remove(vr2);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for second remove");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "HasErrorsChanged count for second remove");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for second remove");
        }
        /// <summary>
        /// Verifies that the expected collection events are raised from the <see cref="ValidationResultCollection"/>
        /// for validation results with the specified member names.
        /// </summary>
        /// <param name="validationResultMemberNames">
        /// The array of member names to create validation results for that will be
        /// added and removed from the collection.
        /// </param>
        /// <param name="errorsChangedMemberNames">The array of member names to expect errors changed events for.</param>
        private static void VerifyAddRemoveCollectionEvents(string[] validationResultMemberNames, string[] errorsChangedMemberNames)
        {
            int collectionChangedCount = 0;
            int hasErrorsChangedCount = 0;
            List<string> propertyErrorsChangedList = new List<string>();

            Action collectionChanged = () => ++collectionChangedCount;
            Action hasErrorsChanged = () => ++hasErrorsChangedCount;
            Action<string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);
            ValidationResult vr1 = new ValidationResult("Error 1", validationResultMemberNames);
            collection.Add(vr1);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for first add");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "HasErrorsChanged count for first add");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for first add");

            collectionChangedCount = 0;
            hasErrorsChangedCount = 0;
            propertyErrorsChangedList.Clear();

            ValidationResult vr2 = new ValidationResult("Error 2", validationResultMemberNames);
            collection.Add(vr2);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for second add");
            Assert.AreEqual<int>(0, hasErrorsChangedCount, "HasErrorsChanged count for second add");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for second add");

            collectionChangedCount = 0;
            hasErrorsChangedCount = 0;
            propertyErrorsChangedList.Clear();

            collection.Remove(vr1);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for first remove");
            Assert.AreEqual<int>(0, hasErrorsChangedCount, "HasErrorsChanged count for first remove");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for first remove");

            collectionChangedCount = 0;
            hasErrorsChangedCount = 0;
            propertyErrorsChangedList.Clear();

            collection.Remove(vr2);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for second remove");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "HasErrorsChanged count for second remove");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList for second remove");
        }
        public void ReplaceAllResultsWithNothing()
        {
            // This test differs from the other replacement tests enough that it doesn't use the same helper method

            string member = "Member";

            string[] memberNames      = new string[] { member };
            string[] replacementNames = new string[] { member };
            IEnumerable <ValidationResult> initialResults     = new ValidationResult[] { new ValidationResult("Error", memberNames) };
            IEnumerable <ValidationResult> replacementResults = Enumerable.Empty <ValidationResult>();

            int           collectionChangedCount    = 0;
            int           hasErrorsChangedCount     = 0;
            List <string> propertyErrorsChangedList = new List <string>();

            Action          collectionChanged     = () => ++ collectionChangedCount;
            Action          hasErrorsChanged      = () => ++ hasErrorsChangedCount;
            Action <string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);

            collection.ReplaceErrors(initialResults);

            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for first replacement");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "HasErrorsChanged count for first replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(replacementNames.OrderBy(s => s)), "propertyErrorsChangedList for first replacement");

            collection.Add(new ValidationResult("Error", new string[] { member }));
            collectionChangedCount = 0;
            hasErrorsChangedCount  = 0;
            propertyErrorsChangedList.Clear();

            collection.ReplaceErrors(replacementResults);

            // Notice that HasErrors changes again because we no longer have any errors
            Assert.AreEqual <int>(1, collectionChangedCount, "CollectionChanged count for second replacement");
            Assert.AreEqual <int>(1, hasErrorsChangedCount, "HasErrorsChanged count for second replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(replacementNames.OrderBy(s => s)), "propertyErrorsChangedList for second replacement");
        }
        /// <summary>
        /// Verifies that the expected collection events are raised from the <see cref="ValidationResultCollection"/>
        /// when <see cref="ValidationResultCollection.ReplaceErrors"/> is called for a property.
        /// </summary>
        /// <param name="member">The property that errors are being replaced for</param>
        /// <param name="replacementResults">The results to use as the replacement errors for the property for the replacement.</param>
        /// <param name="errorsChangedMembers">The array of member names to expect errors changed events for.</param>
        private static void VerifyPropertyReplacementEvents(string member, IEnumerable<ValidationResult> replacementResults, string[] errorsChangedMembers)
        {
            int collectionChangedCount = 0;
            int hasErrorsChangedCount = 0;
            List<string> propertyErrorsChangedList = new List<string>();

            Action collectionChanged = () => ++collectionChangedCount;
            Action hasErrorsChanged = () => ++hasErrorsChangedCount;
            Action<string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);
            collection.ReplaceErrors(member, replacementResults);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for first replacement");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "HasErrorsChanged count for first replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMembers.OrderBy(s => s)), "propertyErrorsChangedList for first replacement");

            collection.Add(new ValidationResult("Error", new string[] { member }));
            collectionChangedCount = 0;
            hasErrorsChangedCount = 0;
            propertyErrorsChangedList.Clear();

            collection.ReplaceErrors(member, replacementResults);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for second replacement");
            Assert.AreEqual<int>(0, hasErrorsChangedCount, "HasErrorsChanged count for second replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMembers.OrderBy(s => s)), "propertyErrorsChangedList for second replacement");
        }
        public void ClearRaisesEvents()
        {
            int collectionChangedCount = 0;
            int hasErrorsChangedCount = 0;
            List<string> propertyErrorsChangedList = new List<string>();

            Action collectionChanged = () => ++collectionChangedCount;
            Action hasErrorsChanged = () => ++hasErrorsChangedCount;
            Action<string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);
            collection.Add(new ValidationResult("Property Error", new string[] { "Member" }));
            collection.Add(new ValidationResult("Entity Error", null));

            string[] errorsChangedMemberNames = new string[] { "Member", null };

            Assert.AreEqual<int>(2, collectionChangedCount, "collectionChangedCount after adding");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "hasErrorsChangedCount after adding");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList after adding");

            collectionChangedCount = 0;
            hasErrorsChangedCount = 0;
            propertyErrorsChangedList.Clear();

            collection.Clear();

            // We only get one collection changed event because it's an atomic action
            Assert.AreEqual<int>(1, collectionChangedCount, "collectionChangedCount after clearing");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "hasErrorsChangedCount after clearing");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(errorsChangedMemberNames.OrderBy(s => s)), "propertyErrorsChangedList after clearing");
        }
        public void ReplaceAllResultsWithNothing()
        {
            // This test differs from the other replacement tests enough that it doesn't use the same helper method

            string member = "Member";
            string[] memberNames = new string[] { member };
            string[] replacementNames = new string[] { member };
            IEnumerable<ValidationResult> initialResults = new ValidationResult[] { new ValidationResult("Error", memberNames) };
            IEnumerable<ValidationResult> replacementResults = Enumerable.Empty<ValidationResult>();

            int collectionChangedCount = 0;
            int hasErrorsChangedCount = 0;
            List<string> propertyErrorsChangedList = new List<string>();

            Action collectionChanged = () => ++collectionChangedCount;
            Action hasErrorsChanged = () => ++hasErrorsChangedCount;
            Action<string> propertyErrorsChanged = propertyName => propertyErrorsChangedList.Add(propertyName);

            ValidationResultCollection collection = new TestValidationResultCollection(collectionChanged, hasErrorsChanged, propertyErrorsChanged);
            collection.ReplaceErrors(initialResults);

            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for first replacement");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "HasErrorsChanged count for first replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(replacementNames.OrderBy(s => s)), "propertyErrorsChangedList for first replacement");

            collection.Add(new ValidationResult("Error", new string[] { member }));
            collectionChangedCount = 0;
            hasErrorsChangedCount = 0;
            propertyErrorsChangedList.Clear();

            collection.ReplaceErrors(replacementResults);

            // Notice that HasErrors changes again because we no longer have any errors
            Assert.AreEqual<int>(1, collectionChangedCount, "CollectionChanged count for second replacement");
            Assert.AreEqual<int>(1, hasErrorsChangedCount, "HasErrorsChanged count for second replacement");
            Assert.IsTrue(propertyErrorsChangedList.OrderBy(s => s).SequenceEqual(replacementNames.OrderBy(s => s)), "propertyErrorsChangedList for second replacement");
        }