//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods /// <summary> /// Override of Object.Equals that returns true when the dependency /// property contained within each attribute is the same. /// </summary> public override bool Equals(object value) { DependencyPropertyAttribute da = value as DependencyPropertyAttribute; if (da != null && object.ReferenceEquals(da._dp, _dp) && da._isAttached == _isAttached) { return(true); } return(false); }
/// <summary> /// This method is called on demand when we need to get at one or /// more attributes for this property. Because obtaining attributes /// can be costly, we wait until now to do the job. /// </summary> private void MergeAttributes() { AttributeCollection baseAttributes; if (_property != null) { baseAttributes = _property.Attributes; } else { baseAttributes = GetAttachedPropertyAttributes(); } List <Attribute> newAttributes = new List <Attribute>(baseAttributes.Count + 1); bool readOnly = false; foreach (Attribute a in baseAttributes) { Attribute attrToAdd = a; DefaultValueAttribute defAttr = a as DefaultValueAttribute; if (defAttr != null) { // DP metadata always overrides CLR metadata for // default value. attrToAdd = null; } else { ReadOnlyAttribute roAttr = a as ReadOnlyAttribute; if (roAttr != null) { // DP metata is the merge of CLR metadata for // read only readOnly = roAttr.IsReadOnly; attrToAdd = null; } } if (attrToAdd != null) { newAttributes.Add(attrToAdd); } } // Always include the metadata choice readOnly |= _dp.ReadOnly; // If we are an attached property and non-read only, the lack of a // set method will make us read only. if (_property == null && !readOnly && GetAttachedPropertySetMethod(_dp) == null) { readOnly = true; } // Add our own DependencyPropertyAttribute DependencyPropertyAttribute dpa = new DependencyPropertyAttribute(_dp, (_property == null)); newAttributes.Add(dpa); // Add DefaultValueAttribute if the DP has a default // value if (_metadata.DefaultValue != DependencyProperty.UnsetValue) { newAttributes.Add(new DefaultValueAttribute(_metadata.DefaultValue)); } // And add a read only attribute if needed if (readOnly) { newAttributes.Add(new ReadOnlyAttribute(true)); } // Inject these attributes into our attribute array. There // is a quirk to the way this works. Attributes as they // are returned by the CLR and by AttributeCollection are in // priority order with the attributes at the front of the list // taking precidence over those at the end. Attributes // handed to MemberDescriptor's AttributeArray, however, are // in reverse priority order so the "last one in wins". Therefore // we need to reverse the array. Attribute[] attrArray = newAttributes.ToArray(); for (int idx = 0; idx < attrArray.Length / 2; idx++) { int swap = attrArray.Length - idx - 1; Attribute t = attrArray[idx]; attrArray[idx] = attrArray[swap]; attrArray[swap] = t; } AttributeArray = attrArray; }