BindingListCollectionView.cs source code in C# .NET
Source code for the .NET framework in C#
Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Data / BindingListCollectionView.cs / 4 / BindingListCollectionView.cs
//----------------------------------------------------------------------------
//
//
// Copyright (C) 2003 by Microsoft Corporation. All rights reserved.
//
//
//
// See spec at [....]/connecteddata/Specs/CollectionView.mht
//
// History:
// 06/02/2003 : [....] - Ported from DotNet tree
// 03/27/2004 : [....] - Implement IList
//
//---------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Data;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using MS.Internal; // Invariant.Assert
using MS.Internal.Data;
using MS.Utility;
namespace System.Windows.Data
{
///
/// based on and associated to
/// and , namely ADO DataViews.
///
public sealed class BindingListCollectionView : CollectionView, IComparer
{
//-----------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Constructor
///
/// Underlying IBindingList
public BindingListCollectionView(IBindingList list)
: base(list)
{
InternalList = list;
_blv = list as IBindingListView;
_cachedList = new ArrayList(InternalList);
SubscribeToChanges();
_group = new CollectionViewGroupRoot(this);
_group.GroupDescriptionChanged += new EventHandler(OnGroupDescriptionChanged);
((INotifyCollectionChanged)_group).CollectionChanged += new NotifyCollectionChangedEventHandler(OnGroupChanged);
((INotifyCollectionChanged)_group.GroupDescriptions).CollectionChanged += new NotifyCollectionChangedEventHandler(OnGroupByChanged);
}
#endregion Constructors
//------------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
//------------------------------------------------------
#region ICollectionView
///
/// Return true if the item belongs to this view. The item is assumed to belong to the
/// underlying DataCollection; this method merely takes filters into account.
/// It is commonly used during collection-changed notifications to determine if the added/removed
/// item requires processing.
/// Returns true if no filter is set on collection view.
///
public override bool PassesFilter(object item)
{
if (IsCustomFilterSet)
return Contains(item); // need to ask inner list, not cheap but only way to determine
else
return true; // every item is contained
}
///
/// Return true if the item belongs to this view. No assumptions are
/// made about the item. This method will behave similarly to IList.Contains().
///
public override bool Contains(object item)
{
VerifyRefreshNotDeferred();
return CollectionProxy.Contains(item);
}
///
/// Move to the item at the given index.
///
/// Move CurrentItem to this index
/// true if points to an item within the view.
public override bool MoveCurrentToPosition(int position)
{
VerifyRefreshNotDeferred();
if (position < -1 || position > Count)
throw new ArgumentOutOfRangeException("position");
_MoveTo(position);
return IsCurrentInView;
}
#endregion ICollectionView
//------------------------------------------------------
#region IComparer
/// Return -, 0, or +, according to whether o1 occurs before, at, or after o2 (respectively)
///
/// first object
/// second object
///
/// Compares items by their resp. index in the IList.
///
int IComparer.Compare(object o1, object o2)
{
int i1 = InternalIndexOf(o1);
int i2 = InternalIndexOf(o2);
return (i1 - i2);
}
#endregion IComparer
/// Return the index where the given item belongs, or -1 if this index is unknown.
///
///
/// If this method returns an index other than -1, it must always be true that
/// view[index-1] < item <= view[index], where the comparisons are done via
/// the view's IComparer.Compare method (if any).
/// (This method is used by a listener's (e.g. System.Windows.Controls.ItemsControl)
/// CollectionChanged event handler to speed up its reaction to insertion and deletion of items.
/// If IndexOf is not implemented, a listener does a binary search using IComparer.Compare.)
///
/// data item
public override int IndexOf(object item)
{
VerifyRefreshNotDeferred();
return InternalIndexOf(item);
}
///
/// Retrieve item at the given zero-based index in this CollectionView.
///
///
///
The index is evaluated with any SortDescriptions or Filter being set on this CollectionView.
///
///
/// Thrown if index is out of range
///
public override object GetItemAt(int index)
{
VerifyRefreshNotDeferred();
return InternalItemAt(index);
}
///
/// Implementation of IEnumerable.GetEnumerator().
/// This provides a way to enumerate the members of the collection
/// without changing the currency.
///
protected override IEnumerator GetEnumerator()
{
VerifyRefreshNotDeferred();
return InternalGetEnumerator();
}
#endregion Public Methods
//-----------------------------------------------------
//
// Public Properties
//
//------------------------------------------------------
#region Public Properties
//-----------------------------------------------------
#region ICollectionView
///
/// Collection of Sort criteria to sort items in this view over the inner IBindingList.
///
///
///
/// If the underlying SourceCollection only implements IBindingList,
/// then only one sort criteria in form of a
/// can be added, specifying a property and direction to sort by.
/// Adding more than one SortDescription will cause a InvalidOperationException.
/// One such class is Generic BindingList
///
///
/// Classes like ADO's DataView (the view around a DataTable) do implement
/// IBindingListView which can support sorting by more than one property
/// and also filtering
///
///
/// Some IBindingList implementations do not support sorting; for those this property
/// will return an empty and immutable / read-only SortDescription collection.
/// Attempting to modify such a collection will cause NotSupportedException.
/// Use property on this CollectionView to test if sorting is supported
/// before modifying the returned collection.
///
///
public override SortDescriptionCollection SortDescriptions
{
get
{
if (InternalList.SupportsSorting)
{
if (_sort == null)
{
bool allowAdvancedSorting = _blv != null && _blv.SupportsAdvancedSorting;
_sort = new BindingListSortDescriptionCollection(allowAdvancedSorting);
((INotifyCollectionChanged)_sort).CollectionChanged += new NotifyCollectionChangedEventHandler(SortDescriptionsChanged);
}
return _sort;
}
else
return SortDescriptionCollection.Empty;
}
}
///
/// Test if this ICollectionView supports sorting before adding
/// to .
///
///
/// ListCollectionView does implement an IComparer based sorting.
///
public override bool CanSort
{
get
{
return InternalList.SupportsSorting;
}
}
private IComparer ActiveComparer
{
get { return _comparer; }
set
{
_comparer = value;
_group.ActiveComparer = value;
}
}
///
/// BindingListCollectionView does not support callback-based filtering.
/// Use instead.
///
public override bool CanFilter
{
get
{
return false;
}
}
///
/// Gets or sets the filter to be used to exclude items from the collection of items returned by the data source .
///
///
/// Before assigning, test if this CollectionView supports custom filtering
/// .
/// The actual syntax depends on the implementer of IBindingListView. ADO's DataView is
/// a common example, see for its supported
/// filter expression syntax.
///
public string CustomFilter
{
get { return _customFilter; }
set
{
if (!CanCustomFilter)
throw new NotSupportedException(SR.Get(SRID.BindingListCannotCustomFilter));
_customFilter = value;
RefreshOrDefer();
}
}
///
/// Test if this CollectionView supports custom filtering before assigning
/// a filter string to .
///
public bool CanCustomFilter
{
get
{
return ((_blv != null) && _blv.SupportsFiltering);
}
}
///
/// Returns true if this view really supports grouping.
/// When this returns false, the rest of the interface is ignored.
///
public override bool CanGroup
{
get { return true; }
}
///
/// The description of grouping, indexed by level.
///
public override ObservableCollection GroupDescriptions
{
get { return _group.GroupDescriptions; }
}
///
/// The top-level groups, constructed according to the descriptions
/// given in GroupDescriptions and/or GroupBySelector.
///
public override ReadOnlyObservableCollection