Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / CompMod / System / ComponentModel / BindingList.cs / 1305376 / BindingList.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Scope="type", Target="System.ComponentModel.BindingList`1")] namespace System.ComponentModel { using System; using System.Reflection; using System.Collections; using System.Collections.ObjectModel; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Security.Permissions; using CodeAccessPermission = System.Security.CodeAccessPermission; ////// /// [HostProtection(SharedState = true)] [Serializable] public class BindingList: Collection , IBindingList, ICancelAddNew, IRaiseItemChangedEvents { private int addNewPos = -1; private bool raiseListChangedEvents = true; private bool raiseItemChangedEvents = false; [NonSerialized()] private PropertyDescriptorCollection itemTypeProperties = null; [NonSerialized()] private PropertyChangedEventHandler propertyChangedEventHandler = null; [NonSerialized()] private AddingNewEventHandler onAddingNew; [NonSerialized()] private ListChangedEventHandler onListChanged; [NonSerialized()] private int lastChangeIndex = -1; private bool allowNew = true; private bool allowEdit = true; private bool allowRemove = true; private bool userSetAllowNew = false; #region Constructors /// /// /// Default constructor. /// public BindingList() : base() { Initialize(); } ////// /// Constructor that allows substitution of the inner list with a custom list. /// public BindingList(IListlist) : base(list) { Initialize(); } private void Initialize() { // Set the default value of AllowNew based on whether type T has a default constructor this.allowNew = ItemTypeHasDefaultConstructor; // Check for INotifyPropertyChanged if (typeof(INotifyPropertyChanged).IsAssignableFrom(typeof(T))) { // Supports INotifyPropertyChanged this.raiseItemChangedEvents = true; // Loop thru the items already in the collection and hook their change notification. foreach (T item in this.Items) { HookPropertyChanged(item); } } } private bool ItemTypeHasDefaultConstructor { get { Type itemType = typeof(T); if (itemType.IsPrimitive) { return true; } if (itemType.GetConstructor(BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance, null, new Type[0], null) != null) { return true; } return false; } } #endregion #region AddingNew event /// /// /// Event that allows a custom item to be provided as the new item added to the list by AddNew(). /// public event AddingNewEventHandler AddingNew { add { bool allowNewWasTrue = AllowNew; onAddingNew += value; if (allowNewWasTrue != AllowNew) { FireListChanged(ListChangedType.Reset, -1); } } remove { bool allowNewWasTrue = AllowNew; onAddingNew -= value; if (allowNewWasTrue != AllowNew) { FireListChanged(ListChangedType.Reset, -1); } } } ////// /// Raises the AddingNew event. /// protected virtual void OnAddingNew(AddingNewEventArgs e) { if (onAddingNew != null) { onAddingNew(this, e); } } // Private helper method private object FireAddingNew() { AddingNewEventArgs e = new AddingNewEventArgs(null); OnAddingNew(e); return e.NewObject; } #endregion #region ListChanged event ////// /// Event that reports changes to the list or to items in the list. /// public event ListChangedEventHandler ListChanged { add { onListChanged += value; } remove { onListChanged -= value; } } ////// /// Raises the ListChanged event. /// protected virtual void OnListChanged(ListChangedEventArgs e) { if (onListChanged != null) { onListChanged(this, e); } } ////// /// public void ResetBindings() { FireListChanged(ListChangedType.Reset, -1); } ////// /// public void ResetItem(int position) { FireListChanged(ListChangedType.ItemChanged, position); } // Private helper method private void FireListChanged(ListChangedType type, int index) { if (this.raiseListChangedEvents) { OnListChanged(new ListChangedEventArgs(type, index)); } } #endregion #region Collectionoverrides // Collection funnels all list changes through the four virtual methods below. // We override these so that we can commit any pending new item and fire the proper ListChanged events. protected override void ClearItems() { EndNew(addNewPos); if (this.raiseItemChangedEvents) { foreach (T item in this.Items) { UnhookPropertyChanged(item); } } base.ClearItems(); FireListChanged(ListChangedType.Reset, -1); } protected override void InsertItem(int index, T item) { EndNew(addNewPos); base.InsertItem(index, item); if (this.raiseItemChangedEvents) { HookPropertyChanged(item); } FireListChanged(ListChangedType.ItemAdded, index); } protected override void RemoveItem(int index) { // Need to all RemoveItem if this on the AddNew item if (!this.allowRemove && !(this.addNewPos >= 0 && this.addNewPos == index)) { throw new NotSupportedException(); } EndNew(addNewPos); if (this.raiseItemChangedEvents) { UnhookPropertyChanged(this[index]); } base.RemoveItem(index); FireListChanged(ListChangedType.ItemDeleted, index); } protected override void SetItem(int index, T item) { if (this.raiseItemChangedEvents) { UnhookPropertyChanged(this[index]); } base.SetItem(index, item); if (this.raiseItemChangedEvents) { HookPropertyChanged(item); } FireListChanged(ListChangedType.ItemChanged, index); } #endregion #region ICancelAddNew interface /// /// /// If item added using AddNew() is still cancellable, then remove that item from the list. /// public virtual void CancelNew(int itemIndex) { if (addNewPos >= 0 && addNewPos == itemIndex) { RemoveItem(addNewPos); addNewPos = -1; } } ////// /// If item added using AddNew() is still cancellable, then commit that item. /// public virtual void EndNew(int itemIndex) { if (addNewPos >= 0 && addNewPos == itemIndex) { addNewPos = -1; } } #endregion #region IBindingList interface ////// /// Adds a new item to the list. Calls public T AddNew() { return (T)((this as IBindingList).AddNew()); } object IBindingList.AddNew() { // Create new item and add it to list object newItem = AddNewCore(); // Record position of new item (to support cancellation later on) addNewPos = (newItem != null) ? IndexOf((T) newItem) : -1; // Return new item to caller return newItem; } private bool AddingNewHandled { get { return onAddingNew != null && onAddingNew.GetInvocationList().Length > 0; } } ///to create and add the item. /// /// Add operations are cancellable via the interface. The position of the /// new item is tracked until the add operation is either cancelled by a call to , /// explicitly commited by a call to , or implicitly commmited some other operation /// that changes the contents of the list (such as an Insert or Remove). When an add operation is /// cancelled, the new item is removed from the list. /// /// /// Creates a new item and adds it to the list. /// /// The base implementation raises the AddingNew event to allow an event handler to /// supply a custom item to add to the list. Otherwise an item of type T is created. /// The new item is then added to the end of the list. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2113:SecureLateBindingMethods")] protected virtual object AddNewCore() { // Allow event handler to supply the new item for us object newItem = FireAddingNew(); // If event hander did not supply new item, create one ourselves if (newItem == null) { Type type = typeof(T); newItem = SecurityUtils.SecureCreateInstance(type); } // Add item to end of list. Note: If event handler returned an item not of type T, // the cast below will trigger an InvalidCastException. This is by design. Add((T) newItem); // Return new item to caller return newItem; } ////// /// public bool AllowNew { get { //If the user set AllowNew, return what they set. If we have a default constructor, allowNew will be //true and we should just return true. if (userSetAllowNew || allowNew) { return this.allowNew; } //Even if the item doesn't have a default constructor, the user can hook AddingNew to provide an item. //If there's a handler for this, we should allow new. return AddingNewHandled; } set { bool oldAllowNewValue = AllowNew; userSetAllowNew = true; //Note that we don't want to set allowNew only if AllowNew didn't match value, //since AllowNew can depend on onAddingNew handler this.allowNew = value; if (oldAllowNewValue != value) { FireListChanged(ListChangedType.Reset, -1); } } } /* private */ bool IBindingList.AllowNew { get { return AllowNew; } } ////// /// public bool AllowEdit { get { return this.allowEdit; } set { if (this.allowEdit != value) { this.allowEdit = value; FireListChanged(ListChangedType.Reset, -1); } } } /* private */ bool IBindingList.AllowEdit { get { return AllowEdit; } } ////// /// public bool AllowRemove { get { return this.allowRemove; } set { if (this.allowRemove != value) { this.allowRemove = value; FireListChanged(ListChangedType.Reset, -1); } } } /* private */ bool IBindingList.AllowRemove { get { return AllowRemove; } } bool IBindingList.SupportsChangeNotification { get { return SupportsChangeNotificationCore; } } protected virtual bool SupportsChangeNotificationCore { get { return true; } } bool IBindingList.SupportsSearching { get { return SupportsSearchingCore; } } protected virtual bool SupportsSearchingCore { get { return false; } } bool IBindingList.SupportsSorting { get { return SupportsSortingCore; } } protected virtual bool SupportsSortingCore { get { return false; } } bool IBindingList.IsSorted { get { return IsSortedCore; } } protected virtual bool IsSortedCore { get { return false; } } PropertyDescriptor IBindingList.SortProperty { get { return SortPropertyCore; } } protected virtual PropertyDescriptor SortPropertyCore { get { return null; } } ListSortDirection IBindingList.SortDirection { get { return SortDirectionCore; } } protected virtual ListSortDirection SortDirectionCore { get { return ListSortDirection.Ascending; } } void IBindingList.ApplySort(PropertyDescriptor prop, ListSortDirection direction) { ApplySortCore(prop, direction); } protected virtual void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) { throw new NotSupportedException(); } void IBindingList.RemoveSort() { RemoveSortCore(); } protected virtual void RemoveSortCore() { throw new NotSupportedException(); } int IBindingList.Find(PropertyDescriptor prop, object key) { return FindCore(prop, key); } protected virtual int FindCore(PropertyDescriptor prop, object key) { throw new NotSupportedException(); } void IBindingList.AddIndex(PropertyDescriptor prop) { // Not supported } void IBindingList.RemoveIndex(PropertyDescriptor prop) { // Not supported } #endregion #region Property Change Support private void HookPropertyChanged(T item) { INotifyPropertyChanged inpc = (item as INotifyPropertyChanged); // Note: inpc may be null if item is null, so always check. if (null != inpc) { if (propertyChangedEventHandler == null) { propertyChangedEventHandler = new PropertyChangedEventHandler(Child_PropertyChanged); } inpc.PropertyChanged += propertyChangedEventHandler; } } private void UnhookPropertyChanged(T item) { INotifyPropertyChanged inpc = (item as INotifyPropertyChanged); // Note: inpc may be null if item is null, so always check. if (null != inpc && null != propertyChangedEventHandler) { inpc.PropertyChanged -= propertyChangedEventHandler; } } void Child_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (this.RaiseListChangedEvents) { if (sender == null || e == null || string.IsNullOrEmpty(e.PropertyName)) { // Fire reset event (per INotifyPropertyChanged spec) ResetBindings(); } else { // The change event is broken should someone pass an item to us that is not // of type T. Still, if they do so, detect it and ignore. It is an incorrect // and rare enough occurrence that we do not want to slow the mainline path // with "is" checks. T item; try { item = (T)sender; } catch(InvalidCastException) { ResetBindings(); return; } // Find the position of the item. This should never be -1. If it is, // somehow the item has been removed from our list without our knowledge. int pos = lastChangeIndex; if (pos < 0 || pos >= Count || !this[pos].Equals(item)) { pos = this.IndexOf(item); lastChangeIndex = pos; } if (pos == -1) { Debug.Fail("Item is no longer in our list but we are still getting change notifications."); UnhookPropertyChanged(item); ResetBindings(); } else { // Get the property descriptor if (null == this.itemTypeProperties) { // Get Shape itemTypeProperties = TypeDescriptor.GetProperties(typeof(T)); Debug.Assert(itemTypeProperties != null); } PropertyDescriptor pd = itemTypeProperties.Find(e.PropertyName, true); // Create event args. If there was no matching property descriptor, // we raise the list changed anyway. ListChangedEventArgs args = new ListChangedEventArgs(ListChangedType.ItemChanged, pos, pd); // Fire the ItemChanged event OnListChanged(args); } } } } #endregion #region IRaiseItemChangedEvents interface ////// /// Returns false to indicate that BindingList bool IRaiseItemChangedEvents.RaisesItemChangedEvents { get { return this.raiseItemChangedEvents; } } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.does NOT raise ListChanged events /// of type ItemChanged as a result of property changes on individual list items /// unless those items support INotifyPropertyChanged ///
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbSetClause.cs
- PcmConverter.cs
- PopupRootAutomationPeer.cs
- MouseWheelEventArgs.cs
- DrawingCollection.cs
- HTMLTagNameToTypeMapper.cs
- hresults.cs
- WebPartRestoreVerb.cs
- TreeView.cs
- HttpDebugHandler.cs
- WebPartDisplayMode.cs
- BuildResult.cs
- SafeFileHandle.cs
- ConfigurationCollectionAttribute.cs
- Soap.cs
- ReaderContextStackData.cs
- XmlSiteMapProvider.cs
- MaskedTextBox.cs
- GatewayDefinition.cs
- UIElementParagraph.cs
- RemoteWebConfigurationHost.cs
- SystemColors.cs
- OleDbPermission.cs
- MouseGestureConverter.cs
- EntityDataSourceReferenceGroup.cs
- UrlMappingsModule.cs
- MenuItemCollection.cs
- HexParser.cs
- TemplateApplicationHelper.cs
- ProfileGroupSettingsCollection.cs
- SQLCharsStorage.cs
- BmpBitmapEncoder.cs
- TraceSection.cs
- XmlnsDictionary.cs
- ChannelManager.cs
- CodeSubDirectory.cs
- ChangeConflicts.cs
- ListItemCollection.cs
- NumberSubstitution.cs
- WebPartEventArgs.cs
- TextServicesDisplayAttributePropertyRanges.cs
- WebPartMovingEventArgs.cs
- WebPartTransformerAttribute.cs
- Lasso.cs
- ConstraintStruct.cs
- CorrelationTokenTypeConvertor.cs
- WebUtil.cs
- TableLayoutColumnStyleCollection.cs
- LinqDataSourceDeleteEventArgs.cs
- StyleModeStack.cs
- Hashtable.cs
- RemotingSurrogateSelector.cs
- GcSettings.cs
- XmlQualifiedNameTest.cs
- PrinterResolution.cs
- WindowsListViewSubItem.cs
- InkPresenterAutomationPeer.cs
- WpfKnownMemberInvoker.cs
- ApplicationServicesHostFactory.cs
- DispatchProxy.cs
- Invariant.cs
- VectorAnimationBase.cs
- SqlDependencyListener.cs
- SmiTypedGetterSetter.cs
- XmlSchemaGroup.cs
- SecureEnvironment.cs
- StyleTypedPropertyAttribute.cs
- BamlLocalizabilityResolver.cs
- ContractCodeDomInfo.cs
- KnownTypeHelper.cs
- ExtractorMetadata.cs
- ScriptDescriptor.cs
- QueryContinueDragEvent.cs
- SystemWebCachingSectionGroup.cs
- LogStream.cs
- Utilities.cs
- Intellisense.cs
- ToggleButton.cs
- DataTransferEventArgs.cs
- SharedUtils.cs
- DashStyle.cs
- BuildResult.cs
- NewArrayExpression.cs
- LinkClickEvent.cs
- __Filters.cs
- EmptyStringExpandableObjectConverter.cs
- FunctionNode.cs
- Propagator.ExtentPlaceholderCreator.cs
- FileDialogCustomPlacesCollection.cs
- DictionarySectionHandler.cs
- RtfToXamlReader.cs
- ImagingCache.cs
- ThrowHelper.cs
- SpanIndex.cs
- StringPropertyBuilder.cs
- UTF32Encoding.cs
- MessageEventSubscriptionService.cs
- DelegateHelpers.cs
- Control.cs
- OrderByBuilder.cs