/// <summary> /// Updates the DataGrid's validation results, modifies the ValidationSummary's items, /// and sets the IsValid states of the UIElements. /// </summary> /// <param name="newValidationResults">New validation results.</param> /// <param name="scrollIntoView">If the validation results have changed, scrolls the editing row into view.</param> private void UpdateValidationResults(List<ValidationResult> newValidationResults, bool scrollIntoView) { bool validationResultsChanged = false; Debug.Assert(this.EditingRow != null); // Remove the validation results that have been fixed List<ValidationResult> removedValidationResults = new List<ValidationResult>(); foreach (ValidationResult oldValidationResult in this._validationResults) { if (oldValidationResult != null && !newValidationResults.ContainsEqualValidationResult(oldValidationResult)) { removedValidationResults.Add(oldValidationResult); validationResultsChanged = true; } } foreach (ValidationResult removedValidationResult in removedValidationResults) { this._validationResults.Remove(removedValidationResult); if (this._validationSummary != null) { ValidationSummaryItem removedValidationSummaryItem = this.FindValidationSummaryItem(removedValidationResult); if (removedValidationSummaryItem != null) { this._validationSummary.Errors.Remove(removedValidationSummaryItem); } } } // Add any validation results that were just introduced foreach (ValidationResult newValidationResult in newValidationResults) { if (newValidationResult != null && !this._validationResults.ContainsEqualValidationResult(newValidationResult)) { this._validationResults.Add(newValidationResult); if (this._validationSummary != null && ShouldDisplayValidationResult(newValidationResult)) { ValidationSummaryItem newValidationSummaryItem = this.CreateValidationSummaryItem(newValidationResult); if (newValidationSummaryItem != null) { this._validationSummary.Errors.Add(newValidationSummaryItem); } } validationResultsChanged = true; } } if (validationResultsChanged) { this.UpdateValidationStatus(); } if (!this.IsValid && scrollIntoView) { // Scroll the row with the error into view. int editingRowSlot = this.EditingRow.Slot; if (this._validationSummary != null) { // If the number of errors has changed, then the ValidationSummary will be a different size, // and we need to delay our call to ScrollSlotIntoView this.InvalidateMeasure(); this.Dispatcher.BeginInvoke(delegate { // It's possible that the DataContext or ItemsSource has changed by the time we reach this code, // so we need to ensure that the editing row still exists before scrolling it into view if (!this.IsSlotOutOfBounds(editingRowSlot)) { this.ScrollSlotIntoView(editingRowSlot, false /*scrolledHorizontally*/); } }); } else { this.ScrollSlotIntoView(editingRowSlot, false /*scrolledHorizontally*/); } } }
private bool ValidateEditingRow() { if (this.EditingRow != null) { List<ValidationResult> newValidationResults = new List<ValidationResult>(); ValidationContext context = new ValidationContext(this.EditingRow.DataContext, null, null); if (!Validator.TryValidateObject(this.EditingRow.DataContext, context, newValidationResults, true)) { bool validationResultsChanged = false; // Remove the validation results that have been fixed List<ValidationResult> removedValidationResults = new List<ValidationResult>(); foreach (ValidationResult oldValidationResult in this._validationResults) { if (oldValidationResult != null && !newValidationResults.ContainsEqualValidationResult(oldValidationResult)) { removedValidationResults.Add(oldValidationResult); validationResultsChanged = true; } } foreach (ValidationResult removedValidationResult in removedValidationResults) { this._validationResults.Remove(removedValidationResult); if (this._validationSummary != null) { ValidationSummaryItem removedValidationSummaryItem = this.FindValidationSummaryItem(removedValidationResult); if (removedValidationSummaryItem != null) { this._validationSummary.Errors.Remove(removedValidationSummaryItem); } } } // Add any validation results that were just introduced foreach (ValidationResult newValidationResult in newValidationResults) { if (newValidationResult != null && !this._validationResults.ContainsEqualValidationResult(newValidationResult)) { this._validationResults.Add(newValidationResult); if (this._validationSummary != null) { ValidationSummaryItem newValidationSummaryItem = this.CreateValidationSummaryItem(newValidationResult); if (newValidationSummaryItem != null) { this._validationSummary.Errors.Add(newValidationSummaryItem); } } validationResultsChanged = true; } } // Scroll the row with the error into view int editingRowSlot = this.EditingRow.Slot; if (validationResultsChanged && this._validationSummary != null) { // If the number of errors has changed, then the ValidationSummary will be a different size, // and we need to delay our call to ScrollSlotIntoView this.InvalidateMeasure(); this.Dispatcher.BeginInvoke(delegate { // It's possible that the DataContext or ItemsSource has changed by the time we reach this code, // so we need to ensure that the editing row still exists before scrolling it into view if (!this.IsSlotOutOfBounds(editingRowSlot)) { this.ScrollSlotIntoView(editingRowSlot, false /*scrolledHorizontally*/); } }); } else { this.ScrollSlotIntoView(editingRowSlot, false /*scrolledHorizontally*/); } this.IsValid = this.EditingRow.IsValid = false; this.EditingRow.ApplyState(true); return false; } } // No validation errors, so reset the status ResetValidationStatus(); return true; }