//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------- namespace System.Activities.Presentation { using System.Activities.Presentation.Model; using System.Activities.Presentation.View; using System.Collections.Generic; using System.Runtime; abstract class ViewStateAttachedPropertyFeature : Feature { Type modelType; ViewStateService viewStateService; AttachedPropertiesService attachedPropertiesService; Dictionary attachedProperties = new Dictionary(); public sealed override void Initialize(EditingContext context, Type modelType) { this.modelType = modelType; context.Services.Subscribe(delegate(ViewStateService viewStateService) { this.viewStateService = viewStateService; viewStateService.ViewStateChanged += this.OnViewStateChanged; if (this.attachedPropertiesService != null) { RegisterAttachedProperties(); } }); context.Services.Subscribe(delegate(AttachedPropertiesService attachedPropertiesService) { this.attachedPropertiesService = attachedPropertiesService; if (this.viewStateService != null) { RegisterAttachedProperties(); } }); } protected abstract IEnumerable AttachedProperties { get; } internal void RegisterAttachedProperty(string propertyName, bool isBrowsable, bool isVisibleToModelItem, T defaultValue) { AttachedProperty attachedProperty = new AttachedProperty { IsBrowsable = isBrowsable, IsVisibleToModelItem = isVisibleToModelItem, Name = propertyName, OwnerType = modelType, Getter = (modelItem) => { T result = (T)viewStateService.RetrieveViewState(modelItem, propertyName); return result == null ? defaultValue : result; }, Setter = (modelItem, value) => { if (value == null || value.Equals(defaultValue)) { viewStateService.StoreViewStateWithUndo(modelItem, propertyName, null); } else { viewStateService.StoreViewStateWithUndo(modelItem, propertyName, value); } } }; attachedPropertiesService.AddProperty(attachedProperty); attachedProperties.Add(propertyName, attachedProperty); } void OnViewStateChanged(object sender, ViewStateChangedEventArgs e) { if (attachedProperties.ContainsKey(e.Key)) { // Checking is required to avoid infinite loop of ViewState -> AttachedProperty -> ... if ((e.NewValue == null && e.OldValue != null) || !e.NewValue.Equals(e.OldValue)) { attachedProperties[e.Key].SetValue(e.ParentModelItem, e.NewValue); } } } void RegisterAttachedProperties() { foreach (AttachedPropertyInfo attachedPropertyInfo in this.AttachedProperties) { attachedPropertyInfo.Register(this); } } } }