/// <include file='doc\UserControlDesigner.uex' path='docs/doc[@for="ControlDesigner.OnComponentChanged"]/*' />
        /// <devdoc>
        ///    <para>
        ///       Delegate to handle component changed event.
        ///    </para>
        /// </devdoc>
        public virtual void OnComponentChanged(object sender, ComponentChangedEventArgs ce)
        {
            if (IsIgnoringComponentChanges)
            {
                return;
            }

            IComponent component = Component;

            Debug.Assert(ce.Component == component, "ControlDesigner::OnComponentChanged - Called from an unknown/invalid source object");

            if (DesignTimeElement == null)
            {
                return;
            }

            MemberDescriptor member = ce.Member;

            if (member != null)
            {
                // CONSIDER: Figure out a better and more correct way than looking for internal types...
                Type t = Type.GetType("System.ComponentModel.ReflectPropertyDescriptor, " + AssemblyRef.System);

                if ((member.GetType() != t) ||
                    (ce.NewValue != null && ce.NewValue == ce.OldValue))
                {
                    // HACK: ideally, we would prevent the property descriptor from firing this change.
                    // This would tear large holes in the WFC architecture. Instead, we do the
                    // filtering ourselves in this evil fashion.

                    Debug.WriteLineIf(CompModSwitches.UserControlDesigner.TraceInfo, "    ...ignoring property descriptor of type: " + member.GetType().Name);
                    return;
                }

                if (((PropertyDescriptor)member).SerializationVisibility != DesignerSerializationVisibility.Hidden)
                {
                    // Set the dirty state upon changing persistable properties.
                    this.IsDirty = true;

                    PersistenceModeAttribute persistenceType = (PersistenceModeAttribute)member.Attributes[typeof(PersistenceModeAttribute)];
                    PersistenceMode          mode            = persistenceType.Mode;

                    if ((mode == PersistenceMode.Attribute) ||
                        (mode == PersistenceMode.InnerDefaultProperty) ||
                        (mode == PersistenceMode.EncodedInnerDefaultProperty))
                    {
                        string propName = member.Name;

                        // Check to see whether the property that was changed is data bound.
                        // If it is we need to remove it...
                        // For this rev, we're only doing this for the properties on the Component itself
                        // as we can't distinguish which subproperty of a complex type changed.
                        if (IsPropertyBound(propName) && (ce.Component == Component))
                        {
                            DataBindings.Remove(propName, false);
                            Behavior.RemoveAttribute(propName, true);
                        }
                    }
                    if (mode == PersistenceMode.Attribute)
                    {
                        // For tag level properties ...

                        string propName = member.Name;

                        PersistProperties(propName, ce.Component, (PropertyDescriptor)member);
                        PersistAttribute((PropertyDescriptor)member, ce.Component, propName);
                    }
                }
            }
            else
            {
                // member is null, meaning that the whole component
                // could have changed and not just a single member.
                // This happens when a component is edited through a ComponentEditor.

                // Set the dirty state if more than one property is changed.
                this.IsDirty = true;

                PersistProperties(string.Empty, ce.Component, null);
                OnBindingsCollectionChanged(null);
            }

            // Update the WYSIWYG HTML.
            UpdateDesignTimeHtml();
        }