1 //-----------------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 //-----------------------------------------------------------------------------
5 namespace System.Activities.Presentation.Model
7 using System.ComponentModel;
8 using System.Diagnostics;
9 using System.Globalization;
12 /// FakeModelPropertyImpl. This class is used with FakeModelItemImpl. it is used to allow full model editing expirience
13 /// without actually modyfing actual model tree. Even though reference to ModelTreeManager is availabe, changes made to object
14 /// using this class are not reflected in actual model. Especially, any changes made here do not affect undo/redo stack.
15 /// see aslo DesignObjectWrapper class for more usage details
17 sealed class FakeModelPropertyImpl : ModelPropertyImpl
19 IModelTreeItem parentModelTreeItem;
20 FakeModelItemImpl temporaryValue;
21 bool isSettingValue = false;
23 public FakeModelPropertyImpl(FakeModelItemImpl parent, PropertyDescriptor propertyDescriptor)
24 : base(parent, propertyDescriptor, false)
26 this.parentModelTreeItem = (IModelTreeItem)parent;
29 //no collection support
30 public override ModelItemCollection Collection
35 public override bool IsCollection
40 //no dictionary support
41 public override ModelItemDictionary Dictionary
46 public override bool IsDictionary
51 public override ModelItem Value
55 ModelItem result = null;
56 object parentObject = this.parentModelTreeItem.ModelItem.GetCurrentValue();
57 result = this.StoreValue(this.PropertyDescriptor.GetValue(parentObject));
62 public override void ClearValue()
64 //try setting default value
65 this.SetValue(this.DefaultValue);
68 public override ModelItem SetValue(object value)
70 //are we already setting value?
75 this.isSettingValue = true;
77 this.temporaryValue = this.WrapValue(value);
78 //is there a value stored already?
79 if (this.parentModelTreeItem.ModelPropertyStore.ContainsKey(this.Name))
81 //yes - cleanup references
82 IModelTreeItem item = (IModelTreeItem)this.parentModelTreeItem.ModelPropertyStore[this.Name];
83 item.RemoveSource(this);
84 item.RemoveParent(this.parentModelTreeItem.ModelItem);
86 this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
88 //set it onto underlying object
89 this.PropertyDescriptor.SetValue(this.Parent.GetCurrentValue(), (null != this.temporaryValue ? this.temporaryValue.GetCurrentValue() : null));
90 //store it in parent's store
91 this.temporaryValue = this.StoreValue(this.temporaryValue);
93 //notify listeners - notification must be postponed until actual underlying object value is updated, otherwise, listeners might get old value
94 this.parentModelTreeItem.ModelTreeManager.AddToCurrentEditingScope(new FakeModelNotifyPropertyChange(this.parentModelTreeItem, this.Name));
96 catch (ValidationException e)
98 Trace.WriteLine(e.ToString());
99 //it is important to rethrow exception here - otherwise, DataGrid will assume operation completed successfully
104 this.isSettingValue = false;
108 return this.temporaryValue;
111 FakeModelItemImpl WrapValue(object value)
113 FakeModelItemImpl wrappedValue = value as FakeModelItemImpl;
114 if (null == wrappedValue && null != value)
116 wrappedValue = new FakeModelItemImpl(this.parentModelTreeItem.ModelTreeManager, this.PropertyType, value, (FakeModelItemImpl)this.Parent);
121 FakeModelItemImpl StoreValue(object value)
123 FakeModelItemImpl wrappedValue = WrapValue(value);
124 if (null != wrappedValue)
126 this.parentModelTreeItem.ModelPropertyStore[this.Name] = wrappedValue;
127 IModelTreeItem modelTreeItem = (IModelTreeItem)wrappedValue;
128 modelTreeItem.SetSource(this);
132 ModelItem existing = null;
133 if (this.parentModelTreeItem.ModelPropertyStore.TryGetValue(this.Name, out existing))
135 IModelTreeItem modelTreeItem = (IModelTreeItem)existing;
136 modelTreeItem.RemoveSource(this);
137 modelTreeItem.RemoveParent(this.Parent);
139 this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
145 //helper class - implements change
146 //FakeModelPropery uses instance of this class to notify all listeners that property value has changed. the notification is deffered untill all editing operations
147 //have completed, so the listener will get notified after edit is completed
148 sealed class FakeModelNotifyPropertyChange : ModelChange
150 IModelTreeItem modelTreeItem;
153 public FakeModelNotifyPropertyChange(IModelTreeItem modelTreeItem, string propertyName)
155 this.modelTreeItem = modelTreeItem;
156 this.propertyName = propertyName;
159 public override string Description
161 get { return this.GetType().Name; }
164 public override bool Apply()
166 if (this.modelTreeItem != null)
168 EditingContext context = this.modelTreeItem.ModelTreeManager.Context;
169 //this change shouldn't participate in Undo/Redo
170 if (null != context && !context.Services.GetService<UndoEngine>().IsUndoRedoInProgress)
172 this.modelTreeItem.OnPropertyChanged(this.propertyName);
175 //return false here - i don't need that change in the change list
179 public override Change GetInverse()
181 //this change shouldn't participate in Undo/Redo