Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / WinForms / Managed / System / WinForms / PropertyGridInternal / MergePropertyDescriptor.cs / 1305376 / MergePropertyDescriptor.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms.PropertyGridInternal { using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; using System.ComponentModel; using System.Diagnostics; using System; using System.IO; using System.Collections; using System.Globalization; using System.Reflection; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Windows.Forms; using System.Drawing; using Microsoft.Win32; internal class MergePropertyDescriptor : PropertyDescriptor { private PropertyDescriptor[] descriptors; private enum TriState { Unknown, Yes, No } private TriState localizable = TriState.Unknown; private TriState readOnly = TriState.Unknown; private TriState canReset = TriState.Unknown; private MultiMergeCollection collection; public MergePropertyDescriptor(PropertyDescriptor[] descriptors) : base(descriptors[0].Name, null) { this.descriptors = descriptors; } ////// /// public override Type ComponentType { get { return descriptors[0].ComponentType; } } ////// When overridden in a derived class, gets the type of the /// component this property /// is bound to. /// ////// /// public override TypeConverter Converter { get { return descriptors[0].Converter; } } public override string DisplayName { get { return descriptors[0].DisplayName; } } ////// Gets the type converter for this property. /// ////// /// public override bool IsLocalizable { get { if (localizable == TriState.Unknown) { localizable = TriState.Yes; foreach (PropertyDescriptor pd in descriptors) { if (!pd.IsLocalizable) { localizable = TriState.No; break; } } } return (localizable == TriState.Yes); } } ////// Gets a value /// indicating whether this property should be localized, as /// specified in the ///. /// /// /// public override bool IsReadOnly { get { if (readOnly == TriState.Unknown) { readOnly = TriState.No; foreach (PropertyDescriptor pd in descriptors) { if (pd.IsReadOnly) { readOnly = TriState.Yes; break; } } } return (readOnly == TriState.Yes); } } ////// When overridden in /// a derived class, gets a value /// indicating whether this property is read-only. /// ////// /// public override Type PropertyType { get { return descriptors[0].PropertyType; } } public PropertyDescriptor this[int index] { get { return descriptors[index]; } } ////// When overridden in a derived class, /// gets the type of the property. /// ////// /// public override bool CanResetValue(object component) { Debug.Assert(component is Array, "MergePropertyDescriptor::CanResetValue called with non-array value"); if (canReset == TriState.Unknown) { canReset = TriState.Yes; Array a = (Array)component; for (int i = 0; i < descriptors.Length; i++) { if (!descriptors[i].CanResetValue(GetPropertyOwnerForComponent(a, i))) { canReset = TriState.No; break; } } } return (canReset == TriState.Yes); } ////// When overridden in a derived class, indicates whether /// resetting the ///will change the value of the /// . /// /// This method attempts to copy the given value so unique values are /// always passed to each object. If the object cannot be copied it /// will be returned. /// private object CopyValue(object value) { // null is always OK if (value == null) { return value; } Type type = value.GetType(); // value types are always copies if (type.IsValueType) { return value; } object clonedValue = null; // ICloneable is the next easiest thing ICloneable clone = value as ICloneable; if (clone != null) { clonedValue = clone.Clone(); } // Next, access the type converter if (clonedValue == null) { TypeConverter converter = TypeDescriptor.GetConverter(value); if (converter.CanConvertTo(typeof(InstanceDescriptor))) { // Instance descriptors provide full fidelity unless // they are marked as incomplete. InstanceDescriptor desc = (InstanceDescriptor)converter.ConvertTo(null, CultureInfo.InvariantCulture, value, typeof(InstanceDescriptor)); if (desc != null && desc.IsComplete) { clonedValue = desc.Invoke(); } } // If that didn't work, try conversion to/from string if (clonedValue == null && converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) { object stringRep = converter.ConvertToInvariantString(value); clonedValue = converter.ConvertFromInvariantString((string)stringRep); } } // How about serialization? if (clonedValue == null && type.IsSerializable) { BinaryFormatter f = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); f.Serialize(ms, value); ms.Position = 0; clonedValue = f.Deserialize(ms); } if (clonedValue != null) { return clonedValue; } // we failed. This object's reference will be set on each property. return value; } ////// /// protected override AttributeCollection CreateAttributeCollection() { return new MergedAttributeCollection(this); } private object GetPropertyOwnerForComponent(Array a, int i) { object propertyOwner = a.GetValue(i); if (propertyOwner is ICustomTypeDescriptor) { propertyOwner = ((ICustomTypeDescriptor) propertyOwner).GetPropertyOwner(descriptors[i]); } return propertyOwner; } ////// Creates a collection of attributes using the /// array of attributes that you passed to the constructor. /// ////// /// public override object GetEditor(Type editorBaseType) { return descriptors[0].GetEditor(editorBaseType); } ////// Gets an editor of the specified type. /// ////// /// public override object GetValue(object component) { Debug.Assert(component is Array, "MergePropertyDescriptor::GetValue called with non-array value"); bool temp; return GetValue((Array)component, out temp); } public object GetValue(Array components, out bool allEqual) { allEqual = true; object obj = descriptors[0].GetValue(GetPropertyOwnerForComponent(components, 0)); if (obj is ICollection) { if (collection == null) { collection = new MultiMergeCollection((ICollection)obj); } else if (collection.Locked) { return collection; } else { collection.SetItems((ICollection)obj); } } for (int i = 1; i < descriptors.Length; i++) { object objCur = descriptors[i].GetValue(GetPropertyOwnerForComponent(components, i)); if (collection != null) { if (!collection.MergeCollection((ICollection)objCur)){ allEqual = false; return null; } } else if ((obj == null && objCur == null) || (obj != null && obj.Equals(objCur))) { continue; } else { allEqual = false; return null; } } if (allEqual && collection != null && collection.Count == 0) { return null; } return (collection != null ? collection : obj); } internal object[] GetValues(Array components) { object[] values = new object[components.Length]; for (int i = 0; i < components.Length; i++) { values[i] = descriptors[i].GetValue(GetPropertyOwnerForComponent(components, i)); } return values; } ////// When overridden in a derived class, gets the current /// value /// of the /// property on a component. /// ////// /// public override void ResetValue(object component) { Debug.Assert(component is Array, "MergePropertyDescriptor::ResetValue called with non-array value"); Array a = (Array)component; for (int i = 0; i < descriptors.Length; i++) { descriptors[i].ResetValue(GetPropertyOwnerForComponent(a, i)); } } private void SetCollectionValues(Array a, IList listValue) { try { if (collection != null) { collection.Locked = true; } // now we have to copy the value into each property. object[] values = new object[listValue.Count]; listValue.CopyTo(values, 0); for (int i = 0; i < descriptors.Length; i++) { IList propList = descriptors[i].GetValue(GetPropertyOwnerForComponent(a, i)) as IList; if (propList == null) { continue; } propList.Clear(); foreach (object val in values) { propList.Add(val); } } } finally { if (collection != null) { collection.Locked = false; } } } ////// When overridden in a derived class, resets the /// value /// for this property /// of the component. /// ////// /// public override void SetValue(object component, object value) { Debug.Assert(component is Array, "MergePropertyDescriptor::SetValue called with non-array value"); Array a = (Array)component; if (value is IList && typeof(IList).IsAssignableFrom(PropertyType)) { SetCollectionValues(a, (IList)value); } else { for (int i = 0; i < descriptors.Length; i++) { object clonedValue = CopyValue(value); descriptors[i].SetValue(GetPropertyOwnerForComponent(a, i), clonedValue); } } } ////// When overridden in a derived class, sets the value of /// the component to a different value. /// ////// /// public override bool ShouldSerializeValue(object component) { Debug.Assert(component is Array, "MergePropertyDescriptor::ShouldSerializeValue called with non-array value"); Array a = (Array)component; for (int i = 0; i < descriptors.Length; i++) { if (!descriptors[i].ShouldSerializeValue(GetPropertyOwnerForComponent(a, i))) { return false; } } return true; } private class MultiMergeCollection : ICollection { private object[] items; private bool locked; public MultiMergeCollection(ICollection original) { SetItems(original); } ////// When overridden in a derived class, indicates whether the /// value of /// this property needs to be persisted. /// ////// /// Retrieves the number of items. /// public int Count { get { if (items != null) { return items.Length; } else { return 0; } } } ////// /// Prevents the contents of the collection from being re-initialized; /// public bool Locked { get { return locked; } set { this.locked = value; } } object ICollection.SyncRoot { get { return this; } } bool ICollection.IsSynchronized { get { return false; } } public void CopyTo(Array array, int index) { if (items == null) return; Array.Copy(items, 0, array, index, items.Length); } public IEnumerator GetEnumerator(){ if (items != null) { return items.GetEnumerator(); } else { return new object[0].GetEnumerator(); } } ////// /// Ensures that the new collection equals the exisitng one. /// Otherwise, it wipes out the contents of the new collection. /// public bool MergeCollection(ICollection newCollection) { if (locked) { return true; } if (items.Length != newCollection.Count) { items = new object[0]; return false; } object[] newItems = new object[newCollection.Count]; newCollection.CopyTo(newItems, 0); for (int i = 0;i < newItems.Length; i++) { if (((newItems[i] == null) != (items[i] == null)) || (items[i] != null && !items[i].Equals(newItems[i]))){ items = new object[0]; return false; } } return true; } public void SetItems(ICollection collection) { if (locked) { return; } items = new object[collection.Count]; collection.CopyTo(items, 0); } } private class MergedAttributeCollection : AttributeCollection { private MergePropertyDescriptor owner; private AttributeCollection[] attributeCollections = null; private IDictionary foundAttributes = null; public MergedAttributeCollection(MergePropertyDescriptor owner) : base((Attribute[])null) { this.owner = owner; } public override Attribute this[Type attributeType] { get { return GetCommonAttribute(attributeType); } } #if false private void FullMerge() { Attribute[][] collections = new Attribute[owner.descriptors.Length][]; for (int i = 0; i < owner.descriptors.Length; i++) { AttributeCollection attrCollection = owner.descriptors[i].Attributes; collections[i] = new Attribute[attrCollection.Count]; attrCollection.CopyTo(collections[i], 0); Array.Sort(collections[i], GridEntry.AttributeTypeSorter); } ArrayList mergedList = new ArrayList(); // merge the sorted lists -- note that lists aren't fully sorted just by // Attribute.TypeId // int[] posArray = new int[collections.Length]; for (int i = 0; i < collections[0].Length; i++) { Attribute pivotAttr = collections[0][i]; bool match = true; for (int j = 1; j < collections.Length; j++) { if (posArray[j] >= collections[j].Length) { match = false; break; } // check to see if we're on a match // if (pivotAttr.Equals(collections[j][posArray[j]])) { posArray[j] += 1; continue; } int jPos = posArray[j]; Attribute jAttr = collections[j][jPos]; match = false; // if we aren't on a match, check all the items until we're past // where the matching item would be while (GridEntry.AttributeTypeSorter.Compare(jAttr, pivotAttr) <= 0) { // got a match! if (pivotAttr.Equals(jAttr)) { posArray[j] = jPos + 1; match = true; break; } // try again jPos++; if (jPos < collections[j].Length) { jAttr = collections[j][jPos]; } else { break; } } // if we got here, there is no match, quit for this guy if (!match) { posArray[j] = jPos; break; } } // do we have a match? if (match) { mergedList.Add(pivotAttr); } } // create our merged array Attribute[] mergedAttrs = new Attribute[mergedList.Count]; mergedList.CopyTo(mergedAttrs, 0); } #endif private Attribute GetCommonAttribute(Type attributeType) { if (attributeCollections == null) { attributeCollections = new AttributeCollection[owner.descriptors.Length]; for (int i = 0; i < owner.descriptors.Length; i++) { attributeCollections[i] = owner.descriptors[i].Attributes; } } if (attributeCollections.Length == 0) { return GetDefaultAttribute(attributeType); } Attribute value; if (foundAttributes != null) { value = foundAttributes[attributeType] as Attribute; if (value != null) { return value; } } value = attributeCollections[0][attributeType]; if (value == null) { return null; } for (int i = 1; i < attributeCollections.Length; i++) { Attribute newValue = attributeCollections[i][attributeType]; if (!value.Equals(newValue)) { value = GetDefaultAttribute(attributeType); break; } } if (foundAttributes == null) { foundAttributes = new Hashtable(); } foundAttributes[attributeType] = value; return value; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MenuAutomationPeer.cs
- InProcStateClientManager.cs
- MinMaxParagraphWidth.cs
- HTMLTextWriter.cs
- LineUtil.cs
- ScaleTransform.cs
- XPathNodeInfoAtom.cs
- GridViewRowPresenter.cs
- MsdtcWrapper.cs
- Scheduling.cs
- CodePageUtils.cs
- EndpointAddressProcessor.cs
- SmtpMail.cs
- DataServiceProcessingPipelineEventArgs.cs
- ObjectDisposedException.cs
- ColorTransformHelper.cs
- DataPagerField.cs
- BrowserInteropHelper.cs
- RootBuilder.cs
- Application.cs
- SQLGuidStorage.cs
- QilFunction.cs
- FormatterServices.cs
- ApplicationCommands.cs
- XmlElement.cs
- DefaultSerializationProviderAttribute.cs
- MgmtConfigurationRecord.cs
- ClientRolePrincipal.cs
- TdsParserSessionPool.cs
- ArrangedElement.cs
- UriWriter.cs
- AccessDataSourceView.cs
- ErrorsHelper.cs
- LineSegment.cs
- WebPartManagerInternals.cs
- FormClosingEvent.cs
- _ContextAwareResult.cs
- ControlUtil.cs
- TextBoxBase.cs
- TableLayoutPanel.cs
- GcSettings.cs
- RepeatButton.cs
- ApplicationHost.cs
- HttpConfigurationContext.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- EntryPointNotFoundException.cs
- SizeValueSerializer.cs
- DockAndAnchorLayout.cs
- CookieParameter.cs
- EntityDataSourceChangingEventArgs.cs
- CodeGroup.cs
- ParameterModifier.cs
- TypefaceMap.cs
- xmlglyphRunInfo.cs
- XmlHelper.cs
- NavigationProperty.cs
- HistoryEventArgs.cs
- ProfileModule.cs
- BaseTreeIterator.cs
- BrowsableAttribute.cs
- ResourcePermissionBase.cs
- OrderedDictionaryStateHelper.cs
- OracleConnectionFactory.cs
- DataGridColumn.cs
- ClientTargetSection.cs
- ObjectKeyFrameCollection.cs
- BrowserCapabilitiesCodeGenerator.cs
- UpnEndpointIdentityExtension.cs
- CacheDependency.cs
- SynchronizedRandom.cs
- Rule.cs
- SocketStream.cs
- AccessibilityHelperForVista.cs
- IResourceProvider.cs
- unitconverter.cs
- ModelItemCollection.cs
- XhtmlBasicFormAdapter.cs
- ReadOnlyState.cs
- HideDisabledControlAdapter.cs
- GestureRecognizer.cs
- SoapCodeExporter.cs
- WebPartZoneBase.cs
- Separator.cs
- XmlnsCompatibleWithAttribute.cs
- QilPatternVisitor.cs
- TypeNameParser.cs
- SrgsElementFactory.cs
- ReflectionPermission.cs
- OneOfConst.cs
- SqlDataSourceFilteringEventArgs.cs
- SQLByteStorage.cs
- SatelliteContractVersionAttribute.cs
- EdgeModeValidation.cs
- MonthCalendar.cs
- WpfKnownTypeInvoker.cs
- X509ChainElement.cs
- OraclePermissionAttribute.cs
- AttachedPropertyBrowsableAttribute.cs
- CalendarDateRangeChangingEventArgs.cs
- XmlAttributeAttribute.cs