예제 #1
0
        // Intercept GetValue calls for certain ADO properties
        internal override object GetValue(object item, PropertyDescriptor pd, bool useFollowParent)
        {
            object value = GetRawValue(item, pd, useFollowParent);

            if (IsDataSetCollectionProperty(pd))
            {
                // ADO returns a newly-created object (of type DataView or RelatedView)
                // for each call to the getter of a "DataSet collection property".
                // These objects are not referenced by any other ADO objects,
                // so it is up to the caller to keep them alive.  But WPF tries
                // hard not to add strong references to these objects.  There
                // are only three ways:
                //  1. Creating a BindingListCollectionView over the object
                //  2. Adding a ValueChanged listener for one of the object's properties
                //  3. Caching the object in the ValueTable
                //
                // Actually (3) no longer happens at all - it was causing a memory
                // leak of the entire DataSet.
                //
                // If the app never uses (1) or (2), there's nothing to keep the
                // object alive.  There is a case where this actually
                // happens - the app uses bindings with indexers on the object, but
                // doesn't use any collection views or PropertyDescriptor-backed
                // properties.   After a while, the object is GC'd, and the app
                // silently stops working.
                //
                // To fix this, we add a reference from a suitable ADO object to
                // the new DataView/RelatedView.  This reference can't involve
                // any WPF objects - that would bring back the memory leak.
                // Instead, we use an ephemeral object created just for this purpose.
                // The ephemeral object subscribes to an event on the "suitable
                // ADO object", intentionally *not* using the WeakEvent pattern
                // so that the ADO object refers to the ephemeral object via the handler.
                // The ephemeral object also holds a strong reference to the new
                // DataView/RelatedView.  Together, these references tie the
                // lifetime of the DataView/RelatedView to the lifetime of the
                // ADO object, as desired.

                if (pd.GetType() == s_DataTablePropertyDescriptorType)
                {
                    // the "suitable ADO object" is the corresponding DataTable
                    DataTable dataTable = (value as DataView)?.Table;
                    if (dataTable != null)
                    {
                        new DataTableToDataViewLink(dataTable, value);
                    }
                }
                else if (pd.GetType() == s_DataRelationPropertyDescriptorType)
                {
                    // the "suitable ADO object" is the parent DataRowView
                    DataRowView dataRowView = item as DataRowView;
                    if (dataRowView != null)
                    {
                        new DataRowViewToRelatedViewLink(dataRowView, value);
                    }
                }
            }

            return(value);
        }
예제 #2
0
        private void contextMenuStripPropertyGrid_Opening(object sender, CancelEventArgs e)
        {
            GridItem gridItem = propertyGrid.SelectedGridItem;

            bool canReset = false;

            if (gridItem != null && gridItem.PropertyDescriptor != null)
            {
                PropertyDescriptor descriptor = gridItem.PropertyDescriptor;

                try
                {
                    if (descriptor.GetType().Name == "MergePropertyDescriptor")
                    {
                        //hack for multiselection.
                        FieldInfo field = descriptor.GetType().GetField(
                            "descriptors", BindingFlags.Instance | BindingFlags.NonPublic);
                        PropertyDescriptor[] childDescriptors = (PropertyDescriptor[])field.GetValue(descriptor);

                        for (int n = 0; n < childDescriptors.Length; n++)
                        {
                            PropertyDescriptor childDescriptor = childDescriptors[n];

                            if (childDescriptor.CanResetValue(propertyGrid.SelectedObjects[n]))
                            {
                                canReset = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        object component = null;

                        GridItem parent = gridItem.Parent;

                        if (parent.GridItemType == GridItemType.Category || parent.GridItemType == GridItemType.Root)
                        {
                            component = propertyGrid.SelectedObject;
                        }
                        else if (parent.GridItemType == GridItemType.Property)
                        {
                            component = parent.Value;
                        }

                        if (descriptor.CanResetValue(component))
                        {
                            canReset = true;
                        }
                    }
                }
                catch
                {
                    canReset = true;
                }
            }

            contextMenuStripPropertyGrid.Items[0].Enabled = canReset;
        }
예제 #3
0
        private void contextMenuStripPropertyGrid_Opening(object sender, CancelEventArgs e)
        {
            GridItem selectedGridItem = this.jxPropertyGrid.SelectedGridItem;
            bool     enabled          = false;

            if (selectedGridItem != null && selectedGridItem.PropertyDescriptor != null)
            {
                PropertyDescriptor propertyDescriptor = selectedGridItem.PropertyDescriptor;
                try
                {
                    if (propertyDescriptor.GetType().Name == "MergePropertyDescriptor")
                    {
                        FieldInfo            field = propertyDescriptor.GetType().GetField("descriptors", BindingFlags.Instance | BindingFlags.NonPublic);
                        PropertyDescriptor[] array = (PropertyDescriptor[])field.GetValue(propertyDescriptor);
                        for (int i = 0; i < array.Length; i++)
                        {
                            PropertyDescriptor propertyDescriptor2 = array[i];
                            if (propertyDescriptor2.CanResetValue(this.jxPropertyGrid.SelectedObjects[i]))
                            {
                                enabled = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        object   component = null;
                        GridItem parent    = selectedGridItem.Parent;
                        if (parent.GridItemType == GridItemType.Category || parent.GridItemType == GridItemType.Root)
                        {
                            component = this.jxPropertyGrid.SelectedObject;
                        }
                        else if (parent.GridItemType == GridItemType.Property)
                        {
                            component = parent.Value;
                        }
                        if (propertyDescriptor.CanResetValue(component))
                        {
                            enabled = true;
                        }
                    }
                }
                catch
                {
                    enabled = true;
                }
            }
            this.contextMenuStripPropertyGrid.Items[0].Enabled = enabled;
            while (this.contextMenuStripPropertyGrid.Items.Count > 1)
            {
                this.contextMenuStripPropertyGrid.Items.RemoveAt(this.contextMenuStripPropertyGrid.Items.Count - 1);
            }
            if (this.ContextMenuOpening != null)
            {
                this.ContextMenuOpening(this.contextMenuStripPropertyGrid);
            }
        }
예제 #4
0
        static public string IdentifyAccessor(object accessor)
        {
            DependencyProperty dp = accessor as DependencyProperty;

            if (dp != null)
            {
                return(Format("{0}({1})", dp.GetType().Name, dp.Name));
            }

            PropertyInfo pi = accessor as PropertyInfo;;

            if (pi != null)
            {
                return(Format("{0}({1})", pi.GetType().Name, pi.Name));
            }

            PropertyDescriptor pd = accessor as PropertyDescriptor;;

            if (pd != null)
            {
                return(Format("{0}({1})", pd.GetType().Name, pd.Name));
            }

            return(Identify(accessor));
        }
예제 #5
0
        private object GetRawValue(object item, PropertyDescriptor pd, bool useFollowParent)
        {
            if (useFollowParent && pd.GetType() == s_DataRelationPropertyDescriptorType)
            {
                // the DataRelation property returns a child view that doesn't
                // work in master/detail scenarios, when the primary key linking
                // the two tables changes.
                // ADO added a new method that returns a better child view, specifically
                // to fix this bug, but System.Data.DataRelationPropertyDescriptor.GetValue
                // still uses the old method:
                //
                // public override object GetValue(object component) {
                //     DataRowView dataRowView = (DataRowView) component;
                //     return dataRowView.CreateChildView(relation);
                // }
                //
                // so we intercept the GetValue call and use the new method.
                // (The value of the 'relation' member isn't publicly visible,
                // but its name is.  That's enough to call the new method.)
                DataRowView dataRowView = (DataRowView)item;
                return(dataRowView.CreateChildView(pd.Name, followParent: true));
            }

            // otherwise, call GetValue the normal way
            return(pd.GetValue(item));
        }
        protected void SerializeProperty(IDesignerSerializationManager manager, CodeStatementCollection statements, object value, PropertyDescriptor propertyToSerialize)
        {
            if (propertyToSerialize == null)
            {
                throw new ArgumentNullException("propertyToSerialize");
            }
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
            if (statements == null)
            {
                throw new ArgumentNullException("statements");
            }
            if (manager == null)
            {
                throw new ArgumentNullException("manager");
            }

            MemberCodeDomSerializer serializer = manager.GetSerializer(propertyToSerialize.GetType(), typeof(MemberCodeDomSerializer)) as MemberCodeDomSerializer;

            if (serializer != null && serializer.ShouldSerialize(manager, value, propertyToSerialize))
            {
                serializer.Serialize(manager, value, propertyToSerialize, statements);
            }
        }
예제 #7
0
        // XLinq exposes several properties on XElement that create new objects
        // every time the getter is called.  We have to live with this, since
        // the property descriptors carry state that depends on components later
        // in the path (e.g. when path=Attribute[FirstName], the value returned by
        // the Attribute PD can only be used to look up "FirstName").  But we need
        // to be aware of it in certain circumstances - e.g. when checking for
        // event leapfrogging.
        internal override bool IsXLinqNonIdempotentProperty(PropertyDescriptor pd)
        {
            Type pdType = pd.GetType();

            return((pdType == s_XElementAttributePropertyDescriptorType) ||
                   (pdType == s_XElementElementPropertyDescriptorType));
        }
예제 #8
0
        // XLinq exposes two synthetic properties - Elements and Descendants -
        // on XElement that return IEnumerable<XElement>.  We handle these specially
        // to work around problems involving identity and change notifications
        internal override bool IsXLinqCollectionProperty(PropertyDescriptor pd)
        {
            Type pdType = pd.GetType();

            return((pdType == s_XElementElementsPropertyDescriptorType) ||
                   (pdType == s_XElementDescendantsPropertyDescriptorType));
        }
예제 #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        public static string GetFieldName(PropertyDescriptor property)
        {
            DbFieldAttribute attribute =
                property.Attributes[_TypeOf_Field] as DbFieldAttribute;

            if (attribute != null)
            {
                return(attribute.FieldName);
            }
            throw FieldNotExists(string.Format("for property: {0}", property.Name), property.GetType());
        }
예제 #10
0
 /// <summary>
 /// Returns the PropertyDescriptorCollection for the relation or nested collection.
 /// </summary>
 /// <param name="pd"></param>
 /// <returns></returns>
 public static DataRelation GetDataRelation(PropertyDescriptor pd)
 {
     if (!BrowserInteropHelper.IsBrowserHosted)
     {
         if (pd != null && pd.GetType().FullName == "System.Data.DataRelationPropertyDescriptor")
         {
             var t  = pd.GetType();
             var pi = t.GetProperty("Relation", BindingFlags.GetProperty
                                    | BindingFlags.Public | BindingFlags.IgnoreReturn
                                    | BindingFlags.Instance | BindingFlags.NonPublic);
             if (pi != null)
             {
                 var mInfo = pi.GetGetMethod(true);
                 if (mInfo != null)
                 {
                     var dr = mInfo.Invoke(pd, new object[0]) as DataRelation;
                     return(dr);
                 }
             }
         }
     }
     return(null);
 }
예제 #11
0
 public static string GetCaption(PropertyDescriptor descriptor)
 {
     try
     {
         PropertyInfo property = descriptor.GetType().GetProperty("Column", BindingFlags.Instance | BindingFlags.NonPublic);
         if ((object)property == null)
         {
             return((string)null);
         }
         return((property.GetValue((object)descriptor, (object[])null) as DataColumn).Caption);
     }
     catch
     {
         return((string)null);
     }
 }
예제 #12
0
        private static PropertyDescriptorCollection WrapProperties(PropertyDescriptorCollection oldProps)
        {
            PropertyDescriptor[] newProps = new PropertyDescriptor[oldProps.Count];
            int  index   = 0;
            bool changed = false;
            // HACK: how to identify reflection, given that the class is internal...
            Type wrapMe = Assembly.GetAssembly(typeof(PropertyDescriptor)).GetType("System.ComponentModel.ReflectPropertyDescriptor");

            foreach (PropertyDescriptor oldProp in oldProps)
            {
                PropertyDescriptor pd = oldProp;
                // if it looks like reflection, try to create a bespoke descriptor
                if (ReferenceEquals(wrapMe, pd.GetType()) && TryCreatePropertyDescriptor(ref pd))
                {
                    changed = true;
                }
                newProps[index++] = pd;
            }

            return(changed ? new PropertyDescriptorCollection(newProps, true) : oldProps);
        }
예제 #13
0
        // ADO DataSet exposes some properties that cause problems involving
        // identity and change notifications.  We handle these specially.
        internal override bool IsDataSetCollectionProperty(PropertyDescriptor pd)
        {
            if (s_DataTablePropertyDescriptorType == null)
            {
                // lazy load the types for the offending PD's.  They're internal, so
                // we get them indirectly.
                DataSet dataset = new DataSet();
                dataset.Locale = System.Globalization.CultureInfo.InvariantCulture;

                DataTable table1 = new DataTable("Table1");
                table1.Locale = System.Globalization.CultureInfo.InvariantCulture;
                table1.Columns.Add("ID", typeof(int));
                dataset.Tables.Add(table1);

                DataTable table2 = new DataTable("Table2");
                table2.Locale = System.Globalization.CultureInfo.InvariantCulture;
                table2.Columns.Add("ID", typeof(int));
                dataset.Tables.Add(table2);

                dataset.Relations.Add(new DataRelation("IDRelation",
                                                       table1.Columns["ID"],
                                                       table2.Columns["ID"]));

                System.Collections.IList     list = ((IListSource)dataset).GetList();
                PropertyDescriptorCollection pdc  = TypeDescriptor.GetProperties(list[0]);
                s_DataTablePropertyDescriptorType = pdc["Table1"].GetType();

                pdc = ((ITypedList)table1.DefaultView).GetItemProperties(null);
                s_DataRelationPropertyDescriptorType = pdc["IDRelation"].GetType();
            }

            Type pdType = pd.GetType();

            return((pdType == s_DataTablePropertyDescriptorType) ||
                   (pdType == s_DataRelationPropertyDescriptorType));
        }
예제 #14
0
 private static PropertyInfo GetPropertyInfo(PropertyDescriptor prop, string name)
 => prop.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.NonPublic);
 private static bool IsReflected(PropertyDescriptor descriptor)
 {
     return((descriptor != null) &&
            (descriptor.GetType() == s_reflectPropertyDescriptorType));
 }