Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / Validation / ValidationService.cs / 1591162 / ValidationService.cs
//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //--------------------------------------------------------------- namespace System.Activities.Presentation.Validation { using System.Activities.Presentation.Model; using System.Activities.Presentation.Services; using System.Activities.Presentation.Xaml; using System.Activities.Statements; using System.Activities.Validation; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime; using System.Text; using System.Windows.Threading; using Microsoft.VisualBasic.Activities; using Microsoft.Win32; using System.Activities.ExpressionParser; using System.Activities.Presentation.View; using System.Activities.Expressions; using System.ComponentModel; using System.Activities.XamlIntegration; public enum ValidationState { // The numeric values of each of the enum values indicate the severity of the error. // The higher the number is, the more severe the error. See the MarkError method in the // ValidationService class for example of usage. Error = 3, Warning = 2, ChildInvalid = 1, Valid = 0 } internal enum ValidationReason { Unknown, Load, Save, ModelChange, } [Fx.Tag.XamlVisible(false)] public class ValidationService { static PropertyInfo parentPropertyInfo; EditingContext context; ModelService modelService; ModelTreeManager modelTreeManager; WorkflowViewService viewService; IValidationErrorService errorService; // Dictionary which maps the activities to their error messages and indicators // NOTE: Valid Workflow Elements/Model Items do not appear in this dictionary, // only elements which violated a constraint (Errors or Warnings or Child Validation Issues) DictionaryvalidationErrors; // Attached properties for error visuals AttachedProperty validationStateProperty; AttachedProperty validationMessageProperty; internal event EventHandler ValidationCompleted; internal class ErrorsMarkedEventArgs : EventArgs { ICollection errors; ValidationReason reason; ModelTreeManager modelTreeManager; EditingContext context; public ErrorsMarkedEventArgs(ICollection errors, ValidationReason reason, ModelTreeManager modelTreeManager, EditingContext context) { this.errors = errors; this.reason = reason; this.modelTreeManager = modelTreeManager; this.context = context; } public ICollection Errors { get { return this.errors; } } public ValidationReason Reason { get { return this.reason; } } public ModelTreeManager ModelTreeManager { get { return this.modelTreeManager; } } public bool Handled { get; set; } public EditingContext Context { get { return this.context; } } } internal event EventHandler ErrorsMarked; Sequence bodyPlaceholder; ValidationSettings settings; bool isValidationDisabled = false; const string ValidationRegKeyName = "DisableValidateOnModelItemChanged"; const string ValidationRegKeyInitialPath = "Software\\Microsoft\\.NETFramework\\"; [ThreadStatic] static StringBuilder errorBuilder; private static StringBuilder ErrorBuilder { get { if (errorBuilder == null) { errorBuilder = new StringBuilder(); } return errorBuilder; } } public ValidationService(EditingContext context) { this.context = context; this.settings = new ValidationSettings(); this.context.Services.Subscribe (new SubscribeServiceCallback (OnModelServiceAvailable)); this.context.Services.Subscribe (new SubscribeServiceCallback (OnModelTreeManagerAvailable)); this.context.Services.Subscribe (new SubscribeServiceCallback (OnErrorServiceAvailable)); this.context.Services.Subscribe (new SubscribeServiceCallback (OnAttachedPropertiesServiceAvailable)); AssemblyName currentAssemblyName = Assembly.GetExecutingAssembly().GetName(); StringBuilder validationKeyPath = new StringBuilder(90); validationKeyPath.Append(ValidationRegKeyInitialPath); validationKeyPath.AppendFormat("{0}{1}{2}", "v", currentAssemblyName.Version.ToString(), "\\"); validationKeyPath.Append(currentAssemblyName.Name); RegistryKey validationRegistryKey = Registry.CurrentUser.OpenSubKey(validationKeyPath.ToString()); if (validationRegistryKey != null) { object value = validationRegistryKey.GetValue(ValidationRegKeyName); this.isValidationDisabled = (value != null && string.Equals("1", value.ToString())); validationRegistryKey.Close(); } } Sequence BodyPlaceholder { get { if (null == this.bodyPlaceholder) { this.bodyPlaceholder = new Sequence(); } return this.bodyPlaceholder; } } public ValidationSettings Settings { get { return this.settings; } } WorkflowViewService ViewService { get { if (null == this.viewService) { this.viewService = (WorkflowViewService)this.context.Services.GetService (); } return this.viewService; } } void OnAttachedPropertiesServiceAvailable(AttachedPropertiesService attachedPropertiesService) { this.validationStateProperty = new AttachedProperty () { Getter = (modelItem) => GetValidationState(modelItem), Name = "ValidationState", OwnerType = typeof(Activity) }; attachedPropertiesService.AddProperty(this.validationStateProperty); this.validationMessageProperty = new AttachedProperty () { Getter = (modelItem) => GetValidationMessage(modelItem), Name = "ValidationMessage", OwnerType = typeof(Activity) }; attachedPropertiesService.AddProperty(this.validationMessageProperty); } ValidationState GetValidationState(ModelItem modelItem) { ValidationState validationState = ValidationState.Valid; ValidationErrorState validationError = GetValidationError(modelItem); if (validationError != null) { validationState = validationError.ValidationState; } return validationState; } string GetValidationMessage(ModelItem modelItem) { string errorMessage = string.Empty; ValidationErrorState validationError = GetValidationError(modelItem); if (validationError != null) { if (validationError.ErrorMessages != null) { ValidationService.ErrorBuilder.Clear(); foreach (string message in validationError.ErrorMessages) { ValidationService.ErrorBuilder.AppendLine(message); } ValidationService.ErrorBuilder.Remove(errorBuilder.Length - 1, 1); errorMessage = ValidationService.ErrorBuilder.ToString(); } } return errorMessage; } ValidationErrorState GetValidationError(ModelItem modelItem) { ValidationErrorState validationError = null; Activity workflowElement = modelItem.GetCurrentValue() as Activity; if (workflowElement != null) { this.ValidationErrors.TryGetValue(workflowElement, out validationError); } return validationError; } void AddValidationError(ModelItem modelItem, ValidationErrorState error) { Activity workflowElement = modelItem.GetCurrentValue() as Activity; Fx.Assert(workflowElement != null, "modelItem current value can't be null"); this.ValidationErrors.Add(workflowElement, error); } void OnModelServiceAvailable(ModelService modelService) { if (modelService != null) { this.modelService = modelService; } } void OnModelTreeManagerAvailable(ModelTreeManager modelTreeManager) { if (modelTreeManager != null) { this.modelTreeManager = modelTreeManager; } } void OnErrorServiceAvailable(IValidationErrorService errorService) { if (errorService != null) { this.errorService = errorService; if (this.isValidationDisabled) { this.errorService.ShowValidationErrors(new List { new ValidationErrorInfo(new ValidationError(SR.ValidationDisabledWarning, true)) }); } } } private void NotifyValidationPropertiesChanged(ModelItem modelItem) { // Notify an update to the attached properties this.validationStateProperty.NotifyPropertyChanged(modelItem); this.validationMessageProperty.NotifyPropertyChanged(modelItem); } public void ValidateWorkflow() { ValidateWorkflow(ValidationReason.Unknown); } internal void ValidateWorkflow(ValidationReason reason) { if (!isValidationDisabled) { ValidateActivity(GetRootElement(), reason); } } Activity GetRootElement() { Activity rootElement = null; Fx.Assert(this.modelService != null, "ModelService is null."); // ModelService should not be null ModelItem rootItem = this.modelService.Root; object root = rootItem.GetCurrentValue(); //special case handling for ActivityBuilder - its arguments must be converted to variables before validation. //otherwise, there will be validation error for each argument referenced if (root is ActivityBuilder) { var activityBuilder = (ActivityBuilder)root; this.BodyPlaceholder.Activities.Clear(); this.BodyPlaceholder.Variables.Clear(); if (activityBuilder.Implementation != null) { this.BodyPlaceholder.Activities.Add(activityBuilder.Implementation); VisualBasic.SetSettings(this.BodyPlaceholder, VisualBasic.GetSettings(root)); } ActivityBuilderHelper.GetVariables(activityBuilder).ForEach(variable => this.BodyPlaceholder.Variables.Add(variable)); rootElement = this.BodyPlaceholder; } else { rootElement = rootItem.GetRootActivity(); } return rootElement; } // Validate the imported WF element (and thus all its children) void ValidateActivity(Activity workflowElement, ValidationReason reason) { if (workflowElement != null) { Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action( () => { DesignerPerfEventProvider perfProvider = this.context.Services.GetService (); perfProvider.WorkflowDesignerValidationStart(); ValidationResults results = null; ValidationErrorInfo validationErrorInfo = null; try { results = ActivityValidationServices.Validate(workflowElement, this.settings); } catch (System.Exception e) { ModelItem rootModelItem = this.modelService.Root; Activity rootActivity = rootModelItem.GetRootActivity(); if (rootActivity != null) { // We dont want any crash propagating from here as it causes VS to crash. if (!this.ValidationErrors.ContainsKey(rootActivity)) { ValidationErrorState validationError = new ValidationErrorState(new List (), ValidationState.Error); this.ValidationErrors.Add(rootActivity, validationError); } else { this.ValidationErrors[rootActivity].ValidationState = ValidationState.Error; } this.ValidationErrors[rootActivity].ErrorMessages.Add(e.ToString()); // Notify an update to the attached properties this.NotifyValidationPropertiesChanged(rootModelItem); } validationErrorInfo = new ValidationErrorInfo(e.ToString()); } List validationErrors = null; if (results != null) { validationErrors = new List (results.Errors); validationErrors.AddRange(results.Warnings); } bool needsToMarkValidationErrors = false; if (validationErrors != null) { needsToMarkValidationErrors = MarkErrors(validationErrors, reason); } if (this.errorService != null) // Error service could be null if no implementation has been provided { List errors = new List (); if (validationErrors != null && needsToMarkValidationErrors) { foreach (ValidationError validationError in validationErrors) { ValidationErrorInfo error = new ValidationErrorInfo(validationError); errors.Add(error); } } if (validationErrorInfo != null) { errors.Add(validationErrorInfo); } this.errorService.ShowValidationErrors(errors); } perfProvider.WorkflowDesignerValidationEnd(); this.OnValidationCompleted(); })); } } protected virtual void OnValidationCompleted() { if (this.ValidationCompleted != null) { this.ValidationCompleted(this, new EventArgs()); } } // Find model item and properly create it if necessary. ModelItem FindModelItem(Activity element) { List parentChain = GetParentChain(element); Fx.Assert(parentChain != null, "Cannot find parent chain for " + element.DisplayName); Fx.Assert(this.modelTreeManager != null, "ModelTreeManager is null."); // ModelTreeManager should not be null ModelItem lowestModelItem = null; foreach (Activity parent in parentChain) { lowestModelItem = this.modelTreeManager.GetModelItem(parent); if (lowestModelItem != null) { break; } } Fx.Assert(lowestModelItem != null, "Cannot find lowest model item for parents of " + element.DisplayName); // Root ModelItem should not be null at this point // Walk the tree to create all the model items until it found the model item for the element. return this.modelTreeManager.FindFirst(lowestModelItem, (modelItem) => (modelItem.GetCurrentValue() == element)); } internal static Activity GetParent(Activity childActivity) { // Obtaining the parent from childActivity using (private) reflection. if (parentPropertyInfo == null) { parentPropertyInfo = typeof(Activity).GetProperty("Parent", BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic); } Fx.Assert(parentPropertyInfo != null, "Activity.Parent is not defined"); return parentPropertyInfo.GetValue(childActivity, null) as Activity; } // Get the parent chain of this activity. // Can't use GetParentChain activity because it can only be used in a Constraint. internal static List GetParentChain(Activity activity) { List parentChain = new List (); while (activity != null) { activity = GetParent(activity); if (activity != null) { parentChain.Add(activity); } } return parentChain; } bool MarkErrors(ICollection errors, ValidationReason reason) { // Clear the previous errors/warnings and update the visuals ClearErrors(); Fx.Assert(this.modelTreeManager != null, "ModelTreeManager is null."); // ModelTreeManager should not be null if (HandleErrorsMarked(errors, reason)) { return false; } // Iterate through the new violation list and mark errors/warnings foreach (ValidationError error in errors) { if (error.Source != null) { ModelItem modelItem = this.modelTreeManager.GetModelItem(error.Source); if (modelItem != null) { MarkError(error, modelItem); } else { MarkUnmappedValidationError(error); } } } return true; } bool HandleErrorsMarked(ICollection errors, ValidationReason reason) { if (this.ErrorsMarked != null) { ErrorsMarkedEventArgs arg = new ErrorsMarkedEventArgs (errors, reason, this.modelTreeManager, this.context); this.ErrorsMarked(this, arg); return arg.Handled; } return false; } void MarkUnmappedValidationError(ValidationError validationError) { Activity errorSource = validationError.Source; AddUnmappedValidationError(errorSource, validationError); // Mark errorSource's ancestors. foreach (Activity parent in GetParentChain(errorSource)) { ModelItem modelItem = this.modelTreeManager.GetModelItem(parent); if (modelItem == null) { AddUnmappedValidationError(parent, validationError); } else { // This parent already have a model item. // Then MarkError will propagate to all its ancestors' ModelItem. MarkParents(modelItem, validationError.IsWarning ? ValidationState.Warning : ValidationState.Error); break; } } } void AddUnmappedValidationError(Activity activity, ValidationError validationError) { ValidationErrorState currentError; if (!this.ValidationErrors.TryGetValue(activity, out currentError)) { currentError = new ValidationErrorState(new List (), ValidationState.Valid); this.ValidationErrors.Add(activity, currentError); } MergeValidationError(currentError, validationError); } static void MergeValidationError(ValidationErrorState originalError, ValidationError newError) { if (originalError.ValidationState == ValidationState.ChildInvalid) { // If original error is due to child's issue, clear the error list, // as we don't care about its child's issues anymore and want to add its own issues. originalError.ErrorMessages.Clear(); } ValidationState errorState = newError.IsWarning ? ValidationState.Warning : ValidationState.Error; if (originalError.ValidationState < errorState) { // Promote to the higher level of violation. originalError.ValidationState = errorState; } if (newError.IsWarning) { originalError.ErrorMessages.Add(string.Format(CultureInfo.CurrentUICulture, "{0}{1}", SR.WarningPrefix, newError.Message)); } else { originalError.ErrorMessages.Add(newError.Message); } } // Mark this error to corresponding ModelItem. // Mark all its ancestors accordingly. void MarkError(ValidationError error, ModelItem modelItem) { ValidationErrorState currentError = this.GetValidationError(modelItem); if (currentError == null) { currentError = new ValidationErrorState(new List (), ValidationState.Valid); this.AddValidationError(modelItem, currentError); } MergeValidationError(currentError, error); MarkParents(modelItem.Parent, this.GetValidationState(modelItem)); // Notify an update to the attached properties NotifyValidationPropertiesChanged(modelItem); } void MarkParents(ModelItem parentModelItem, ValidationState childValidationState) { List childErrors = new List (); childErrors.Add(SR.ChildValidationError); Activity parentActivity; while (parentModelItem != null) { parentActivity = parentModelItem.GetCurrentValue() as Activity; if (parentActivity != null) { bool updateAttachedProperties = false; ValidationErrorState validationError; if (!this.ValidationErrors.TryGetValue(parentActivity, out validationError)) { validationError = new ValidationErrorState(childErrors, ValidationState.ChildInvalid); this.AddValidationError(parentModelItem, validationError); updateAttachedProperties = true; } if (validationError.ValidationState < childValidationState) { validationError.ValidationState = childValidationState; updateAttachedProperties = true; } // Notify and update to the attached properties if (updateAttachedProperties) { NotifyValidationPropertiesChanged(parentModelItem); } } parentModelItem = parentModelItem.Parent; } } void ClearErrors() { // Copy over the previously marked model items before you clear the dictionaries Activity[] oldErrorList = new Activity[this.ValidationErrors.Count]; this.ValidationErrors.Keys.CopyTo(oldErrorList, 0); this.ValidationErrors.Clear(); // Iterate through the previously marked model items and notify an update to the attached properties ModelItem modelItem; foreach (Activity workflowElement in oldErrorList) { modelItem = this.modelTreeManager.GetModelItem(workflowElement); if (modelItem != null) { NotifyValidationPropertiesChanged(modelItem); } } } public void NavigateToError(string id) { ModelItem modelItem = null; if (id != null) { Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action( () => { Activity errorElement = ActivityValidationServices.Resolve(GetRootElement(), id); if (errorElement != null) { Fx.Assert(this.modelTreeManager != null, "ModelTreeManager is null."); // ModelTreeManager should not be null modelItem = this.modelTreeManager.GetModelItem(errorElement) ?? this.FindModelItem(errorElement); if (modelItem != null) { // For a VB Expression, need to focus to its parent instead. Activity activity = modelItem.GetCurrentValue() as Activity; if (activity != null && (activity.IsVisualBasicExpression())) { ModelItem parent = modelItem.Parent; while (parent != null && this.ViewService.GetDesignerType(parent.ItemType) == null) { parent = parent.Parent; } if (parent != null) { modelItem = parent; } } modelItem.Focus(); } } })); } } // Properties Dictionary ValidationErrors { get { if (this.validationErrors == null) { this.validationErrors = new Dictionary (); } return this.validationErrors; } } internal AttachedProperty ValidationStateProperty { get { return this.validationStateProperty; } } internal AttachedProperty ValidationMessageProperty { get { return this.validationMessageProperty; } } class ValidationErrorState { internal ValidationErrorState(List errorMessages, ValidationState validationState) { this.ErrorMessages = errorMessages; this.ValidationState = validationState; } internal List ErrorMessages { get; set; } internal ValidationState ValidationState { get; set; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ThicknessAnimationUsingKeyFrames.cs
- MaterialGroup.cs
- ColorConverter.cs
- mediaclock.cs
- ItemType.cs
- SimpleType.cs
- SqlMethodAttribute.cs
- EventLevel.cs
- ScriptingRoleServiceSection.cs
- ApplicationGesture.cs
- DefaultPrintController.cs
- ViewKeyConstraint.cs
- ElapsedEventArgs.cs
- XmlWriterSettings.cs
- ConfigurationPropertyCollection.cs
- BindingSource.cs
- WithStatement.cs
- WSUtilitySpecificationVersion.cs
- SchemaTableColumn.cs
- Popup.cs
- OdbcReferenceCollection.cs
- HtmlProps.cs
- DES.cs
- datacache.cs
- WebPartVerb.cs
- WsatServiceAddress.cs
- IdleTimeoutMonitor.cs
- BulletedListDesigner.cs
- WebPartMovingEventArgs.cs
- EntityContainerAssociationSet.cs
- DataGridViewControlCollection.cs
- MessageContractExporter.cs
- TypeElement.cs
- ReadWriteControlDesigner.cs
- ValidationRule.cs
- PersistenceTypeAttribute.cs
- SHA256Managed.cs
- XmlBinaryWriter.cs
- DoubleKeyFrameCollection.cs
- ScriptControl.cs
- QueryOperatorEnumerator.cs
- DataGridViewAutoSizeColumnModeEventArgs.cs
- TimelineGroup.cs
- SchemaComplexType.cs
- EmissiveMaterial.cs
- SafeHandle.cs
- XomlCompilerError.cs
- __ConsoleStream.cs
- SmiEventStream.cs
- RubberbandSelector.cs
- unitconverter.cs
- TableChangeProcessor.cs
- HttpWriter.cs
- SyndicationDeserializer.cs
- CommandID.cs
- CodeAttachEventStatement.cs
- Padding.cs
- Size3DValueSerializer.cs
- CompiledWorkflowDefinitionContext.cs
- PassportAuthenticationModule.cs
- NameValueFileSectionHandler.cs
- SizeChangedEventArgs.cs
- ProtocolsConfiguration.cs
- DataGridViewButtonColumn.cs
- SelectionHighlightInfo.cs
- FrameworkContextData.cs
- ExpandedWrapper.cs
- LayeredChannelListener.cs
- EventlogProvider.cs
- XmlDataImplementation.cs
- ButtonChrome.cs
- DBConnection.cs
- ListViewItemMouseHoverEvent.cs
- ProfilePropertyNameValidator.cs
- HeaderLabel.cs
- Events.cs
- ConfigXmlReader.cs
- SystemInformation.cs
- HttpHostedTransportConfiguration.cs
- ScriptManagerProxy.cs
- SqlDataSource.cs
- ReflectionTypeLoadException.cs
- ProviderSettingsCollection.cs
- TraceListeners.cs
- HGlobalSafeHandle.cs
- SmiConnection.cs
- COMException.cs
- ObjectSecurity.cs
- ExpressionServices.cs
- ModuleElement.cs
- ObjectManager.cs
- XmlSchemaValidator.cs
- WebBrowserBase.cs
- ReadOnlyDictionary.cs
- ChannelHandler.cs
- CookieParameter.cs
- StylusCollection.cs
- SqlCacheDependency.cs
- PartitionedStream.cs
- RecognitionResult.cs