protected override void OnPropertyChanged(string propertyName)
        {
            IModelTreeItem modelTreeItem = (IModelTreeItem)this;
            ModelItem      currentValue;

            //if property value has changed - remove existing value, so the ModelPropertyImplementation will
            //force reading the value from the underlying object
            if (modelTreeItem.ModelPropertyStore.TryGetValue(propertyName, out currentValue))
            {
                IModelTreeItem valueAsTreeItem = (IModelTreeItem)currentValue;
                //cleanup references
                valueAsTreeItem.RemoveParent(this);
                valueAsTreeItem.RemoveSource(this.Properties[propertyName]);
                //remove from store
                modelTreeItem.ModelPropertyStore.Remove(propertyName);
            }
            base.OnPropertyChanged(propertyName);
        }
        public override ModelItem SetValue(object value)
        {
            //are we already setting value?
            if (!isSettingValue)
            {
                try
                {
                    this.isSettingValue = true;
                    //create new value
                    this.temporaryValue = this.WrapValue(value);
                    //is there a value stored already?
                    if (this.parentModelTreeItem.ModelPropertyStore.ContainsKey(this.Name))
                    {
                        //yes - cleanup references
                        IModelTreeItem item = (IModelTreeItem)this.parentModelTreeItem.ModelPropertyStore[this.Name];
                        item.RemoveSource(this);
                        item.RemoveParent(this.parentModelTreeItem.ModelItem);
                        //and remove it
                        this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
                    }
                    //set it onto underlying object
                    this.PropertyDescriptor.SetValue(this.Parent.GetCurrentValue(), (null != this.temporaryValue ? this.temporaryValue.GetCurrentValue() : null));
                    //store it in parent's store
                    this.temporaryValue = this.StoreValue(this.temporaryValue);

                    //notify listeners - notification must be postponed until actual underlying object value is updated, otherwise, listeners might get old value
                    this.parentModelTreeItem.ModelTreeManager.AddToCurrentEditingScope(new FakeModelNotifyPropertyChange(this.parentModelTreeItem, this.Name));
                }
                catch (ValidationException e)
                {
                    Trace.WriteLine(e.ToString());
                    //it is important to rethrow exception here - otherwise, DataGrid will assume operation completed successfully
                    throw;
                }
                finally
                {
                    this.isSettingValue = false;
                }
            }

            return(this.temporaryValue);
        }
        FakeModelItemImpl StoreValue(object value)
        {
            FakeModelItemImpl wrappedValue = WrapValue(value);

            if (null != wrappedValue)
            {
                this.parentModelTreeItem.ModelPropertyStore[this.Name] = wrappedValue;
                IModelTreeItem modelTreeItem = (IModelTreeItem)wrappedValue;
                modelTreeItem.SetSource(this);
            }
            else
            {
                ModelItem existing = null;
                if (this.parentModelTreeItem.ModelPropertyStore.TryGetValue(this.Name, out existing))
                {
                    IModelTreeItem modelTreeItem = (IModelTreeItem)existing;
                    modelTreeItem.RemoveSource(this);
                    modelTreeItem.RemoveParent(this.Parent);
                }
                this.parentModelTreeItem.ModelPropertyStore.Remove(this.Name);
            }
            return(wrappedValue);
        }