Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / ComponentModel / APCustomTypeDescriptor.cs / 1305600 / APCustomTypeDescriptor.cs
namespace MS.Internal.ComponentModel
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Windows;
using System.Windows.Markup;
using System.Text;
///
/// This class is a custom type descriptor for attached dependency properties. We
/// could just inherit from the CustomTypeDescriptor class, which does most of the forwarding
/// work for us, but these are allocated a lot so we want them to be structs.
///
struct APCustomTypeDescriptor : ICustomTypeDescriptor {
//------------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Creates a new APCustomTypeDescriptor. We pass in the custom type descriptor of
/// our base provider, which provides is with a default implementation of everything
/// we don't override. for us, we want to override only the property mechanism.
///
internal APCustomTypeDescriptor(ICustomTypeDescriptor parent, object instance)
{
_parent = parent;
_instance = FromObj(instance);
}
#endregion Constructors
//-----------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// Returns a collection of properties for our object. We first rely on base
/// CLR properties and then we attempt to match these with dependency properties.
///
public PropertyDescriptorCollection GetProperties()
{
return GetProperties(null);
}
///
/// Returns a collection of properties for our object. We first rely on base
/// CLR properties and then we attempt to match these with dependency properties.
///
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
// Because attached properties can come and go at any time,
// the set of properties we have here always needs to be rebuilt.
// We have two code paths here based on filtered attributes. An attribute
// filter is just a notificaiton of a filter, it doesn't actually perform
// the filter. Because the default PropertyFilterAttribute is PropertyFilter.All,
// it acts as a nice "don't care" in later filtering stages that TypeDescriptor
// may apply. That means that regardless of the filter value, we don't have
// to fiddle with adding the attribute to the property descriptor.
PropertyFilterOptions filter = PropertyFilterOptions.Valid | PropertyFilterOptions.SetValues;
if (attributes != null)
{
foreach (Attribute attr in attributes)
{
PropertyFilterAttribute filterAttr = attr as PropertyFilterAttribute;
if (filterAttr != null)
{
filter = filterAttr.Filter;
break;
}
}
}
if (filter == PropertyFilterOptions.None)
{
return PropertyDescriptorCollection.Empty;
}
// First, get the set of all known registered properties in the
// app domain. GetRegisteredProperties caches its results and
// will automatically re-fetch if new properties have been
// registered
DependencyProperty[] registeredProperties = GetRegisteredProperties();
Type instanceType = _instance.GetType();
// Next, walk through them and see which ones can be attached to this
// object. If our filter is specifically SetValues, we can
// greatly shortcut the entire process by using the local value
// enumerator.
List filteredProps;
if (filter == PropertyFilterOptions.SetValues)
{
LocalValueEnumerator localEnum = _instance.GetLocalValueEnumerator();
filteredProps = new List(localEnum.Count);
while(localEnum.MoveNext())
{
DependencyProperty dp = localEnum.Current.Property;
DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);
// For locally set values, we just want to exclude direct and internal properties.
if (!kind.IsDirect && !kind.IsInternal)
{
DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
filteredProps.Add(dpProp);
}
}
}
else
{
filteredProps = new List(registeredProperties.Length);
foreach (DependencyProperty dp in registeredProperties)
{
bool addProp = false;
DependencyPropertyKind kind = DependencyObjectProvider.GetDependencyPropertyKind(dp, instanceType);
if (kind.IsAttached)
{
// Check bit combinations that would yield true in
// any case. For non-attached properties, they're all valid, so if
// the valid bit is set, we're done.
PropertyFilterOptions anySet = PropertyFilterOptions.SetValues | PropertyFilterOptions.UnsetValues;
PropertyFilterOptions anyValid = PropertyFilterOptions.Valid | PropertyFilterOptions.Invalid;
if ((filter & anySet) == anySet || (filter & anyValid) == anyValid)
{
addProp = true;
}
if (!addProp && (filter & anyValid) != 0)
{
bool canAttach = CanAttachProperty(dp, _instance);
addProp = canAttach ^ ((filter & anyValid) == PropertyFilterOptions.Invalid);
}
if (!addProp && (filter & anySet) != 0)
{
bool shouldSerialize = _instance.ContainsValue(dp);
addProp = shouldSerialize ^ ((filter & anySet) == PropertyFilterOptions.UnsetValues);
}
}
else if ((filter & PropertyFilterOptions.SetValues) != 0 && _instance.ContainsValue(dp) && !kind.IsDirect && !kind.IsInternal)
{
// The property is not attached. However, it isn't an internal DP and the user
// has requested set values. See if the property is set on the object and include
// it if it is.
addProp = true;
}
if (addProp)
{
DependencyObjectPropertyDescriptor dpProp = DependencyObjectProvider.GetAttachedPropertyDescriptor(dp, instanceType);
filteredProps.Add(dpProp);
}
}
}
PropertyDescriptorCollection properties;
properties = new PropertyDescriptorCollection(filteredProps.ToArray(), true);
return properties;
}
//
// All methods below simply forward to the parent descriptor.
//
public AttributeCollection GetAttributes() { return _parent.GetAttributes(); }
public string GetClassName() { return _parent.GetClassName(); }
public string GetComponentName() { return _parent.GetComponentName(); }
public TypeConverter GetConverter()
{
// We only support public type converters, in order to avoid asserts.
TypeConverter typeConverter = _parent.GetConverter();
if( typeConverter.GetType().IsPublic )
{
return typeConverter;
}
else
{
return null;
}
}
public EventDescriptor GetDefaultEvent() { return _parent.GetDefaultEvent(); }
public PropertyDescriptor GetDefaultProperty() { return _parent.GetDefaultProperty(); }
public object GetEditor(Type editorBaseType) { return _parent.GetEditor(editorBaseType); }
public EventDescriptorCollection GetEvents() { return _parent.GetEvents(); }
public EventDescriptorCollection GetEvents(Attribute[] attributes) { return _parent.GetEvents(attributes); }
public object GetPropertyOwner(PropertyDescriptor property) { return _parent.GetPropertyOwner(property); }
#endregion Public Methods
//------------------------------------------------------
//
// Private Methods
//
//-----------------------------------------------------
#region Private Methods
///
/// This method determines if the given property can be attached
/// to the given instance.
///
private bool CanAttachProperty(DependencyProperty dp, DependencyObject instance)
{
AttachInfo info = DependencyObjectProvider.GetAttachInfo(dp);
return info.CanAttach(instance);
}
///
/// Returns a dependency object for the given value.
///
private static DependencyObject FromObj(object value)
{
// This indirection is necessary to support
// the "association" feature of type descriptor. This feature
// alows one object to mimic the API of another.
return (DependencyObject)TypeDescriptor.GetAssociation(typeof(DependencyObject), value);
}
///
/// Returns an array of all registered properties declared in the
/// system.
///
private DependencyProperty[] GetRegisteredProperties()
{
DependencyProperty[] registeredProperties;
// We keep track of the global dependency property count.
// Because DPs are never removed, we use this value to
// verify if our cache of registered properties is up to date.
// If the count doesn't match our cached count, we re-fetch
// all registered properties.
lock(_syncLock)
{
int cacheCnt = _dpCacheCount;
int currentCnt = DependencyProperty.RegisteredPropertyCount;
if (_dpCacheArray == null || cacheCnt != currentCnt)
{
List dpList = new List(currentCnt);
lock(DependencyProperty.Synchronized)
{
foreach(DependencyProperty dp in DependencyProperty.RegisteredProperties)
{
dpList.Add(dp);
}
_dpCacheCount = DependencyProperty.RegisteredPropertyCount;
_dpCacheArray = dpList.ToArray();
}
}
registeredProperties = _dpCacheArray;
}
return registeredProperties;
}
#endregion Private Methods
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
#region Private Fields
private ICustomTypeDescriptor _parent;
private DependencyObject _instance;
private static object _syncLock = new object();
// Synchronized by "_syncLock"
private static int _dpCacheCount = 0;
// Synchronized by "_syncLock"
private static DependencyProperty[] _dpCacheArray;
#endregion Private Fields
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DefaultPrintController.cs
- _SpnDictionary.cs
- VirtualDirectoryMappingCollection.cs
- GeometryDrawing.cs
- HttpResponseHeader.cs
- SecurityContext.cs
- SizeValueSerializer.cs
- DebugView.cs
- UnsafeNativeMethods.cs
- GeneralTransform3DGroup.cs
- CompilerParameters.cs
- TimestampInformation.cs
- ResourceExpression.cs
- ELinqQueryState.cs
- WebPartDisplayMode.cs
- MessageSmuggler.cs
- TableRowCollection.cs
- InvalidAsynchronousStateException.cs
- XmlSchemaNotation.cs
- PersonalizableTypeEntry.cs
- ExpressionBinding.cs
- RequestCacheManager.cs
- _OSSOCK.cs
- ObjRef.cs
- ContentPathSegment.cs
- CatalogPart.cs
- QueryableDataSourceEditData.cs
- MatrixCamera.cs
- NativeMethodsCLR.cs
- RegisteredArrayDeclaration.cs
- AggregateNode.cs
- MenuCommand.cs
- CharKeyFrameCollection.cs
- WebPartsPersonalizationAuthorization.cs
- PropertyTabChangedEvent.cs
- Pair.cs
- DataServiceExpressionVisitor.cs
- TableRowCollection.cs
- RectKeyFrameCollection.cs
- EncodingTable.cs
- HostingPreferredMapPath.cs
- Single.cs
- DateTimeSerializationSection.cs
- XmlSubtreeReader.cs
- NetworkStream.cs
- ValuePattern.cs
- Vector3DKeyFrameCollection.cs
- ListBoxItem.cs
- EventLogQuery.cs
- documentsequencetextview.cs
- PageCatalogPartDesigner.cs
- RenderCapability.cs
- ItemsControlAutomationPeer.cs
- ImpersonationContext.cs
- TextUtf8RawTextWriter.cs
- MobileControlDesigner.cs
- JsonFormatGeneratorStatics.cs
- PeerFlooder.cs
- ProfileBuildProvider.cs
- OutputCacheModule.cs
- UInt16Storage.cs
- Processor.cs
- XamlInt32CollectionSerializer.cs
- SystemEvents.cs
- AsyncOperation.cs
- WebPartRestoreVerb.cs
- QilPatternVisitor.cs
- CustomAttributeSerializer.cs
- CustomAssemblyResolver.cs
- WebResponse.cs
- ApplicationException.cs
- UnsafeNativeMethods.cs
- RawStylusActions.cs
- StylusButtonEventArgs.cs
- SimpleTextLine.cs
- State.cs
- DiagnosticsConfigurationHandler.cs
- MenuItem.cs
- XPathScanner.cs
- ObjectCache.cs
- NativeMethods.cs
- Attributes.cs
- ViewStateChangedEventArgs.cs
- FlowDocumentPaginator.cs
- QueryResponse.cs
- DataGridViewTextBoxCell.cs
- Confirm.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- BindingElementCollection.cs
- RectangleHotSpot.cs
- GenerateHelper.cs
- PageCatalogPart.cs
- ImageAutomationPeer.cs
- DefaultEventAttribute.cs
- XPathExpr.cs
- NamespaceInfo.cs
- DeploymentSectionCache.cs
- GridSplitter.cs
- TextContainerHelper.cs
- Constants.cs