Browse Source

V3.1.0 reviewed

pull/1453/head
BoucherS 7 years ago
parent
commit
3c1b88956a
  1. 285
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/EmptyDataItem.cs
  2. 892
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualList.cs
  3. 153
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListEnumerator.cs
  4. 169
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListTableOfContent.cs
  5. 671
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPage.cs
  6. 817
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPageManager.cs
  7. 100
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualizedItemInfo.cs
  8. 153
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualizedItemValueCollection.cs
  9. 226
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(ForeignKeys)/DataGridForeignKeyDescription.cs
  10. 113
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(ForeignKeys)/DataTableForeignKeyDescription.cs
  11. 187
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/AsyncCommitInfo.cs
  12. 297
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/AsyncQueryInfo.cs
  13. 53
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/AsyncQueryInfoWeakComparer.cs
  14. 217
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/BindingPathValueExtractor.cs
  15. 161
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CollectionViewGroupExtensions.cs
  16. 55
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CommitItemsEvent.cs
  17. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ConnectionErrorChangedEventManager.cs
  18. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ConnectionStateChangedEventManager.cs
  19. 37
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CustomDistinctValueItemConfiguration.cs
  20. 47
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CustomDistinctValueItemConfigurationCollection.cs
  21. 2456
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionView.cs
  22. 2901
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewBase.cs
  23. 179
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewBaseDataProvider.cs
  24. 95
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewDataProvider.cs
  25. 162
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewEnumerator.cs
  26. 1055
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroup.cs
  27. 134
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroupRoot.cs
  28. 51
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroupSort.cs
  29. 63
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSort.cs
  30. 111
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSource.cs
  31. 550
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSourceBase.cs
  32. 57
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCommittingNewItemEvent.cs
  33. 84
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCreatingNewItemEvent.cs
  34. 507
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridDetailDescription.cs
  35. 77
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridDetailDescriptionCollection.cs
  36. 122
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridGroupDescription.cs
  37. 71
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridGroupInfo.cs
  38. 53
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemCancelEvent.cs
  39. 60
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemEvent.cs
  40. 51
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemHandledEvent.cs
  41. 68
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemProperty.PropertyDescriptorFromItemProperty.cs
  42. 629
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemProperty.cs
  43. 113
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyBase.PropertyDescriptorFromItemPropertyBase.cs
  44. 955
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyBase.cs
  45. 978
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyCollection.cs
  46. 35
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyCommittingValue.cs
  47. 47
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyDictionary.cs
  48. 625
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyMap.cs
  49. 118
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyMapHelper.cs
  50. 34
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyQueryValueEvent.cs
  51. 97
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyRoute.cs
  52. 43
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemRemovedEvent.cs
  53. 171
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridLINQPageManager.cs
  54. 103
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridPageManager.cs
  55. 584
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridPageManagerBase.cs
  56. 43
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridRemovingItemEvent.cs
  57. 130
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridSortDescriptionCollection.cs
  58. 126
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridUnboundItemProperty.cs
  59. 155
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionView.cs
  60. 977
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewBase.cs
  61. 53
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewDataProvider.cs
  62. 112
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewGroup.cs
  63. 469
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewGroupBase.cs
  64. 54
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewGroupRoot.cs
  65. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewSource.cs
  66. 164
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewSourceBase.cs
  67. 77
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionView.cs
  68. 54
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewDataProvider.cs
  69. 283
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewGroup.cs
  70. 146
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewGroupRoot.cs
  71. 77
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewSource.cs
  72. 141
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataRelationDetailDescription.cs
  73. 192
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataRowColumnPropertyDescriptor.cs
  74. 229
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DeferredOperation.cs
  75. 599
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DeferredOperationManager.cs
  76. 74
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DistinctValuesDictionary.cs
  77. 83
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DistinctValuesRefreshNeededEventManager.cs
  78. 104
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/EmptyDataItemSafePropertyDescriptor.cs
  79. 107
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/EntityDetailDescription.cs
  80. 44
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/EnumerableDetailDescription.cs
  81. 89
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupDescriptionCollection.cs
  82. 41
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupNameCountPair.cs
  83. 147
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupSortComparer.cs
  84. 92
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ItemPropertyGroupSortStatNameChangedEventManager.cs
  85. 116
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/JaggedArrayPropertyDescriptor.cs
  86. 47
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ListSourceDetailDescription.cs
  87. 78
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PostBatchCollectionChangedEventManager.cs
  88. 78
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PreBatchCollectionChangedEventManager.cs
  89. 182
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PropertyDetailDescription.cs
  90. 28
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PropertyRelationAttribute.cs
  91. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyCollectionRefreshEventManager.cs
  92. 93
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyGroupDescriptionsChangedEventManager.cs
  93. 93
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxySortDescriptionsChangedEventManager.cs
  94. 47
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryDistinctValueEventArgs.cs
  95. 61
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryEntityDetailsEventArgs.cs
  96. 148
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryGroupsEventArgs.cs
  97. 90
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryItemCountEvent.cs
  98. 95
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryItemsEvent.cs
  99. 798
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryableExtensions.cs
  100. 104
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/RawItem.cs

285
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/EmptyDataItem.cs

@ -1,285 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
/// <summary>
/// This object is used as the dataItem of a VirtualItemInfo when creating a VirtualItemPage and waiting for the
/// fetch callback.
/// </summary>
internal class EmptyDataItem : INotifyPropertyChanged, ICustomTypeDescriptor
{
#region CONSTRUCTORS
internal EmptyDataItem()
: base()
{
}
internal EmptyDataItem( int index, VirtualList parentVirtualList )
: base()
{
if( index < 0 )
throw new ArgumentException( "Index must be greater than or equal to zero.", "index" );
if( parentVirtualList == null )
throw new ArgumentNullException( "parentVirtualList" );
m_index = index;
m_parentVirtualList = parentVirtualList;
}
#endregion CONSTRUCTORS
#region Index Property
public int Index
{
get
{
return m_index;
}
}
#endregion Index Property
#region INTERNAL PROPERTIES
internal VirtualList ParentVirtualList
{
get
{
return m_parentVirtualList;
}
}
#endregion INTERNAL PROPERTIES
#region Indexer
[EditorBrowsable( EditorBrowsableState.Never )]
public object this[ object parameter ]
{
get
{
return null;
}
set
{
}
}
#endregion
#region PRIVATE FIELDS
private int m_index;
private VirtualList m_parentVirtualList;
#endregion PRIVATE FIELDS
#region CONSTANTS
private static readonly EmptyDataItemPropertyDescriptorCollection DefaultEmptyDataItemPropertyDescriptorCollection = new EmptyDataItemPropertyDescriptorCollection();
#endregion CONSTANTS
#region ICustomTypeDescriptor Members
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes( this );
}
public string GetClassName()
{
return TypeDescriptor.GetClassName( this );
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName( this );
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter( this );
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent( this );
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty( this );
}
public object GetEditor( Type editorBaseType )
{
return TypeDescriptor.GetEditor( this, editorBaseType );
}
public EventDescriptorCollection GetEvents( Attribute[] attributes )
{
return TypeDescriptor.GetEvents( this, attributes );
}
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents( this );
}
public PropertyDescriptorCollection GetProperties( Attribute[] attributes )
{
// We use a custom PropertyDescriptorCollection that will return the same instance
// of an EmptyDataItemPropertyDescriptor for ANY property that will be ask. This is to avoid
// BindingErrors when an EmptyDataItem is used in the grid.
return EmptyDataItem.DefaultEmptyDataItemPropertyDescriptorCollection;
}
public PropertyDescriptorCollection GetProperties()
{
return this.GetProperties( null );
}
public object GetPropertyOwner( PropertyDescriptor pd )
{
return this;
}
#endregion ICustomTypeDescriptor Members
#region EmptyDataItemPropertyDescriptorCollection Class
private class EmptyDataItemPropertyDescriptorCollection : PropertyDescriptorCollection
{
private static readonly EmptyDataItemPropertyDescriptor DefaultEmptyDataItemPropertyDescriptor = new EmptyDataItemPropertyDescriptor();
private static readonly EmptyDataItemPropertyDescriptor[] DefaultEmptyDataItemPropertyDescriptorArray = new EmptyDataItemPropertyDescriptor[]
{
EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor,
};
public EmptyDataItemPropertyDescriptorCollection()
: base( EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptorArray )
{
}
public override PropertyDescriptor Find( string name, bool ignoreCase )
{
return EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor;
}
public override PropertyDescriptor this[ int index ]
{
get
{
return EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor;
}
}
public override PropertyDescriptor this[ string name ]
{
get
{
return EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor;
}
}
}
#endregion EmptyDataItemPropertyDescriptorCollection Class
#region EmptyDataItemPropertyDescriptor Class
private class EmptyDataItemPropertyDescriptor : PropertyDescriptor
{
private const string DefaultPropertyName = "Empty";
private static readonly Type ObjectType = typeof( object );
public EmptyDataItemPropertyDescriptor()
: base( EmptyDataItemPropertyDescriptor.DefaultPropertyName, null )
{
}
public override bool CanResetValue( object component )
{
return false;
}
public override Type ComponentType
{
get
{
return EmptyDataItemPropertyDescriptor.ObjectType;
}
}
public override object GetValue( object component )
{
return null;
}
public override bool IsReadOnly
{
get
{
return false;
}
}
public override Type PropertyType
{
get
{
return EmptyDataItemPropertyDescriptor.ObjectType;
}
}
public override void ResetValue( object component )
{
}
public override void SetValue( object component, object value )
{
}
public override bool ShouldSerializeValue( object component )
{
return false;
}
}
#endregion EmptyDataItemPropertyDescriptor Class
#region INotifyPropertyChanged Members
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { }
remove { }
}
#endregion
}
}

892
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualList.cs

@ -1,892 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualList : IList, IList<object>, INotifyCollectionChanged, IDisposable
{
public VirtualList( VirtualPageManager pagingManager )
: this( pagingManager, -1 )
{
}
public VirtualList( VirtualPageManager pagingManager, int virtualCount )
{
if( pagingManager == null )
throw new ArgumentNullException( "pagingManager" );
pagingManager.ManageList( this );
m_tableOfContent = new VirtualListTableOfContent( 8 );
m_virtualCount = virtualCount;
}
#region VirtualPagingManager Property
public VirtualPageManager PagingManager
{
get
{
return m_pagingManager;
}
}
#endregion
#region VirtualCount Property
public int VirtualCount
{
get
{
if( this.IsDisposed )
return 0;
if( m_virtualCount == -1 )
this.QueryAndSetVirtualCount();
return m_virtualCount;
}
}
#endregion
#region TableOfContent Property
internal VirtualListTableOfContent TableOfContent
{
get
{
return m_tableOfContent;
}
}
#endregion
#region VirtualPagingManager Property
internal VirtualPageManager VirtualPagingManager
{
get
{
return m_pagingManager;
}
set
{
// null is an acceptable value when disposing the list
if( ( m_pagingManager != null ) && ( value != null ) )
throw new InvalidOperationException( "An attempt was made to set a VirtualPageManager when one has already been provided." );
m_pagingManager = value;
}
}
#endregion
#region IsDisposed Property
internal bool IsDisposed
{
get
{
return m_flags[ ( int )VirtualItemBookFlags.Disposed ];
}
private set
{
m_flags[ ( int )VirtualItemBookFlags.Disposed ] = value;
}
}
#endregion
#region IsRestarting Property
internal bool IsRestarting
{
get
{
return m_flags[ ( int )VirtualItemBookFlags.Restarting ];
}
private set
{
m_flags[ ( int )VirtualItemBookFlags.Restarting ] = value;
}
}
#endregion
#region HasPagePendingCommit Property
internal bool HasPagePendingCommit
{
get
{
foreach( VirtualPage page in m_tableOfContent.VirtualPages )
{
if( page.IsCommitPending )
return true;
}
return false;
}
}
#endregion
#if DEBUG
public override string ToString()
{
StringBuilder builder = new StringBuilder();
ReadOnlyCollection<VirtualPage> virtualPages = m_tableOfContent.VirtualPages;
int pageCount = virtualPages.Count;
for( int i = 0; i < pageCount; i++ )
{
VirtualPage page = virtualPages[ i ];
builder.Append( i.ToString() + ": Page " + page.ToString() + Environment.NewLine );
}
return builder.ToString();
}
#endif
internal int IndexOf( object item )
{
if( ( item == null ) || ( this.IsDisposed ) )
return -1;
EmptyDataItem emptyDataItem = item as EmptyDataItem;
if( emptyDataItem != null )
{
if( ( emptyDataItem.ParentVirtualList == this ) && ( emptyDataItem.Index < m_virtualCount ) )
return emptyDataItem.Index;
return -1;
}
return m_tableOfContent.IndexOf( item );
}
internal bool IsPageDirty( int index )
{
VirtualPage page = this.GetPageOrDefaultForItemIndex( index, true );
return ( page == null ) ? false : page.IsDirty;
}
internal bool IsItemDirty( object item )
{
int localIndex = this.IndexOf( item );
if( localIndex == -1 )
return false;
VirtualizedItemInfo virtualizedItemInfo = this.GetVirtualizedItemInfoAtIndex( localIndex, false, true );
return ( virtualizedItemInfo == null ) ? false : virtualizedItemInfo.IsDirty;
}
internal VirtualizedItemValueCollection GetCachedValuesForItemAtIndex( int index )
{
VirtualizedItemInfo virtualizedItemInfo = this.GetVirtualizedItemInfoAtIndex( index, false, true );
return ( virtualizedItemInfo == null ) ? null : virtualizedItemInfo.OldValues;
}
internal void SetCachedValuesForItemAtIndex( int index, string[] names, object[] values )
{
VirtualizedItemInfo virtualizedItemInfo = this.GetVirtualizedItemInfoAtIndex( index, false, true );
if( virtualizedItemInfo == null )
throw new ArgumentOutOfRangeException( "index", index, "No VirtualizedItemInfo can be found at the specified index." );
virtualizedItemInfo.OldValues = new VirtualizedItemValueCollection( names, values );
}
internal void ClearCachedValuesForItemAtIndex( int index )
{
VirtualizedItemInfo virtualizedItemInfo = this.GetVirtualizedItemInfoAtIndex( index, false, true );
if( virtualizedItemInfo == null )
throw new ArgumentOutOfRangeException( "index", index, "No VirtualizedItemInfo can be found at the specified index." );
virtualizedItemInfo.OldValues = null;
}
internal object GetItemAt( int index )
{
if( ( index < 0 ) || ( index >= m_virtualCount ) )
throw new ArgumentOutOfRangeException( "Index", index, "index must be greater than or equal to zero and less than count." );
VirtualizedItemInfo virtualizedItemInfo = this.GetVirtualizedItemInfoAtIndex( index, true, false );
return virtualizedItemInfo.DataItem;
}
internal VirtualizedItemInfo GetVirtualizedItemInfoAtIndex( int index, bool createPageIfLineNotFound, bool preventMovePageToFront )
{
VirtualizedItemInfo virtualizedItemInfo = null;
VirtualPage page = this.GetPageOrDefaultForItemIndex( index, preventMovePageToFront );
if( page != null )
{
virtualizedItemInfo = page.GetVirtualizedItemInfoAtIndex( index );
Debug.Assert( virtualizedItemInfo != null );
}
else if( createPageIfLineNotFound )
{
page = this.CreateNewPage( index );
virtualizedItemInfo = page.GetVirtualizedItemInfoAtIndex( index );
m_pagingManager.AddPage( page, VirtualPageManager.PageInsertPosition.Front );
}
return virtualizedItemInfo;
}
internal void LockPageForLocalIndex( int sourceIndex )
{
Debug.Assert( m_tableOfContent.ContainsPageForSourceIndex( sourceIndex ) );
Debug.Assert( this.GetPageOrDefaultForItemIndex( sourceIndex, true ) != null );
VirtualPage page;
if( m_tableOfContent.TryGetPageForSourceIndex( sourceIndex, out page ) )
{
if( page.LockPage() )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "List: " + this.GetHashCode().ToString() + " - LOCKING PAGE: " + page.ToString() + " for index: " + sourceIndex.ToString() + " NEW LOCKED PAGES COUNT: " + this.GetLockedPageCount().ToString() );
}
this.PreEmptiveLoadPages( sourceIndex, page );
}
}
internal void UnlockPageForLocalIndex( int sourceIndex )
{
if( this.IsDisposed )
return;
VirtualPage page;
if( m_tableOfContent.TryGetPageForSourceIndex( sourceIndex, out page ) )
{
if( page.UnlockPage() )
{
Debug.Assert( this.GetLockedPageCount() >= 0 );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "List: " + this.GetHashCode().ToString() + " - UN-LOCKING PAGE: " + page.ToString() + " for index: " + sourceIndex.ToString() + " NEW LOCKED PAGES COUNT: " + this.GetLockedPageCount().ToString() );
m_pagingManager.CleanUpAndDisposeUnused();
}
}
}
private void PreEmptiveLoadPages( int sourceIndex, VirtualPage page )
{
// The VirtualList is disposed or part of a PagingManager that will be disposed (only disconnected when dispose is required)
if( !this.PagingManager.IsConnected )
return;
Debug.Assert( !this.IsDisposed );
double preemptivePageQueryRatio = m_pagingManager.PreemptivePageQueryRatio;
int pageSize = m_pagingManager.PageSize;
double pageRatio = ( preemptivePageQueryRatio > 0.5 ) ? 0.5 : ( preemptivePageQueryRatio < 0.0 ) ? 0 : preemptivePageQueryRatio;
double boundariesItemCount = ( pageRatio * pageSize );
int preEmptivePageStartIndex = -1;
if( ( page.StartDataIndex > 0 ) && ( sourceIndex < ( page.StartDataIndex + boundariesItemCount ) ) )
{
// Pre emptively load the previous page.
preEmptivePageStartIndex = page.StartDataIndex - pageSize;
}
else if( ( page.EndDataIndex < ( m_virtualCount - 1 ) ) && ( sourceIndex > ( page.EndDataIndex - boundariesItemCount ) ) )
{
// Pre emptively load the next page.
preEmptivePageStartIndex = page.EndDataIndex + 1;
}
if( preEmptivePageStartIndex != -1 )
{
VirtualPage preEmptivePage = null;
// We do not want to move the pre-emptive page to the front if it is already created since it does not count as a legitimate user-acess.
preEmptivePage = this.GetPageOrDefaultForItemIndex( preEmptivePageStartIndex, true );
if( preEmptivePage == null )
{
// The pre-emptive page is not yet created. Let's do it and add it to the back since it is not really accessed at the moment.
preEmptivePage = this.CreateNewPage( preEmptivePageStartIndex );
m_pagingManager.AddPage( preEmptivePage, VirtualPageManager.PageInsertPosition.Back );
}
}
}
internal bool IsAsyncCommitQueuedForItem( object item )
{
VirtualPage virtualPage;
if( m_tableOfContent.TryGetPageForItem( item, out virtualPage ) )
return virtualPage.IsAsyncCommitInfoQueuedForItem( item );
return false;
}
internal void CommitAll()
{
foreach( VirtualPage page in m_tableOfContent.VirtualPages )
{
Debug.Assert( page != null );
Debug.Assert( page.ParentVirtualList == this );
if( page.IsDirty )
{
m_pagingManager.QueueCommitData( page );
}
}
}
internal void Restart()
{
if( this.IsRestarting )
return;
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Restart VirtualList requested, checking for pages to commit or abort..." );
this.IsRestarting = true;
m_pagingManager.OnVirtualListRestarting( this );
// We must keep a copy since restarting can remove pages from table of content
int virtualPagesCount = m_tableOfContent.VirtualPages.Count;
if( virtualPagesCount == 0 )
{
this.EndRestart();
}
else
{
// Restart every pages this VirtualList contains.
// Keep a reference to the pages that need to restart in order to know when this VirtualList is restarted
m_restartingPages.AddRange( m_tableOfContent.VirtualPages );
for( int i = virtualPagesCount - 1; i >= 0; i-- )
{
VirtualPage page = m_tableOfContent.VirtualPages[ i ];
Debug.Assert( !page.IsDisposed );
if( !page.IsRestarting )
{
page.Restart();
}
}
}
}
internal void OnVirtualPageRestarting( VirtualPage page )
{
// Notify the VirtualPageManager that this page is restarted to ensure it commits its data or aborts the QueryItems if already invoked
Debug.Assert( m_restartingPages.Contains( page ) );
m_pagingManager.OnVirtualListPageRestarting( this, page );
}
internal void OnVirtualPageRestarted( VirtualPage page )
{
Debug.Assert( m_restartingPages.Contains( page ) );
// The page is restarted, remove it from the restarting pages
m_restartingPages.Remove( page );
// Notify the manager that this page is restarted in order to let it remove it from its m_pageNodes and also from this VirtualList TableOfContent.
// NOTE: We do not remove it from the TableOfContent immediately to avoid have to insert a condition in VirtualPageManager.RemovePage since this method
// used widely to ensure a page is removed from the TableOfContent and from the m_pageNodes list.
m_pagingManager.OnVirtualListPageRestarted( this, page );
// Ensure all restarted pages completed their commit or abort operation before notifying that this list is restarted
if( m_restartingPages.Count == 0 )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Cleared VirtualList" );
this.EndRestart();
}
}
internal void FillEmptyPage( AsyncQueryInfo asyncQueryInfo, object[] fetchedItems )
{
// The VirtualList is disposed or part of a PagingManager that will be disposed (only disconnected when dispose is required)
if( !this.PagingManager.IsConnected )
return;
Debug.Assert( !this.IsDisposed );
Debug.Assert( !asyncQueryInfo.IsDisposed );
// We do not want to move the page we are about to fill to the front since it does not count as a legitimate user-acess. It will get moved to the front when one of its item is accessed.
VirtualPage page = null;
page = this.GetPageOrDefaultForItemIndex( asyncQueryInfo.StartIndex, true );
// Although extremely rare, this situation could occur if we are calling RemovePageNode and the QueryData Dispatcher Operation
// which has been asyncronously invoked in CreateNewPage is raising the QueryData event at the exact moment when we
// try to abort the dispatcher operation. This means that the customer will have queued an async request for data
// for a page we no longer care about, and have already removed from the Table of Content and our LinkedList.
// This should NOT occur if the user did not abort the request and called the AsyncQueryInfo EndQuery method since AsyncQueryInfo should
// not have invoked the EndQueryAction if its ShouldAbort property was set to true.
if( page == null )
return;
Debug.Assert( !page.IsFilled );
Debug.Assert( this.GetPageStartingIndexForItemIndex( asyncQueryInfo.StartIndex ) == asyncQueryInfo.StartIndex );
Debug.Assert( fetchedItems.Length <= page.Count );
if( fetchedItems.Length == page.Count )
{
object[] oldItems = page.ToItemArray();
m_tableOfContent.RemovePage( page );
page.EndQueryItems( asyncQueryInfo, fetchedItems );
m_tableOfContent.AddPage( page );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Replaced TOC items/index for page: " + page.ToString() );
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace, fetchedItems, oldItems, asyncQueryInfo.StartIndex ) );
}
else
{
// The expected count was not met. Maybe the user told us the source was bigger than it really is, or maybe there were delete operations made on the source since the last restart.
// Let's refresh the CollectionView. This will restart the VirtualItemBook and raise the CollectionView's OnCollectionChanged Reset notification.
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
}
internal void NotifyCommitComplete( AsyncCommitInfo asyncCommitInfo )
{
if( asyncCommitInfo.VirtualizedItemInfos.Length < 1 )
throw new DataGridInternalException( "VirualizedItemInfos is empty." );
int indexForItemInPage = asyncCommitInfo.VirtualizedItemInfos[ 0 ].Index;
// We do not want to move the page we are about to flag has committed to the front since it does not count as a legitimate user-access.
// It will get moved to the front when one of its items is accessed.
VirtualPage page = null;
page = this.GetPageOrDefaultForItemIndex( indexForItemInPage, true );
if( page == null )
throw new InvalidOperationException( "An attempt was made to retrieve a page does not exist." );
if( ( !this.HasPagePendingCommit ) || ( !page.IsCommitPending ) )
throw new InvalidOperationException( "An attempt was made to commit a page that does not have a pending commit operation." );
Debug.Assert( page.IsDirty );
page.EndCommitItems( asyncCommitInfo );
// If we no longer have any pages pending commit.
if( !this.HasPagePendingCommit )
{
// CleanUp and queue a request to fill empty pages from the start of the queue.
m_pagingManager.CleanUpAndDisposeUnused();
// This is a failsafe, to make sure that during the clean-up other commit were not queued.
if( !this.HasPagePendingCommit )
{
if( !this.IsRestarting )
{
// After the call to cleanup, there should only be LOCKED pending fill pages remaining. Those are the one to refetch.
List<VirtualPage> lockedPages = this.GetLockedPages();
int lockedPageCount = lockedPages.Count;
for( int i = 0; i < lockedPageCount; i++ )
{
VirtualPage lockedPage = lockedPages[ i ];
if( lockedPage.IsFilled )
continue;
// The locked page has been created while commit was pending. Let's queue its query data operation.
m_pagingManager.QueueQueryData( lockedPage );
}
}
else
{
this.Restart();
}
}
}
}
private void EndRestart()
{
Debug.Assert( m_restartingPages.Count == 0 );
m_virtualCount = -1;
this.IsRestarting = false;
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "VirtualList restarted" );
m_pagingManager.OnVirtualListRestarted( this );
this.Dispose();
}
private int GetPageStartingIndexForItemIndex( int itemIndex )
{
int pageSize = m_pagingManager.PageSize;
return ( itemIndex / pageSize ) * pageSize;
}
private VirtualPage CreateNewPage( int itemIndex )
{
Debug.Assert( !m_tableOfContent.ContainsPageForSourceIndex( itemIndex ) );
int pageStartIndex = this.GetPageStartingIndexForItemIndex( itemIndex );
int pageSize = m_pagingManager.PageSize;
int expectedItemCount = Math.Min( pageSize, ( m_virtualCount - pageStartIndex ) );
expectedItemCount = Math.Max( 0, expectedItemCount );
VirtualPage page = VirtualPage.CreateEmptyPage( this, pageStartIndex, expectedItemCount );
m_tableOfContent.AddPage( page );
// If we have a pending commit page, this brandly new created page will get its query data queued when we are notified of a commit completed and that we no longer have any pages awaiting commiting.
if( !this.HasPagePendingCommit )
{
m_pagingManager.QueueQueryData( page );
}
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Creating VirtualItemPlaceHolder for page: " + page.ToString() );
return page;
}
private VirtualPage GetPageOrDefaultForItemIndex( int index, bool preventMoveToFront )
{
VirtualPage page = null;
if( m_tableOfContent.TryGetPageForSourceIndex( index, out page ) )
{
if( !preventMoveToFront )
m_pagingManager.MovePageToFront( page );
}
return page;
}
private int GetLockedPageCount()
{
int lockedPageCount = 0;
foreach( VirtualPage page in m_tableOfContent.VirtualPages )
{
Debug.Assert( page != null );
if( ( page != null ) && ( page.IsLocked ) )
lockedPageCount++;
}
return lockedPageCount;
}
private List<VirtualPage> GetLockedPages()
{
List<VirtualPage> lockedPages = new List<VirtualPage>();
foreach( VirtualPage page in m_tableOfContent.VirtualPages )
{
Debug.Assert( page != null );
if( ( page != null ) && ( page.IsLocked ) )
{
lockedPages.Add( page );
}
}
return lockedPages;
}
private void QueryAndSetVirtualCount()
{
int count = m_pagingManager.OnQueryItemCount( this );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, ( count != -1 ) ? "QUERY VIRTUAL COUNT: " + count.ToString() : "QUERY VIRTUAL COUNT NOT HANDLED, SETTING COUNT TO ZERO." );
if( count == -1 )
{
count = 0;
}
m_virtualCount = count;
}
private void OnCollectionChanged( NotifyCollectionChangedEventArgs e )
{
var handler = this.CollectionChanged;
if( handler == null )
return;
handler.Invoke( this, e );
}
#region IList<object> Members
int IList<object>.IndexOf( object item )
{
return this.IndexOf( item );
}
void IList<object>.Insert( int index, object item )
{
throw new NotImplementedException();
}
void IList<object>.RemoveAt( int index )
{
throw new NotImplementedException();
}
object IList<object>.this[ int index ]
{
get
{
return this.GetItemAt( index );
}
set
{
throw new NotImplementedException();
}
}
#endregion
#region ICollection<object> Members
void ICollection<object>.Add( object item )
{
throw new NotImplementedException();
}
void ICollection<object>.Clear()
{
throw new NotImplementedException();
}
bool ICollection<object>.Contains( object item )
{
return ( this.IndexOf( item ) != -1 );
}
void ICollection<object>.CopyTo( object[] array, int arrayIndex )
{
throw new NotImplementedException();
}
int ICollection<object>.Count
{
get
{
return this.VirtualCount;
}
}
bool ICollection<object>.IsReadOnly
{
get
{
return true;
}
}
bool ICollection<object>.Remove( object item )
{
throw new NotImplementedException();
}
#endregion
#region IEnumerable<object> Members
IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
return new VirtualListEnumerator( this );
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return ( ( IEnumerable<object> )this ).GetEnumerator();
}
#endregion
#region INotifyCollectionChanged Members
public event NotifyCollectionChangedEventHandler CollectionChanged;
#endregion
#region IList Members
int IList.Add( object value )
{
throw new NotImplementedException();
}
void IList.Clear()
{
throw new NotImplementedException();
}
bool IList.Contains( object value )
{
return this.IndexOf( value ) != -1;
}
int IList.IndexOf( object value )
{
return this.IndexOf( value );
}
void IList.Insert( int index, object value )
{
throw new NotImplementedException();
}
bool IList.IsFixedSize
{
get
{
return true;
}
}
bool IList.IsReadOnly
{
get
{
return true;
}
}
void IList.Remove( object value )
{
throw new NotImplementedException();
}
void IList.RemoveAt( int index )
{
throw new NotImplementedException();
}
object IList.this[ int index ]
{
get
{
return this.GetItemAt( index );
}
set
{
throw new NotImplementedException();
}
}
#endregion
#region ICollection Members
void ICollection.CopyTo( Array array, int index )
{
throw new NotImplementedException();
}
int ICollection.Count
{
get
{
return this.VirtualCount;
}
}
bool ICollection.IsSynchronized
{
get
{
throw new NotImplementedException();
}
}
object ICollection.SyncRoot
{
get
{
throw new NotImplementedException();
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
if( m_tableOfContent != null )
{
Debug.Assert( m_tableOfContent.VirtualPages.Count == 0 );
m_tableOfContent.Dispose();
m_tableOfContent = null;
}
m_pagingManager = null;
this.IsDisposed = true;
}
#endregion
private List<VirtualPage> m_restartingPages = new List<VirtualPage>();
private VirtualPageManager m_pagingManager;
private BitVector32 m_flags;
private int m_virtualCount;
private VirtualListTableOfContent m_tableOfContent;
[Flags]
private enum VirtualItemBookFlags
{
Restarting = 1,
Disposed = 2,
}
}
}

153
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListEnumerator.cs

@ -1,153 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualListEnumerator : IEnumerator<object>, IEnumerator
{
public VirtualListEnumerator( VirtualList virtualList )
{
if( virtualList == null )
throw new ArgumentNullException( "virtualList" );
m_virtualList = virtualList;
m_version = m_virtualList.PagingManager.Version;
m_orderedFilledVirtualPages =
m_virtualList.TableOfContent.VirtualPages.OrderBy(
virtualPage => virtualPage.StartDataIndex ).Where(
virtualPage => virtualPage.IsFilled ).ToArray();
}
#region INTERNAL PROPERTIES
internal bool BeforeStart
{
get
{
return m_beforeStart;
}
}
internal bool AfterEnd
{
get
{
return m_afterEnd;
}
}
#endregion INTERNAL PROPERTIES
#region IDisposable Members
public void Dispose()
{
m_currentItemInfo = null;
m_orderedFilledVirtualPages = null;
m_virtualList = null;
}
#endregion IDisposable Members
#region IEnumerator<object> Members
public object Current
{
get
{
return ( m_currentItemInfo == null ) ? null : m_currentItemInfo.DataItem;
}
}
#endregion IEnumerator<object> Members
#region IEnumerator Members
object IEnumerator.Current
{
get
{
return ( m_currentItemInfo == null ) ? null : m_currentItemInfo.DataItem;
}
}
public bool MoveNext()
{
if( m_version != m_virtualList.PagingManager.Version )
throw new InvalidOperationException( "Collection was modified." );
if( m_beforeStart )
m_beforeStart = false;
if( m_currentPageIndex < m_orderedFilledVirtualPages.Length )
{
VirtualPage virtualPage = m_orderedFilledVirtualPages[ m_currentPageIndex ];
m_currentItemInfo = virtualPage[ m_currentItemIndex ];
m_currentItemIndex++;
if( m_currentItemIndex >= virtualPage.Count )
{
m_currentItemIndex = 0;
m_currentPageIndex++;
}
return true;
}
else
{
m_currentItemInfo = null;
m_afterEnd = true;
return false;
}
}
public void Reset()
{
m_currentItemInfo = null;
m_currentItemIndex = 0;
m_currentPageIndex = 0;
m_afterEnd = false;
m_beforeStart = true;
}
#endregion IEnumerator Members
#region PRIVATE FIELDS
private VirtualList m_virtualList;
private VirtualPage[] m_orderedFilledVirtualPages;
private int m_version;
private VirtualizedItemInfo m_currentItemInfo;
private int m_currentPageIndex;
private int m_currentItemIndex;
private bool m_beforeStart;
private bool m_afterEnd;
#endregion PRIVATE FIELDS
}
}

169
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListTableOfContent.cs

@ -1,169 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualListTableOfContent : IDisposable
{
internal VirtualListTableOfContent( int initialCapacity )
{
m_virtualPages = new List<VirtualPage>();
m_readonlyVirtualPages = new ReadOnlyCollection<VirtualPage>( m_virtualPages );
m_objectVersusIndexDictionary = new Dictionary<object, int>( initialCapacity );
m_indexVersusPageDictionary = new Dictionary<int, VirtualPage>( initialCapacity );
}
public void AddPage( VirtualPage page )
{
Debug.Assert( !m_virtualPages.Contains( page ) );
m_virtualPages.Add( page );
int itemCount = page.Count;
for( int i = 0; i < itemCount; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = page[ i ];
Debug.Assert( !m_objectVersusIndexDictionary.ContainsKey( virtualizedItemInfo.DataItem ) );
Debug.Assert( !m_indexVersusPageDictionary.ContainsKey( virtualizedItemInfo.Index ) );
m_objectVersusIndexDictionary.Add( virtualizedItemInfo.DataItem, virtualizedItemInfo.Index );
m_indexVersusPageDictionary.Add( virtualizedItemInfo.Index, page );
}
}
public void RemovePage( VirtualPage page )
{
Debug.Assert( m_virtualPages.Contains( page ) );
int itemCount = page.Count;
for( int i = 0; i < itemCount; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = page[ i ];
Debug.Assert( m_objectVersusIndexDictionary.ContainsKey( virtualizedItemInfo.DataItem ) );
Debug.Assert( m_indexVersusPageDictionary.ContainsKey( virtualizedItemInfo.Index ) );
Debug.Assert( m_indexVersusPageDictionary[ virtualizedItemInfo.Index ] == page );
m_objectVersusIndexDictionary.Remove( virtualizedItemInfo.DataItem );
m_indexVersusPageDictionary.Remove( virtualizedItemInfo.Index );
}
m_virtualPages.Remove( page );
}
public int IndexOf( object item )
{
int index;
if( m_objectVersusIndexDictionary.TryGetValue( item, out index ) )
return index;
return -1;
}
public bool TryGetPageForItem( object item, out VirtualPage page )
{
page = null;
int index;
if( m_objectVersusIndexDictionary.TryGetValue( item, out index ) )
return m_indexVersusPageDictionary.TryGetValue( index, out page );
return false;
}
public bool TryGetPageForSourceIndex( int sourceIndex, out VirtualPage page )
{
return m_indexVersusPageDictionary.TryGetValue( sourceIndex, out page );
}
public bool ContainsPageForItem( object item )
{
int index;
if( m_objectVersusIndexDictionary.TryGetValue( item, out index ) )
return m_indexVersusPageDictionary.ContainsKey( index );
return false;
}
public bool ContainsPageForSourceIndex( int sourceIndex )
{
return m_indexVersusPageDictionary.ContainsKey( sourceIndex );
}
public int Count
{
get
{
Debug.Assert( m_objectVersusIndexDictionary.Count == m_indexVersusPageDictionary.Count );
return m_objectVersusIndexDictionary.Count;
}
}
public ReadOnlyCollection<VirtualPage> VirtualPages
{
get
{
return m_readonlyVirtualPages;
}
}
private Dictionary<object, int> m_objectVersusIndexDictionary;
private Dictionary<int, VirtualPage> m_indexVersusPageDictionary;
private List<VirtualPage> m_virtualPages;
private ReadOnlyCollection<VirtualPage> m_readonlyVirtualPages;
#region IDisposable Members
public void Dispose()
{
while( m_virtualPages.Count > 0 )
{
// Remove the page from every Dictionaries and
// also from m_virtualPages
VirtualPage page = m_virtualPages[ 0 ];
this.RemovePage( page );
page.Dispose();
}
Debug.Assert( m_objectVersusIndexDictionary.Count == 0 );
Debug.Assert( m_indexVersusPageDictionary.Count == 0 );
Debug.Assert( m_virtualPages.Count == 0 );
m_objectVersusIndexDictionary.Clear();
m_indexVersusPageDictionary.Clear();
m_virtualPages.Clear();
}
#endregion
}
}

671
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPage.cs

@ -1,671 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualPage : List<VirtualizedItemInfo>, IDisposable
{
internal static VirtualPage CreateEmptyPage( VirtualList parentVirtualList, int startSourceIndex, int entryCount )
{
if( parentVirtualList == null )
throw new ArgumentNullException( "parentVirtualList" );
if( startSourceIndex < 0 )
throw new ArgumentOutOfRangeException( "startSourceIndex", startSourceIndex, "startSourceIndex must be greater than or equal to zero." );
if( entryCount < 0 )
throw new ArgumentOutOfRangeException( "entryCount", entryCount, "entryCount must be greater than or equal to zero." );
EmptyDataItem[] emptyDataItems = new EmptyDataItem[ entryCount ];
for( int i = 0; i < entryCount; i++ )
{
emptyDataItems[ i ] = new EmptyDataItem( startSourceIndex + i, parentVirtualList );
}
VirtualPage emptyDataItemPage = new VirtualPage( parentVirtualList, startSourceIndex, emptyDataItems );
emptyDataItemPage.IsFilled = false;
return emptyDataItemPage;
}
private VirtualPage( VirtualList parentVirtualList, int startSourceIndex, object[] dataItems )
: base( dataItems.Length )
{
if( parentVirtualList == null )
throw new ArgumentNullException( "parentVirtualList" );
if( startSourceIndex < 0 )
throw new ArgumentOutOfRangeException( "startSourceIndex", startSourceIndex, "startSourceIndex must be greater than or equal to zero." );
m_startDataIndex = startSourceIndex;
m_asyncCommitInfoList = new List<AsyncCommitInfo>();
m_parentVirtualList = parentVirtualList;
int length = dataItems.Length;
for( int i = 0; i < length; i++ )
{
Debug.Assert( dataItems[ i ] != null );
this.Add( new VirtualizedItemInfo( m_startDataIndex + i, dataItems[ i ] ) );
}
this.IsFilled = true;
}
#region RemoveAfterOperation Property
public bool RemoveAfterOperation
{
get;
set;
}
#endregion
#region IsAborting Property
public bool IsAborting
{
get;
private set;
}
#endregion
#region IsRestarting Property
public bool IsRestarting
{
get;
private set;
}
#endregion
#region IsEmpty Property
public bool IsEmpty
{
get
{
return ( this.Count == 0 );
}
}
#endregion
#region IsFilled Property
public bool IsFilled
{
get
{
return m_flags[ ( int )VirtualItemPageFlags.IsFilled ];
}
private set
{
// Wether we are setting PendingFill to True or to False, we should not be touching this property if we are pending commit.
Debug.Assert( !this.IsCommitPending );
m_flags[ ( int )VirtualItemPageFlags.IsFilled ] = value;
}
}
#endregion
#region IsDisposed Read-Only Property
public bool IsDisposed
{
get
{
return m_flags[ ( int )VirtualItemPageFlags.IsDisposed ];
}
private set
{
m_flags[ ( int )VirtualItemPageFlags.IsDisposed ] = value;
}
}
#endregion
#region IsCommitPending Property
public bool IsCommitPending
{
get
{
return m_asyncCommitInfoList.Count > 0;
}
}
#endregion
#region IsDirty Property
public bool IsDirty
{
get
{
if( !this.IsFilled )
return false;
int count = this.Count;
for( int i = 0; i < count; i++ )
{
if( this[ i ].IsDirty )
return true;
}
return false;
}
}
#endregion
#region IsLocked Property
public bool IsLocked
{
get
{
return ( m_lockCount > 0 );
}
}
#endregion
#region IsRemovable Property
public bool IsRemovable
{
get
{
// A page which IsPendingFill is removable since it hasn't even been filled yet.
return ( ( !this.IsLocked ) && ( !this.IsCommitPending ) );
}
}
#endregion
#region ParentVirtualList Property
public VirtualList ParentVirtualList
{
get
{
return m_parentVirtualList;
}
}
#endregion
#region StartDataIndex Property
public int StartDataIndex
{
get
{
return m_startDataIndex;
}
}
#endregion
#region EndDataIndex Property
public int EndDataIndex
{
get
{
return m_startDataIndex + ( this.Count - 1 );
}
}
#endregion
public VirtualizedItemInfo GetVirtualizedItemInfoAtIndex( int sourceIndex )
{
int index = this.SourceIndexToPageEntryIndex( sourceIndex );
if( index != -1 )
return this[ index ];
return null;
}
#if DEBUG
public override string ToString()
{
string representation = string.Empty;
if( !this.IsFilled )
{
representation += "Fill Pending - ";
}
if( this.IsEmpty )
{
representation += m_startDataIndex.ToString() + " - EMPTY.";
}
else
{
representation += m_startDataIndex.ToString() + " - " + this.EndDataIndex.ToString();
}
return representation;
}
#endif
public object[] ToItemArray()
{
int count = this.Count;
object[] items = new object[ count ];
for( int i = 0; i < count; i++ )
{
items[ i ] = this[ i ].DataItem;
}
return items;
}
internal bool LockPage()
{
m_lockCount++;
// Returns True if the page just became locked (and is not up for removal) or False if the call simply incremented the lock count.
return m_lockCount == 1;
}
internal bool UnlockPage()
{
if( m_lockCount > 0 )
{
m_lockCount--;
}
else
{
// Safety Net. We return False, even though the lock count is reinitialized to zero, since the page did not just become unlocked.
// This can occur when the DataGridVirtualizingCollectionView hits ForceRefresh method restarts the VirtualItemBook, thus getting rid
// of locked and unlocked pages and THEN, the Generator's WeakEventListener of CollectionChanged cleans up its containers which in turn
// tries to unlock a source index which isn't locked at all (since it was cleared when the virtual item book reseted).
m_lockCount = 0;
return false;
}
// Returns True if the page just became unlocked (and is up for removal) or False if the call simply decremented the lock count.
return m_lockCount == 0;
}
internal void AbortQueryDataOperation()
{
Debug.Assert( !this.IsDisposed );
if( this.IsFilled )
throw new InvalidOperationException( "An attempt was made to abort a query that has already completed." );
if( m_asyncQueryInfo != null )
{
// This method can be reentered by another thread, while it's already being processed, with the result that the AbortQuery delegate may not be trigged by the CollectionView,
// and hence the client code not prevented it must abort the query/operation/connection.
lock( this )
{
if( this.IsAborting )
return;
this.IsAborting = true;
}
m_asyncQueryInfo.AbortQuery();
}
}
internal void QueueQueryData( Dispatcher dispatcher )
{
Debug.Assert( !this.IsDisposed );
Debug.Assert( m_asyncQueryInfo == null );
m_asyncQueryInfo = new AsyncQueryInfo(
dispatcher,
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_BeginQueryItems ),
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_AbortQueryItems ),
new Action<AsyncQueryInfo, object[]>( this.AsyncQueryInfo_EndQueryItems ),
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_QueryErrorChanged ),
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_BuiltInAbort ),
m_startDataIndex,
this.Count );
m_asyncQueryInfo.QueueQuery();
}
internal void EndQueryItems( AsyncQueryInfo asyncQueryInfo, object[] items )
{
Debug.Assert( !this.IsDisposed );
// This can occur when the user notify us that the QueryData is completed for an AsyncQueryInfo.StartIndex that refers to a Page which does exists
// but that was removed, then re-created thus creating another asyncQueryInfo and queuing another QueryData.
// The only way to get rid of this situation would be to keep a ref to the queued asyncQueryInfo even if we get rid of the page and re-link the same instance to the newly
// created page. This optimization could be done in a future version. For now, let's return and the second asyncQueryInfo will take care of filling the newly created page.
if( m_asyncQueryInfo != asyncQueryInfo )
{
Debug.Assert( false );
return;
}
if( this.IsFilled )
throw new InvalidOperationException( "An attempt was made to fill a virtual page that is already filled." );
if( items == null )
throw new ArgumentNullException( "items" );
for( int i = 0; i < items.Length; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = this[ i ];
Debug.Assert( virtualizedItemInfo.DataItem is EmptyDataItem );
Debug.Assert( virtualizedItemInfo.Index == ( m_startDataIndex + i ) );
this[ i ].DataItem = items[ i ];
}
this.IsFilled = true;
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Page Filled - " + this.ToString() );
}
internal void QueueCommitData( Dispatcher dispatcher )
{
Debug.Assert( !this.IsDisposed );
int count = this.Count;
List<VirtualizedItemInfo> dirtyItemInfoNotAlreadyPendingCommit = new List<VirtualizedItemInfo>( count );
for( int i = 0; i < count; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = this[ i ];
if( ( virtualizedItemInfo.IsDirty ) && ( !this.IsAsyncCommitInfoQueuedForItem( virtualizedItemInfo.DataItem ) ) )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "QueueCommitData for page " + this.ToString() + " and index " + virtualizedItemInfo.Index );
dirtyItemInfoNotAlreadyPendingCommit.Add( virtualizedItemInfo );
}
}
if( dirtyItemInfoNotAlreadyPendingCommit.Count > 0 )
{
AsyncCommitInfo asyncCommitInfo = new AsyncCommitInfo(
dispatcher,
new Action<AsyncCommitInfo>( this.AsyncCommitInfo_BeginCommitItems ),
new Action<AsyncCommitInfo>( this.AsyncCommitInfo_EndCommitItems ),
new Action<AsyncCommitInfo>( this.AsyncCommitInfo_CommitErrorChanged ),
dirtyItemInfoNotAlreadyPendingCommit.ToArray() );
m_asyncCommitInfoList.Add( asyncCommitInfo );
asyncCommitInfo.BeginCommit();
}
}
internal bool IsAsyncCommitInfoQueuedForItem( object item )
{
int pendingAsyncCommitInfoCount = m_asyncCommitInfoList.Count;
for( int i = 0; i < pendingAsyncCommitInfoCount; i++ )
{
VirtualizedItemInfo[] pendingCommitVirtualizedItemInfos = m_asyncCommitInfoList[ i ].VirtualizedItemInfos;
foreach( VirtualizedItemInfo pendingCommitVirtualizedItemInfo in pendingCommitVirtualizedItemInfos )
{
if( pendingCommitVirtualizedItemInfo.DataItem == item )
return true;
}
}
return false;
}
internal void EndCommitItems( AsyncCommitInfo asyncCommitInfo )
{
Debug.Assert( !this.IsDisposed );
Debug.Assert( m_asyncCommitInfoList.Contains( asyncCommitInfo ) );
VirtualizedItemInfo[] commitedItemInfos = asyncCommitInfo.VirtualizedItemInfos;
for( int i = 0; i < commitedItemInfos.Length; i++ )
{
commitedItemInfos[ i ].OldValues = null;
}
m_asyncCommitInfoList.Remove( asyncCommitInfo );
asyncCommitInfo.Dispose();
}
internal void Restart()
{
if( !this.IsRestarting )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Restart VirtualPage requested for " + this.ToString() );
this.IsRestarting = true;
this.ParentVirtualList.OnVirtualPageRestarting( this );
}
// The page has finished commiting or aborting
if( ( !this.IsCommitPending ) && ( !this.IsAborting ) )
{
this.EndRestart();
}
}
internal void EndRestart()
{
// VirtualPage will be disposed by the VirtualPageManager when it removes the page from is m_pageNodeList
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Restart VirtualPage completed for " + this.ToString() );
this.IsRestarting = false;
this.ParentVirtualList.OnVirtualPageRestarted( this );
}
private void AsyncQueryInfo_BuiltInAbort( AsyncQueryInfo queryInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnBuiltInAbort( this, queryInfo );
this.IsAborting = false;
}
private void AsyncQueryInfo_BeginQueryItems( AsyncQueryInfo queryInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnQueryItems( this, queryInfo );
}
private void AsyncQueryInfo_AbortQueryItems( AsyncQueryInfo queryInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnAbortQueryItems( this, queryInfo );
this.IsAborting = false;
// If the page was removed, it was also disposed. This case means the page was not restarting
if( !this.RemoveAfterOperation && this.ParentVirtualList.IsRestarting )
{
this.Restart();
}
}
private void AsyncQueryInfo_EndQueryItems( AsyncQueryInfo queryInfo, object[] fetchedItems )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
Debug.Assert( !this.IsAborting );
// The page can be removed when the CollectionView raises a CollectionChanged and the selection is consequently updated, so make sure to lock it until the update operation is done.
this.LockPage();
this.ParentVirtualList.PagingManager.OnQueryItemsCompleted( this, queryInfo, fetchedItems );
this.UnlockPage();
if( this.ParentVirtualList.IsRestarting )
{
this.Restart();
}
}
private void AsyncQueryInfo_QueryErrorChanged( AsyncQueryInfo queryInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnQueryErrorChanged( this, queryInfo );
if( this.ParentVirtualList.IsRestarting )
{
this.Restart();
}
}
private void AsyncCommitInfo_BeginCommitItems( AsyncCommitInfo commitInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnCommitItems( this, commitInfo );
}
private void AsyncCommitInfo_EndCommitItems( AsyncCommitInfo commitInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnCommitItemsCompleted( this, commitInfo );
// Make sure the page has not been removed by the previous call before accessing the parent virtual list.
if( !this.IsDisposed && this.ParentVirtualList.IsRestarting )
{
this.Restart();
}
}
private void AsyncCommitInfo_CommitErrorChanged( AsyncCommitInfo commitInfo )
{
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnCommitErrorChanged( this, commitInfo );
if( this.ParentVirtualList.IsRestarting )
{
this.Restart();
}
}
private int SourceIndexToPageEntryIndex( int sourceIndex )
{
if( ( this.Count != 0 ) && ( ( sourceIndex >= m_startDataIndex ) && ( sourceIndex <= this.EndDataIndex ) ) )
return sourceIndex - m_startDataIndex;
return -1;
}
private bool ContainsItem( object item )
{
int count = this.Count;
for( int i = 0; i < count; i++ )
{
if( this[ i ].DataItem == item )
return true;
}
return false;
}
#region IDisposable Members
public void Dispose()
{
Debug.Assert( !this.IsDisposed );
Debug.Assert( ( m_asyncCommitInfoList != null ) && ( m_asyncCommitInfoList.Count == 0 ), "Some async commit are not completed while disposing VirtualPage" );
if( m_asyncQueryInfo != null )
{
// We must dispose the AsyncQueryInfo to be sure it does not root this VirtualPage instance
m_asyncQueryInfo.Dispose();
m_asyncQueryInfo = null;
}
this.Clear();
m_parentVirtualList = null;
this.IsDisposed = true;
}
#endregion
private BitVector32 m_flags;
private int m_startDataIndex;
private int m_lockCount;
private VirtualList m_parentVirtualList;
public AsyncQueryInfo m_asyncQueryInfo;
private List<AsyncCommitInfo> m_asyncCommitInfoList;
[Flags]
private enum VirtualItemPageFlags
{
IsFilled = 1,
IsDisposed = 2,
}
}
}

817
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPageManager.cs

@ -1,817 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
internal abstract class VirtualPageManager : IDisposable
{
internal static bool DebugDataVirtualization = false;
private const DispatcherPriority CommitDataPriority = DispatcherPriority.Input;
private const int EstimatedLockedPageCount = 3;
public VirtualPageManager( Dispatcher dispatcher, int pageSize, int maxRealizedItemCount, double preemptivePageQueryRatio )
{
if( dispatcher == null )
throw new ArgumentNullException( "dispatcher" );
if( pageSize < 1 )
throw new ArgumentOutOfRangeException( "pageSize", pageSize, "pageSize must be greater than zero." );
if( maxRealizedItemCount < pageSize )
throw new ArgumentOutOfRangeException( "maxRealizedItemCount", maxRealizedItemCount, "maxRealizedItemCount must be greater than or equal to pageSize." );
m_managedLists = new List<VirtualList>();
m_pageNodes = new LinkedList<VirtualPage>();
this.Dispatcher = dispatcher;
m_pageSize = pageSize;
m_maxRealizedItemCount = maxRealizedItemCount;
m_maxRemovablePageCount = ( m_maxRealizedItemCount / m_pageSize );
m_preemptivePageQueryRatio = preemptivePageQueryRatio;
this.IsConnected = true;
}
#region Dispatcher Property
public Dispatcher Dispatcher
{
get;
private set;
}
#endregion
#region PageSize Property
public int PageSize
{
get
{
return m_pageSize;
}
}
#endregion
#region MaxRealizedItemCount Property
public int MaxRealizedItemCount
{
get
{
return m_maxRealizedItemCount;
}
}
#endregion
#region PreemptivePageQueryRatio Property
public double PreemptivePageQueryRatio
{
get
{
return m_preemptivePageQueryRatio;
}
set
{
m_preemptivePageQueryRatio = value;
}
}
#endregion
#region ManagedLists Property
public ReadOnlyCollection<VirtualList> ManagedLists
{
get
{
if( m_readOnlyManagedLists == null )
{
m_readOnlyManagedLists = new ReadOnlyCollection<VirtualList>( m_managedLists );
}
return m_readOnlyManagedLists;
}
}
#endregion
#region IsDisposed Property
protected bool IsDisposed
{
get
{
return m_flags[ ( int )VirtualPageManagerFlags.IsDisposed ];
}
private set
{
m_flags[ ( int )VirtualPageManagerFlags.IsDisposed ] = value;
}
}
#endregion
#region EstimatedTotalPageCount Property
internal int EstimatedTotalPageCount
{
get
{
return m_maxRemovablePageCount + VirtualPageManager.EstimatedLockedPageCount;
}
}
#endregion
#region Version Property
internal int Version
{
get
{
return m_version;
}
}
#endregion
#region IsConnected Property
internal bool IsConnected
{
get
{
return m_flags[ ( int )VirtualPageManagerFlags.IsConnected ];
}
private set
{
m_flags[ ( int )VirtualPageManagerFlags.IsConnected ] = value;
}
}
#endregion
#region RestartingManager Property
private bool RestartingManager
{
get
{
return m_flags[ ( int )VirtualPageManagerFlags.RestartingManager ];
}
set
{
m_flags[ ( int )VirtualPageManagerFlags.RestartingManager ] = value;
}
}
#endregion
#region ShouldRefreshAfterRestart Property
private bool ShouldRefreshAfterRestart
{
get
{
return m_flags[ ( int )VirtualPageManagerFlags.ShouldRefreshAfterRestart ];
}
set
{
m_flags[ ( int )VirtualPageManagerFlags.ShouldRefreshAfterRestart ] = value;
}
}
#endregion
#region LastRemovable Property
private LinkedListNode<VirtualPage> LastRemovable
{
get
{
LinkedListNode<VirtualPage> lastRemovableNode = m_pageNodes.Last;
while( lastRemovableNode != null )
{
Debug.Assert( lastRemovableNode.Value != null );
VirtualPage page = lastRemovableNode.Value;
if( page.IsRemovable )
return lastRemovableNode;
lastRemovableNode = lastRemovableNode.Previous;
}
return lastRemovableNode;
}
}
#endregion
protected abstract int OnQueryItemCountCore( VirtualList virtualList );
protected virtual void OnVirtualPageManagerRestarting()
{
}
protected virtual void OnVirtualPageManagerRestarted( bool shouldRefresh )
{
}
protected virtual void EndRestart()
{
this.RestartingManager = false;
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "VirtualPageManager (" + this.GetHashCode() + ")- All virtual Lists restarted." );
this.OnVirtualPageManagerRestarted( this.ShouldRefreshAfterRestart );
this.ShouldRefreshAfterRestart = false;
}
protected internal abstract void OnBuiltInAbort( VirtualPage virtualPage, AsyncQueryInfo queryInfo );
protected internal virtual int OnQueryItemCount( VirtualList virtualList )
{
return this.OnQueryItemCountCore( virtualList );
}
protected internal abstract void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo );
protected internal virtual void OnAbortQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
{
}
protected internal virtual void OnQueryItemsCompleted( VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems )
{
this.IncrementVersion();
page.ParentVirtualList.FillEmptyPage( queryInfo, fetchedItems );
}
protected internal virtual void OnCommitItems( VirtualPage page, AsyncCommitInfo commitInfo )
{
}
protected internal virtual void OnCommitItemsCompleted( VirtualPage page, AsyncCommitInfo commitInfo )
{
page.ParentVirtualList.NotifyCommitComplete( commitInfo );
}
protected internal virtual void OnQueryErrorChanged( VirtualPage page, AsyncQueryInfo queryInfo )
{
}
protected internal virtual void OnCommitErrorChanged( VirtualPage page, AsyncCommitInfo commitInfo )
{
}
internal virtual void OnVirtualListRestarting( VirtualList virtualList )
{
Debug.Assert( m_managedLists.Contains( virtualList ) );
Debug.Assert( this.RestartingManager, "Until CollectionViewGroups can be virtualized, we should not be restarting a leaf list on its own." );
}
internal virtual void OnVirtualListRestarted( VirtualList virtualList )
{
Debug.Assert( m_managedLists.Contains( virtualList ) );
Debug.Assert( this.RestartingManager, "Until CollectionViewGroups can be virtualized, we should not be restarting a leaf list on its own." );
if( this.RestartingManager )
{
m_restartingListsCount--;
}
// Make sure that no page nodes belonging to this virtual list are left in the linked list. Remove all remaining ones since after the manager is restarted, its content is completely cleared.
LinkedListNode<VirtualPage> pageNode = m_pageNodes.Last;
while( pageNode != null )
{
LinkedListNode<VirtualPage> previousNode = pageNode.Previous;
if( pageNode.Value.ParentVirtualList == virtualList )
throw new DataGridInternalException( "A VirtualPage was not remove from its parent VirtualList after it is restarted" );
pageNode = previousNode;
}
this.IncrementVersion();
// If the manager is restarting, no page left and no more list restarting
if( this.RestartingManager && ( m_pageNodes.Count == 0 ) && ( m_restartingListsCount == 0 ) )
{
this.EndRestart();
}
}
internal virtual void OnVirtualListPageRestarting( VirtualList virtualList, VirtualPage page )
{
Debug.Assert( m_managedLists.Contains( virtualList ) );
LinkedListNode<VirtualPage> pageNode = m_pageNodes.Find( page );
Debug.Assert( pageNode != null );
// RemovePageNode takes care of either raising the AbortQueryData event or aborting the QueryData Dispatcher Operation altogether.
// It also takes care of raising the CommitVirtualData event for loaded pages which contains modified data.
this.QueueCommitDataOrAbortIfRequired( pageNode, false );
}
internal virtual void OnVirtualListPageRestarted( VirtualList virtualList, VirtualPage page )
{
Debug.Assert( m_managedLists.Contains( virtualList ) );
Debug.Assert( m_pageNodes.Contains( page ) );
this.RemovePage( page );
}
internal void QueueQueryData( VirtualPage page )
{
Debug.Assert( m_managedLists.Contains( page.ParentVirtualList ) );
page.QueueQueryData( this.Dispatcher );
}
internal void QueueCommitData( VirtualPage page )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "QueueCommitData for page " + page.ToString() );
Debug.Assert( m_managedLists.Contains( page.ParentVirtualList ) );
Debug.Assert( page.IsFilled );
Debug.Assert( page.IsDirty );
if( this.RestartingManager )
{
this.ShouldRefreshAfterRestart = true;
}
page.QueueCommitData( this.Dispatcher );
}
internal List<LinkedListNode<VirtualPage>> GetUnlockedPendingFillNodes()
{
List<LinkedListNode<VirtualPage>> unlockedPendingFillNodes = new List<LinkedListNode<VirtualPage>>();
LinkedListNode<VirtualPage> lastUnlockedPendingFillNode = m_pageNodes.Last;
while( lastUnlockedPendingFillNode != null )
{
VirtualPage page = lastUnlockedPendingFillNode.Value;
Debug.Assert( page != null );
if( ( !page.IsLocked ) && ( !page.IsFilled ) )
{
unlockedPendingFillNodes.Add( lastUnlockedPendingFillNode );
}
lastUnlockedPendingFillNode = lastUnlockedPendingFillNode.Previous;
}
return unlockedPendingFillNodes;
}
internal void CleanUpAndDisposeUnused()
{
// Remove the less used unlocked pages. This will also ask to save it.
// Also remove all pending fill pages which are not locked wether or not we are under the max unlocked page count.
// This is so the abort query event is raised so that the user can abort his fetching of data.
// Start with the unlocked pending fill pages since it is mandatory to remove them all in order to abort the async data fetching.
// The first node in the list returned by the GetUnlockedPendingFillNodes method is the oldest one, so we can start removing from the beginning of the returned list.
List<LinkedListNode<VirtualPage>> unlockedPendingFillNodes = this.GetUnlockedPendingFillNodes();
int unlockedPendingFillCount = unlockedPendingFillNodes.Count;
for( int i = 0; i < unlockedPendingFillCount; i++ )
{
this.QueueCommitDataOrAbortIfRequired( unlockedPendingFillNodes[ i ], true );
}
// Then, move on to removing the other unlocked pages not up for commit, if we are above the max item in memory limit. There should not be any pending fill pages left which are not locked.
int removablePageItemCount = this.GetRemovablePageItemCount();
while( removablePageItemCount > m_maxRealizedItemCount )
{
LinkedListNode<VirtualPage> lastRemovable = this.LastRemovable;
Debug.Assert( lastRemovable != null );
removablePageItemCount -= lastRemovable.Value.Count;
this.QueueCommitDataOrAbortIfRequired( lastRemovable, true );
}
}
internal void RemovePage( VirtualPage page )
{
if( page.IsDisposed )
return;
Debug.Assert( page != null );
Debug.Assert( !page.IsDirty );
// A filled page is being removed. Change the version.
this.IncrementVersion();
// Update the table of content of the page's ParentVirtualList
page.ParentVirtualList.TableOfContent.RemovePage( page );
m_pageNodes.Remove( page );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Removed Page: " + page.ToString() );
// Dispose the page since it will never be reused
page.Dispose();
}
internal void MovePageToFront( VirtualPage page )
{
// The further from the front a page is, the longer it has been since it was requested.
Debug.Assert( page != null );
LinkedListNode<VirtualPage> firstNode = m_pageNodes.First;
if( firstNode.Value != page )
{
LinkedListNode<VirtualPage> node = m_pageNodes.Find( page );
m_pageNodes.Remove( node );
m_pageNodes.AddFirst( node );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Moved To Front: Page " + page.ToString() );
}
}
internal void AddPage( VirtualPage page, PageInsertPosition insertPosition )
{
if( page == null )
throw new ArgumentNullException( "page", "TODOOC: An internal error occured while paging data. Page cannot be null." );
// We call clean-up before the call to AddFirst since if we do it afterward and the page is pending fill, we will remove it.
this.CleanUpAndDisposeUnused();
if( insertPosition == PageInsertPosition.Front )
{
m_pageNodes.AddFirst( page );
}
else
{
m_pageNodes.AddLast( page );
}
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Added To " + ( ( insertPosition == PageInsertPosition.Front ) ? "Front" : "Back" ) + ": Page " + page.ToString() );
}
internal void Restart()
{
if( this.RestartingManager )
return;
this.RestartingManager = true;
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "VirtualPageManager (" + this.GetHashCode() + ") - Restarting all virtual Lists. " );
this.OnVirtualPageManagerRestarting();
if( m_managedLists.Count == 0 )
{
// No pages, restart is completed
this.EndRestart();
}
else
{
m_restartingListsCount = m_managedLists.Count;
int managedListCount = m_managedLists.Count;
// Restart all VirtualLists
for( int i = managedListCount - 1; i >= 0; i-- )
{
VirtualList virtualList = m_managedLists[ i ];
virtualList.Restart();
}
}
}
internal void Disconnect()
{
this.IsConnected = false;
}
internal void ManageList( VirtualList virtualList )
{
Debug.Assert( !m_managedLists.Contains( virtualList ) );
Debug.Assert( virtualList.VirtualPagingManager == null );
virtualList.VirtualPagingManager = this;
this.m_managedLists.Add( virtualList );
}
internal bool IsAsyncCommitQueuedForItem( object item )
{
LinkedListNode<VirtualPage> pageNode = m_pageNodes.First;
while( pageNode != null )
{
VirtualList virtualList = pageNode.Value.ParentVirtualList;
Debug.Assert( m_managedLists.Contains( virtualList ) );
if( virtualList.IsAsyncCommitQueuedForItem( item ) )
{
Debug.Assert( !( item is EmptyDataItem ), "A commit operation should not have been queued for an EmptyDataItem." );
return true;
}
pageNode = pageNode.Next;
}
return false;
}
internal bool IsItemDirty( object item )
{
LinkedListNode<VirtualPage> pageNode = m_pageNodes.First;
while( pageNode != null )
{
VirtualList virtualList = pageNode.Value.ParentVirtualList;
Debug.Assert( m_managedLists.Contains( virtualList ) );
if( virtualList.IsItemDirty( item ) )
{
Debug.Assert( !( item is EmptyDataItem ), "An EmptyDataItem should not have been flagged as dirty." );
return true;
}
pageNode = pageNode.Next;
}
return false;
}
internal void SetCachedValuesForItem( object item, string[] names, object[] values )
{
LinkedListNode<VirtualPage> pageNode = m_pageNodes.First;
while( pageNode != null )
{
VirtualList virtualList = pageNode.Value.ParentVirtualList;
Debug.Assert( m_managedLists.Contains( virtualList ) );
int localIndex = virtualList.IndexOf( item );
if( localIndex != -1 )
{
virtualList.SetCachedValuesForItemAtIndex( localIndex, names, values );
return;
}
pageNode = pageNode.Next;
}
throw new InvalidOperationException( "An attempt was made to begin the edit process on an unknown item." );
}
internal VirtualizedItemValueCollection GetCachedValuesForItem( object item )
{
LinkedListNode<VirtualPage> pageNode = m_pageNodes.First;
while( pageNode != null )
{
VirtualList virtualList = pageNode.Value.ParentVirtualList;
Debug.Assert( m_managedLists.Contains( virtualList ) );
int localIndex = virtualList.IndexOf( item );
if( localIndex != -1 )
return virtualList.GetCachedValuesForItemAtIndex( localIndex );
pageNode = pageNode.Next;
}
return null;
}
internal void ClearCachedValuesForItem( object item )
{
LinkedListNode<VirtualPage> pageNode = m_pageNodes.First;
while( pageNode != null )
{
VirtualList virtualList = pageNode.Value.ParentVirtualList;
Debug.Assert( m_managedLists.Contains( virtualList ) );
int localIndex = virtualList.IndexOf( item );
if( localIndex != -1 )
{
virtualList.ClearCachedValuesForItemAtIndex( localIndex );
return;
}
pageNode = pageNode.Next;
}
throw new InvalidOperationException( "An attempt was made to leave the edit process on an unknown item." );
}
internal void CommitAll()
{
List<VirtualList> currentVirtualLists = new List<VirtualList>( m_pageNodes.Count );
LinkedListNode<VirtualPage> pageNode = m_pageNodes.First;
// Scan all in memory pages to build a list of unique VirtualLists which currently have items loaded in memory.
while( pageNode != null )
{
VirtualList virtualList = pageNode.Value.ParentVirtualList;
Debug.Assert( m_managedLists.Contains( virtualList ) );
if( !currentVirtualLists.Contains( virtualList ) )
{
currentVirtualLists.Add( virtualList );
}
pageNode = pageNode.Next;
}
int currentVirtualListCount = currentVirtualLists.Count;
for( int i = 0; i < currentVirtualListCount; i++ )
{
currentVirtualLists[ i ].CommitAll();
}
}
private int GetRemovablePageCount()
{
int removablePageCount = 0;
LinkedListNode<VirtualPage> pageNode = m_pageNodes.Last;
while( pageNode != null )
{
VirtualPage page = pageNode.Value;
Debug.Assert( page != null );
if( ( page != null ) && ( page.IsRemovable ) )
{
removablePageCount++;
}
pageNode = pageNode.Previous;
}
return removablePageCount;
}
private int GetRemovablePageItemCount()
{
int removablePageItemCount = 0;
LinkedListNode<VirtualPage> pageNode = m_pageNodes.Last;
while( pageNode != null )
{
VirtualPage page = pageNode.Value;
Debug.Assert( page != null );
if( ( page != null ) && ( page.IsRemovable ) )
{
removablePageItemCount += page.Count;
}
pageNode = pageNode.Previous;
}
return removablePageItemCount;
}
private void QueueCommitDataOrAbortIfRequired( LinkedListNode<VirtualPage> pageNode, bool removeAfterOperation )
{
VirtualPage page = pageNode.Value;
// Update the flag in case this page must be removed after an abort or commit operation
page.RemoveAfterOperation = removeAfterOperation;
// The only circumstance when we should remove a page which is not removable is if we are restarting.
Debug.Assert( ( page != null ) && ( !page.IsDisposed ) && ( ( page.IsRemovable ) || ( page.ParentVirtualList.IsRestarting ) ) );
if( page.IsDirty )
{
// Don't remove pages which contains modifications. We'll remove them from the book when they are committed, if they aren't locked.
this.QueueCommitData( page );
}
else if( !page.IsFilled )
{
// The page is not filled, we must send abort the QueryData for this page in case it was sent
page.AbortQueryDataOperation();
}
// The page must be removed after operation and it has nothing to commit and is not currently aborting an operation. It is safe to remove it
if( removeAfterOperation && !page.IsCommitPending && !page.IsAborting )
{
this.RemovePage( page );
}
}
private void IncrementVersion()
{
unchecked
{
m_version++;
}
}
#region IDisposable Members
public void Dispose()
{
this.DisposeCore();
}
protected virtual void DisposeCore()
{
if( m_managedLists != null )
{
m_managedLists.Clear();
}
if( m_pageNodes != null )
{
m_pageNodes.Clear();
}
this.IsDisposed = true;
}
#endregion
private int m_version;
private int m_restartingListsCount;
private BitVector32 m_flags = new BitVector32();
private LinkedList<VirtualPage> m_pageNodes;
private List<VirtualList> m_managedLists;
private ReadOnlyCollection<VirtualList> m_readOnlyManagedLists;
private int m_pageSize;
private int m_maxRealizedItemCount;
private double m_preemptivePageQueryRatio;
private int m_maxRemovablePageCount;
internal enum PageInsertPosition
{
Front = 0,
Back = 1
}
private enum VirtualPageManagerFlags
{
RestartingManager = 1,
ShouldRefreshAfterRestart = 2,
IsDisposed = 4,
IsConnected = 8,
}
}
}

100
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualizedItemInfo.cs

@ -1,100 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class VirtualizedItemInfo
{
#region CONSTRUCTORS
internal VirtualizedItemInfo( int index, object dataItem )
{
m_dataIndex = index;
m_dataItem = dataItem;
}
#endregion CONSTRUCTORS
#region DataItem Property
public object DataItem
{
get
{
return m_dataItem;
}
internal set
{
m_dataItem = value;
}
}
#endregion DataItem Property
#region Index Property
public int Index
{
get
{
return m_dataIndex;
}
}
#endregion Index Property
#region OldValues Property
public VirtualizedItemValueCollection OldValues
{
get
{
return m_oldValues;
}
internal set
{
m_oldValues = value;
}
}
#endregion OldValues Property
#region INTERNAL PROPERTIES
internal bool IsDirty
{
get
{
return m_oldValues != null;
}
}
#endregion INTERNAL PROPERTIES
#region PRIVATE FIELDS
private object m_dataItem;
private int m_dataIndex;
private VirtualizedItemValueCollection m_oldValues;
#endregion PRIVATE FIELDS
}
}

153
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualizedItemValueCollection.cs

@ -1,153 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Xceed.Wpf.DataGrid
{
public class VirtualizedItemValueCollection : ICollection
{
internal VirtualizedItemValueCollection( string[] names, object[] values )
{
if( names.Length != values.Length )
throw new ArgumentException( "Names and Values must be of the same length." );
m_nameValueDictionary = new Dictionary<string, object>( names.Length );
m_valueList = new List<object>( values.Length );
for( int i = 0; i < names.Length; i++ )
{
object value = values[ i ];
m_nameValueDictionary.Add( names[ i ], value );
m_valueList.Add( value );
}
}
public object this[ int index ]
{
get
{
if( ( index < 0 ) || ( index >= m_valueList.Count ) )
throw new ArgumentOutOfRangeException( "index", index, "The index must be greater than or equal to zero and less than count." );
return m_valueList[ index ];
}
}
public object this[ string name ]
{
get
{
if( name == null )
throw new ArgumentNullException( "name" );
if( name == string.Empty )
throw new ArgumentException( "name" );
object val;
if( !m_nameValueDictionary.TryGetValue( name, out val ) )
throw new ArgumentException( "No value could be found for the specified property name." );
return val;
}
}
public int Count
{
get
{
return m_valueList.Count;
}
}
#region PRIVATE FIELDS
private Dictionary<string, object> m_nameValueDictionary;
private List<object> m_valueList;
#endregion PRIVATE FIELDS
#region ICollection Members
public void CopyTo( Array array, int index )
{
if( array == null )
throw new ArgumentNullException( "array" );
if( array.Rank != 1 )
throw new NotSupportedException( "Multi-dimensional arrays are not supported." );
if( index < 0 )
throw new ArgumentOutOfRangeException( "index", index, "index must be greater than or equal to zero." );
int count = this.Count;
if( ( array.Length - index ) < count )
throw new ArgumentException( "Invalid offset position." );
if( array is object[] )
{
object[] objects = ( object[] )array;
for( int i = 0; i < count; i++ )
{
objects[ i + index ] = m_valueList[ i ];
}
}
else
{
for( int i = 0; i < count; i++ )
{
array.SetValue( m_valueList[ i ], ( i + index ) );
}
}
}
public bool IsSynchronized
{
get
{
return false;
}
}
public object SyncRoot
{
get
{
return this;
}
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return m_valueList.GetEnumerator();
}
#endregion
}
}

226
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(ForeignKeys)/DataGridForeignKeyDescription.cs

@ -1,226 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Data;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
public class DataGridForeignKeyDescription : DependencyObject
{
public DataGridForeignKeyDescription()
{
this.SetForeignKeyConverter();
}
#region ForeignKeyConverter Property
public static readonly DependencyProperty ForeignKeyConverterProperty = DependencyProperty.Register(
"ForeignKeyConverter",
typeof( ForeignKeyConverter ),
typeof( DataGridForeignKeyDescription ),
new FrameworkPropertyMetadata( null ) );
public ForeignKeyConverter ForeignKeyConverter
{
get
{
return ( ForeignKeyConverter )this.GetValue( DataGridForeignKeyDescription.ForeignKeyConverterProperty );
}
set
{
this.SetValue( DataGridForeignKeyDescription.ForeignKeyConverterProperty, value );
}
}
#endregion
#region ItemsSource Property
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
"ItemsSource",
typeof( IEnumerable ),
typeof( DataGridForeignKeyDescription ),
new FrameworkPropertyMetadata( null ) );
public IEnumerable ItemsSource
{
get
{
return ( IEnumerable )this.GetValue( DataGridForeignKeyDescription.ItemsSourceProperty );
}
set
{
this.SetValue( DataGridForeignKeyDescription.ItemsSourceProperty, value );
}
}
#endregion
#region IsAutoCreated Internal Property
internal bool IsAutoCreated
{
get;
set;
}
#endregion
#region ValuePath Property
public static readonly DependencyProperty ValuePathProperty = DependencyProperty.Register(
"ValuePath",
typeof( string ),
typeof( DataGridForeignKeyDescription ),
new FrameworkPropertyMetadata( null ) );
public string ValuePath
{
get
{
return ( string )this.GetValue( DataGridForeignKeyDescription.ValuePathProperty );
}
set
{
this.SetValue( DataGridForeignKeyDescription.ValuePathProperty, value );
}
}
#endregion
#region DisplayMemberPath Property
public static readonly DependencyProperty DisplayMemberPathProperty = DependencyProperty.Register(
"DisplayMemberPath",
typeof( string ),
typeof( DataGridForeignKeyDescription ),
new FrameworkPropertyMetadata( null ) );
public string DisplayMemberPath
{
get
{
return ( string )this.GetValue( DataGridForeignKeyDescription.DisplayMemberPathProperty );
}
set
{
this.SetValue( DataGridForeignKeyDescription.DisplayMemberPathProperty, value );
}
}
#endregion
protected virtual void SetForeignKeyConverter()
{
this.ForeignKeyConverter = new DataGridForeignKeyConverter();
}
internal Type GetDataType()
{
var itemsSource = this.ItemsSource;
if( itemsSource == null )
return null;
var displayMemberPath = this.DisplayMemberPath;
var foreignKeyConverter = this.ForeignKeyConverter;
if( string.IsNullOrWhiteSpace( displayMemberPath ) && ( foreignKeyConverter == null ) )
return null;
try
{
//Use the DisplayMemberPath or the ForeignKeyConverter to find the converted value data type, using a DataRowView or reflection.
if( ( itemsSource is DataView ) || ( itemsSource is DataTable ) )
{
foreach( object item in itemsSource )
{
var dataRowView = item as DataRowView;
if( dataRowView == null )
continue;
if( !string.IsNullOrWhiteSpace( displayMemberPath ) )
{
var dataColumn = dataRowView.Row.Table.Columns[ displayMemberPath ];
if( dataColumn != null )
{
return dataColumn.DataType;
}
}
else
{
var valuePath = this.ValuePath;
if( valuePath != null )
{
var key = dataRowView[ valuePath ];
var value = foreignKeyConverter.GetValueFromKey( key, this );
if( value != null )
{
return value.GetType();
}
}
}
}
}
else
{
foreach( object item in itemsSource )
{
if( item == null )
continue;
if( !string.IsNullOrWhiteSpace( displayMemberPath ) )
return item.GetType().GetProperty( displayMemberPath ).PropertyType;
if( item is Enum )
return item.GetType();
var valuePath = this.ValuePath;
if( valuePath != null )
{
var key = item.GetType().GetProperty( valuePath ).GetValue( item, null );
var value = foreignKeyConverter.GetValueFromKey( key, this );
if( value != null )
{
return value.GetType();
}
}
}
}
}
catch
{
//Swallow the exception, no need to terminate the application, since the original value will be exported.
}
return null;
}
internal object GetDisplayValue( object fieldValue )
{
if( fieldValue == null )
return null;
var foreignKeyConverter = this.ForeignKeyConverter;
if( foreignKeyConverter != null )
return foreignKeyConverter.GetValueFromKey( fieldValue, this );
return fieldValue;
}
}
}

113
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(ForeignKeys)/DataTableForeignKeyDescription.cs

@ -1,113 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Data;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
public class DataTableForeignKeyDescription : DataGridForeignKeyDescription
{
public DataTableForeignKeyDescription()
{
}
internal DataTableForeignKeyDescription( ForeignKeyConstraint constraint )
: this()
{
this.ForeignKeyConstraint = constraint;
}
#region ForeignKeyConstraint Property
public static readonly DependencyProperty ForeignKeyConstraintProperty = DependencyProperty.Register(
"ForeignKeyConstraint",
typeof( ForeignKeyConstraint ),
typeof( DataTableForeignKeyDescription ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( DataTableForeignKeyDescription.OnForeignKeyConstraintChanged ) ) );
public ForeignKeyConstraint ForeignKeyConstraint
{
get
{
return ( ForeignKeyConstraint )this.GetValue( DataTableForeignKeyDescription.ForeignKeyConstraintProperty );
}
set
{
this.SetValue( DataTableForeignKeyDescription.ForeignKeyConstraintProperty, value );
}
}
private static void OnForeignKeyConstraintChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
var foreignKeyDescription = sender as DataTableForeignKeyDescription;
if( foreignKeyDescription != null )
{
foreignKeyDescription.UpdateValuePath();
foreignKeyDescription.UpdateItemsSource();
}
}
#endregion
protected override void SetForeignKeyConverter()
{
this.ForeignKeyConverter = new DataTableForeignKeyConverter();
}
private void UpdateValuePath()
{
// Affect the ValuePath if it was not explicitly set or bound
var valuePath = this.ReadLocalValue( ValuePathProperty );
if( string.IsNullOrEmpty( this.ValuePath )
&& ( ( valuePath == DependencyProperty.UnsetValue )
|| ( valuePath == null ) ) )
{
var foreignKeyConstraint = this.ForeignKeyConstraint;
// Affect the FieldName to the first RelatedColumn's name
// if there is only one DataColumn in the RelatedColumns Collection
if( ( foreignKeyConstraint != null )
&& ( foreignKeyConstraint.RelatedColumns != null )
&& ( foreignKeyConstraint.RelatedColumns.Length == 1 ) )
{
var foreignFieldName = foreignKeyConstraint.RelatedColumns[ 0 ].ColumnName;
if( !string.IsNullOrEmpty( foreignFieldName ) )
{
this.ValuePath = foreignFieldName;
}
}
}
}
private void UpdateItemsSource()
{
var foreignKeyConstraint = this.ForeignKeyConstraint;
if( foreignKeyConstraint == null )
return;
var relatedTable = foreignKeyConstraint.RelatedTable;
if( relatedTable == null )
return;
this.ItemsSource = relatedTable.DefaultView;
}
}
}

187
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/AsyncCommitInfo.cs

@ -1,187 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
public class AsyncCommitInfo : IDisposable
{
#region STATIC MEMBERS
#endregion STATIC MEMBERS
#region CONSTRUCTORS
internal AsyncCommitInfo(
Dispatcher dispatcher,
Action<AsyncCommitInfo> beginCommitDelegate,
Action<AsyncCommitInfo> endCommitDelegate,
Action<AsyncCommitInfo> commitErrorChangedDelegate,
VirtualizedItemInfo[] virtualizedItemInfos )
{
m_dispatcher = dispatcher;
m_beginCommitDelegate = beginCommitDelegate;
m_endCommitDelegate = endCommitDelegate;
m_commitErrorChangedDelegate = commitErrorChangedDelegate;
m_virtualizedItemInfos = virtualizedItemInfos;
}
#endregion CONSTRUCTORS
#region Items Property
public VirtualizedItemInfo[] VirtualizedItemInfos
{
get
{
return m_virtualizedItemInfos;
}
}
#endregion Items Property
#region AsyncState Property
public object AsyncState
{
get;
set;
}
#endregion AsyncState Property
#region Error Property
public object Error
{
get
{
return m_error;
}
set
{
Debug.Assert( !this.IsDisposed );
if( m_error != value )
{
m_error = value;
if( m_commitErrorChangedDelegate != null )
{
m_dispatcher.Invoke(
DispatcherPriority.Send,
m_commitErrorChangedDelegate,
this );
}
}
}
}
#endregion Error Property
#region IsDisposed Internal Property
internal bool IsDisposed
{
get
{
return m_isDisposed;
}
}
#endregion
#region PUBLIC METHODS
public void EndCommit()
{
Debug.Assert( !this.IsDisposed );
if( m_commitEndedDispatched )
throw new InvalidOperationException( "An attempt was made to call EndCommit when it has already been called for this AsyncCommitInfo." );
m_dispatcher.BeginInvoke(
DispatcherPriority.Send,
m_endCommitDelegate,
this );
m_commitEndedDispatched = true;
}
#endregion PUBLIC METHODS
#region INTERNAL METHODS
internal void BeginCommit()
{
Debug.Assert( !this.IsDisposed );
m_dispatcher.BeginInvoke(
DispatcherPriority.Background,
m_beginCommitDelegate,
this );
}
#endregion INTERNAL METHODS
#region PRIVATE FIELDS
private VirtualizedItemInfo[] m_virtualizedItemInfos;
private bool m_commitEndedDispatched;
private bool m_isDisposed;
private object m_error;
private Dispatcher m_dispatcher;
private Action<AsyncCommitInfo> m_beginCommitDelegate;
private Action<AsyncCommitInfo> m_endCommitDelegate;
private Action<AsyncCommitInfo> m_commitErrorChangedDelegate;
#endregion PRIVATE FIELDS
#region IDisposable Members
public void Dispose()
{
if( m_isDisposed )
{
Debug.Assert( false, "The AsyncQueryInfo is disposed" );
return;
}
m_dispatcher = null;
m_beginCommitDelegate = null;
m_endCommitDelegate = null;
m_commitErrorChangedDelegate = null;
m_isDisposed = true;
}
#endregion
}
}

297
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/AsyncQueryInfo.cs

@ -1,297 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
public class AsyncQueryInfo : IDisposable
{
internal AsyncQueryInfo(
Dispatcher dispatcher,
Action<AsyncQueryInfo> beginQueryDelegate,
Action<AsyncQueryInfo> abortQueryDelegate,
Action<AsyncQueryInfo, object[]> endQueryDelegate,
Action<AsyncQueryInfo> queryErrorChangedDelegate,
Action<AsyncQueryInfo> builtInAbortDelegate,
int startIndex,
int requestedItemCount )
{
m_dispatcher = dispatcher;
m_builtInAbortDelegate = builtInAbortDelegate;
m_beginQueryDelegate = beginQueryDelegate;
m_abortQueryDelegate = abortQueryDelegate;
m_endQueryDelegate = endQueryDelegate;
m_queryErrorChangedDelegate = queryErrorChangedDelegate;
m_startIndex = startIndex;
m_requestedItemCount = requestedItemCount;
}
#region StartIndex Property
public int StartIndex
{
get
{
return m_startIndex;
}
}
#endregion
#region RequestedItemCount Property
public int RequestedItemCount
{
get
{
return m_requestedItemCount;
}
}
#endregion
#region AsyncState Property
public object AsyncState
{
get;
set;
}
#endregion
#region Error Property
public object Error
{
get
{
return m_error;
}
set
{
Debug.Assert( !this.IsDisposed );
if( m_error != value )
{
m_error = value;
if( m_queryErrorChangedDelegate != null )
{
m_dispatcher.Invoke( DispatcherPriority.Send, m_queryErrorChangedDelegate, this );
}
}
}
}
#endregion
#region ShouldAbort Property
public bool ShouldAbort
{
get
{
return m_flags[ ( int )AsyncQueryInfoFlags.ShouldAbort ];
}
private set
{
m_flags[ ( int )AsyncQueryInfoFlags.ShouldAbort ] = value;
}
}
#endregion
#region IsDisposed Property
internal bool IsDisposed
{
get
{
return m_flags[ ( int )AsyncQueryInfoFlags.IsDisposed ];
}
private set
{
m_flags[ ( int )AsyncQueryInfoFlags.IsDisposed ] = value;
}
}
#endregion
#region BeginQueryDelegateInvoked Property
private bool BeginQueryDelegateInvoked
{
get
{
return m_flags[ ( int )AsyncQueryInfoFlags.BeginQueryDelegateInvoked ];
}
set
{
m_flags[ ( int )AsyncQueryInfoFlags.BeginQueryDelegateInvoked ] = value;
}
}
#endregion
public void EndQuery( object[] items )
{
// Ignore this query when disposed
if( this.IsDisposed )
return;
if( m_endQueryDelegateDispatcherOperation != null )
throw new InvalidOperationException( "An attempt was made to call EndQuery when it has already been called for this AsyncQueryInfo." );
if( this.ShouldAbort )
return;
m_endQueryDelegateDispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.Background, m_endQueryDelegate, this, new object[] { items } );
}
internal void QueueQuery()
{
Debug.Assert( !this.IsDisposed, "The AsyncQueryInfo is disposed" );
this.ShouldAbort = false;
this.BeginQueryDelegateInvoked = false;
//Make sure to abort the EndQuery operation before queuing a new query.
if( m_endQueryDelegateDispatcherOperation != null )
{
m_endQueryDelegateDispatcherOperation.Abort();
m_endQueryDelegateDispatcherOperation = null;
}
#if SILVERLIGHT
m_dispatcher.BeginInvoke( new Action( this.BeginQuery ) );
#else
m_beginQueryDispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.Background, new Action( this.BeginQueryDispatcherCallback ) );
#endif
}
internal void AbortQuery()
{
Debug.Assert( !this.IsDisposed );
// Make sure to abort the EndQuery operation before queuing an abort query.
if( m_endQueryDelegateDispatcherOperation != null )
{
m_endQueryDelegateDispatcherOperation.Abort();
m_endQueryDelegateDispatcherOperation = null;
}
if( this.ShouldAbort )
{
Debug.Assert( m_beginQueryDispatcherOperation == null );
m_builtInAbortDelegate( this );
return;
}
this.ShouldAbort = true;
// If the BeginQuery already had time to execute, then we know the user was notified of the query request. Notify him to cancel the query as soon as possible.
if( this.BeginQueryDelegateInvoked )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "CALLING Abort Query! For page at starting index: " + m_startIndex.ToString() );
m_dispatcher.BeginInvoke( DispatcherPriority.Send, m_abortQueryDelegate, this );
}
else
{
// BeginQueryDispatcherCallback was dispatched but not executed yet, abort it and return
if( m_beginQueryDispatcherOperation != null )
{
m_beginQueryDispatcherOperation.Abort();
m_beginQueryDispatcherOperation = null;
}
m_builtInAbortDelegate( this );
}
}
private void BeginQueryDispatcherCallback()
{
m_beginQueryDispatcherOperation = null;
Debug.Assert( !this.IsDisposed );
if( this.ShouldAbort )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "BUILT-IN BeginQueryDispatcherCallback Aborted! (" + this.GetHashCode() + ") For page at starting index: " + m_startIndex.ToString() );
m_builtInAbortDelegate( this );
return;
}
m_beginQueryDelegate( this );
this.BeginQueryDelegateInvoked = true;
}
#region IDisposable Members
public void Dispose()
{
m_dispatcher = null;
Debug.Assert( m_beginQueryDispatcherOperation == null, "A BeginQueryDispatcherCallback is still pending on the Dispatcher" );
m_beginQueryDispatcherOperation = null;
m_builtInAbortDelegate = null;
m_abortQueryDelegate = null;
m_beginQueryDelegate = null;
m_endQueryDelegate = null;
m_queryErrorChangedDelegate = null;
this.IsDisposed = true;
}
#endregion
private int m_startIndex;
private int m_requestedItemCount;
private BitVector32 m_flags = new BitVector32();
private object m_error;
private Dispatcher m_dispatcher;
private DispatcherOperation m_beginQueryDispatcherOperation;
private DispatcherOperation m_endQueryDelegateDispatcherOperation;
private Action<AsyncQueryInfo> m_builtInAbortDelegate;
private Action<AsyncQueryInfo> m_beginQueryDelegate;
private Action<AsyncQueryInfo> m_abortQueryDelegate;
private Action<AsyncQueryInfo, object[]> m_endQueryDelegate;
private Action<AsyncQueryInfo> m_queryErrorChangedDelegate;
[Flags]
private enum AsyncQueryInfoFlags
{
ShouldAbort = 1,
EndQueryDelegateInvoked = 2,
BeginQueryDelegateInvoked = 4,
IsDisposed = 8,
}
}
}

53
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/AsyncQueryInfoWeakComparer.cs

@ -1,53 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
internal class AsyncQueryInfoWeakComparer : IEqualityComparer<AsyncQueryInfo>
{
#region IEqualityComparer<AsyncQueryInfo> Members
public bool Equals( AsyncQueryInfo x, AsyncQueryInfo y )
{
if( ( x == null ) && ( y == null ) )
return true;
if( ( x == null ) || ( y == null ) )
return false;
if( ( x.StartIndex == y.StartIndex ) && ( x.RequestedItemCount == y.RequestedItemCount ) )
return true;
return false;
}
public int GetHashCode( AsyncQueryInfo obj )
{
if( obj == null )
return 0;
return obj.StartIndex ^ obj.RequestedItemCount;
}
#endregion IEqualityComparer<AsyncQueryInfo> Members
}
}

217
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/BindingPathValueExtractor.cs

@ -1,217 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Diagnostics;
using System.Globalization;
using System.Collections;
namespace Xceed.Wpf.DataGrid
{
internal class BindingPathValueExtractor : FrameworkElement
{
#region CONSTRUCTORS
public BindingPathValueExtractor(
string xPath,
PropertyPath propertyPath,
bool onlyForWrite,
Type dataType,
IValueConverter converter,
object converterParameter,
CultureInfo converterCulture )
{
m_onlyForWrite = onlyForWrite;
m_targetType = dataType;
m_contextDataProvider = new ContextDataProvider();
m_binding = new Binding();
m_binding.XPath = xPath;
m_binding.Path = propertyPath;
if( converter == null )
throw new DataGridInternalException( "A Converter must be used" );
if( onlyForWrite )
{
m_binding.Mode = BindingMode.OneWayToSource;
m_binding.Converter = new ConvertBackInhibitorPassthroughConverter( converter );
m_binding.ConverterParameter = converterParameter;
m_binding.ConverterCulture = converterCulture;
}
else
{
m_binding.Mode = BindingMode.OneWay;
m_converter = converter;
m_converterParameter = converterParameter;
m_converterCulture = converterCulture;
}
m_binding.Source = m_contextDataProvider;
this.SetBinding(
BindingPathValueExtractor.ValueProperty,
m_binding );
}
#endregion CONSTRUCTORS
#region ValueProperty
private static object UninitializedValueKey = new object();
private static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof( object ), typeof( BindingPathValueExtractor ), new PropertyMetadata( BindingPathValueExtractor.UninitializedValueKey ) );
private object Value
{
get
{
if( m_onlyForWrite )
throw new InvalidOperationException( "An attempt was made to read in a write-only binding." );
object value = this.GetValue( BindingPathValueExtractor.ValueProperty );
if( value == BindingPathValueExtractor.UninitializedValueKey )
value = null;
value = m_converter.Convert( value, m_targetType, m_converterParameter, m_converterCulture );
if( ( value == DependencyProperty.UnsetValue ) || ( value == Binding.DoNothing ) )
return null;
return value;
}
set
{
if( !m_onlyForWrite )
throw new InvalidOperationException( "An attempt was made to write in a read-only binding." );
this.SetValue( BindingPathValueExtractor.ValueProperty, value );
}
}
#endregion ValueProperty
#region PUBLIC METHODS
public object GetValueFromItem( object item )
{
m_contextDataProvider.SetNewDataContext( item );
return this.Value;
// To gain some performance we do not reset the context
//m_contextDataProvider.SetNewDataContext( null );
}
public void SetValueToItem( object item, object value )
{
if( m_binding.Mode == BindingMode.OneWay )
throw new InvalidOperationException( "An attempt was made to set a value for a read-only destination path." );
m_contextDataProvider.SetNewDataContext( item );
this.Value = value;
// To gain some performance we do not reset the context
//m_contextDataProvider.SetNewDataContext( null );
}
#endregion PUBLIC METHODS
#region PRIVATE FIELDS
internal static readonly object[] EmptyObjectArray = new object[ 0 ];
private ContextDataProvider m_contextDataProvider;
private Binding m_binding;
private IValueConverter m_converter;
private object m_converterParameter;
private CultureInfo m_converterCulture;
private bool m_onlyForWrite;
private Type m_targetType;
#endregion PRIVATE FIELDS
#region PRIVATE ConvertBackInhibitorConverter CLASS
private class ConvertBackInhibitorPassthroughConverter : IValueConverter
{
public ConvertBackInhibitorPassthroughConverter( IValueConverter converter )
{
m_converter = converter;
}
#region IValueConverter Members
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( m_converter != null )
return m_converter.Convert( value, targetType, parameter, culture );
return value;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
if( value == BindingPathValueExtractor.UninitializedValueKey )
return Binding.DoNothing;
if( m_converter != null )
return m_converter.ConvertBack( value, targetType, parameter, culture );
return value;
}
#endregion
#region PRIVATE FIELDS
private IValueConverter m_converter;
#endregion PRIVATE FIELDS
}
#endregion PRIVATE ConvertBackInhibitorConverter CLASS
#region PRIVATE ContextDataProvider CLASS
private class ContextDataProvider : DataSourceProvider
{
public ContextDataProvider()
{
}
public void SetNewDataContext( object dataContext )
{
m_dataContext = dataContext;
this.Refresh();
}
protected override void BeginQuery()
{
this.OnQueryFinished( m_dataContext );
}
private object m_dataContext;
}
#endregion PRIVATE ContextDataProvider CLASS
}
}

161
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CollectionViewGroupExtensions.cs

@ -1,161 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Collections.ObjectModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
public static class CollectionViewGroupExtensions
{
internal static SelectionRange GetRange( this CollectionViewGroup collectionViewGroup, DataGridContext dataGridContext )
{
int startIndex = -1;
int endIndex = -1;
DataGridVirtualizingCollectionViewGroupBase dataGridVirtualizingCollectionViewGroupBase = collectionViewGroup as DataGridVirtualizingCollectionViewGroupBase;
DataGridCollectionViewGroup dataGridCollectionViewGroup = collectionViewGroup as DataGridCollectionViewGroup;
if( dataGridVirtualizingCollectionViewGroupBase != null )
{
startIndex = dataGridVirtualizingCollectionViewGroupBase.StartGlobalIndex;
endIndex = startIndex + dataGridVirtualizingCollectionViewGroupBase.VirtualItemCount - 1;
}
else if( dataGridCollectionViewGroup != null )
{
startIndex = dataGridCollectionViewGroup.GetFirstRawItemGlobalSortedIndex();
endIndex = startIndex + dataGridCollectionViewGroup.GlobalRawItemCount - 1;
}
else if( collectionViewGroup.ItemCount > 0 )
{
if( dataGridContext == null )
throw new DataGridInternalException( "This collectionViewGroup require a DataGridContext instance" );
var firstItem = collectionViewGroup.GetFirstLeafItem();
var lastItem = collectionViewGroup.GetLastLeafItem();
if( firstItem != null && lastItem != null )
{
startIndex = dataGridContext.Items.IndexOf( firstItem );
endIndex = dataGridContext.Items.IndexOf( lastItem );
}
}
return ( startIndex >= 0 ) && ( startIndex <= endIndex )
? new SelectionRange( startIndex, endIndex )
: SelectionRange.Empty;
}
public static IList<object> GetItems( this CollectionViewGroup collectionViewGroup )
{
var dataGridVirtualizingCollectionViewGroupBase = collectionViewGroup as DataGridVirtualizingCollectionViewGroupBase;
if( dataGridVirtualizingCollectionViewGroupBase != null )
return dataGridVirtualizingCollectionViewGroupBase.VirtualItems;
// The Items property of the DataGridCollectionViewGroup has been optimized to allow faster IndexOf and Contains. Since this property we could not
// override the property, we had to new it thus, we need to cast the CollectionViewGroup in the right type before acecssing the property.
var dataGridCollectionViewGroup = collectionViewGroup as DataGridCollectionViewGroup;
if( dataGridCollectionViewGroup != null )
return dataGridCollectionViewGroup.Items;
return collectionViewGroup.Items;
}
public static int GetItemCount( this CollectionViewGroup collectionViewGroup )
{
var dataGridVirtualizingCollectionViewGroupBase = collectionViewGroup as DataGridVirtualizingCollectionViewGroupBase;
if( dataGridVirtualizingCollectionViewGroupBase != null )
return dataGridVirtualizingCollectionViewGroupBase.VirtualItemCount;
return collectionViewGroup.ItemCount;
}
internal static IEnumerable<object> GetLeafItems( this CollectionViewGroup collectionViewGroup )
{
foreach( var item in collectionViewGroup.GetItems() )
{
if( item is CollectionViewGroup )
{
foreach( var subItem in ( ( CollectionViewGroup )item ).GetLeafItems() )
{
yield return subItem;
}
}
else
{
yield return item;
}
}
}
internal static object GetFirstLeafItem( this CollectionViewGroup collectionViewGroup )
{
IList<object> items = collectionViewGroup.GetItems();
if( items.Count == 0 )
return null;
var item = items[ 0 ];
var subGroup = item as CollectionViewGroup;
return ( subGroup != null )
? subGroup.GetFirstLeafItem()
: item;
}
internal static object GetLastLeafItem( this CollectionViewGroup collectionViewGroup )
{
IList<object> items = collectionViewGroup.GetItems();
if( items.Count == 0 )
return null;
var item = items[ items.Count - 1 ];
var subGroup = item as CollectionViewGroup;
return ( subGroup != null )
? subGroup.GetLastLeafItem()
: item;
}
internal static IEnumerable<CollectionViewGroup> GetSubGroups( this CollectionViewGroup collectionViewGroup )
{
foreach( var item in collectionViewGroup.GetItems() )
{
var subGroup = item as CollectionViewGroup;
//No need to check every items, they will be all Groups or not.
if( subGroup == null )
break;
yield return subGroup;
foreach( var subSubgroup in subGroup.GetSubGroups() )
{
yield return subGroup;
}
}
}
}
}

55
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CommitItemsEvent.cs

@ -1,55 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class CommitItemsEventArgs : EventArgs
{
internal CommitItemsEventArgs( DataGridVirtualizingCollectionViewBase collectionView, AsyncCommitInfo asyncCommitInfo )
{
m_dataGridVirtualizingCollectionViewBase = collectionView;
m_asyncCommitInfo = asyncCommitInfo;
}
public DataGridVirtualizingCollectionViewBase CollectionView
{
get
{
return m_dataGridVirtualizingCollectionViewBase;
}
}
public AsyncCommitInfo AsyncCommitInfo
{
get
{
return m_asyncCommitInfo;
}
}
#region PRIVATE FIELDS
private DataGridVirtualizingCollectionViewBase m_dataGridVirtualizingCollectionViewBase;
private AsyncCommitInfo m_asyncCommitInfo;
#endregion PRIVATE FIELDS
}
}

87
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ConnectionErrorChangedEventManager.cs

@ -1,87 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class ConnectionErrorChangedEventManager : WeakEventManager
{
#region Constructor
private ConnectionErrorChangedEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ConnectionErrorChangedEventManager CurrentManager
{
get
{
var managerType = typeof( ConnectionErrorChangedEventManager );
var currentManager = ( ConnectionErrorChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ConnectionErrorChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridVirtualizingCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridVirtualizingCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var target = ( DataGridVirtualizingCollectionViewBase )source;
target.ConnectionErrorChanged += new EventHandler( this.DeliverEvent );
}
protected override void StopListening( object source )
{
var target = ( DataGridVirtualizingCollectionViewBase )source;
target.ConnectionErrorChanged -= new EventHandler( this.DeliverEvent );
}
}
}

87
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ConnectionStateChangedEventManager.cs

@ -1,87 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class ConnectionStateChangedEventManager : WeakEventManager
{
#region Constructor
private ConnectionStateChangedEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ConnectionStateChangedEventManager CurrentManager
{
get
{
var managerType = typeof( ConnectionStateChangedEventManager );
var currentManager = ( ConnectionStateChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ConnectionStateChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridVirtualizingCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridVirtualizingCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var target = ( DataGridVirtualizingCollectionViewBase )source;
target.ConnectionStateChanged += new EventHandler( this.DeliverEvent );
}
protected override void StopListening( object source )
{
var target = ( DataGridVirtualizingCollectionViewBase )source;
target.ConnectionStateChanged -= new EventHandler( this.DeliverEvent );
}
}
}

37
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CustomDistinctValueItemConfiguration.cs

@ -1,37 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Xceed.Wpf.DataGrid
{
internal class CustomDistinctValueItemConfiguration
{
public CustomDistinctValueItemConfiguration()
{
}
public object Title
{
get;
set;
}
}
}

47
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CustomDistinctValueItemConfigurationCollection.cs

@ -1,47 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.DataGrid
{
internal class CustomDistinctValueItemConfigurationCollection : ObservableCollection<CustomDistinctValueItemConfiguration>
{
internal CustomDistinctValueItemConfigurationCollection()
{
}
public CustomDistinctValueItemConfiguration this[ object configurationTitle ]
{
get
{
foreach( CustomDistinctValueItemConfiguration configuration in this )
{
if( configuration.Title == configurationTitle )
{
return configuration;
}
}
return null;
}
}
}
}

2456
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionView.cs

File diff suppressed because it is too large

2901
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewBase.cs

File diff suppressed because it is too large

179
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewBaseDataProvider.cs

@ -1,179 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
internal abstract class DataGridCollectionViewBaseDataProvider : DataSourceProvider, IWeakEventListener
{
internal DataGridCollectionViewBaseDataProvider( DataGridCollectionViewSourceBase parentSource )
: base()
{
if( parentSource == null )
throw new ArgumentNullException( "parentSource" );
m_parentSource = parentSource;
}
#region CurrentView Property
public DataGridCollectionViewBase CurrentView
{
get
{
return m_currentView;
}
}
private DataGridCollectionViewBase m_currentView;
#endregion
#region ParentSource Internal Property
internal DataGridCollectionViewSourceBase ParentSource
{
get
{
return m_parentSource;
}
}
private readonly DataGridCollectionViewSourceBase m_parentSource;
#endregion
public void DelayRefresh( Dispatcher dispatcher, DispatcherPriority priority )
{
// No need to call Refresh again since there is already one that is pending.
if( m_delayedRefreshPending )
return;
// Call Refresh on the dispatcher with the specified priority.
var operation = dispatcher.BeginInvoke(
priority,
new Action( delegate
{
this.Refresh();
} ) );
// If we're not already completed, set the internal flag to prevent
// another Refresh from being stacked on register to be notified
// when the operation complete.
if( operation.Status != DispatcherOperationStatus.Completed )
{
m_delayedRefreshPending = true;
operation.Completed += new EventHandler( this.OnDelayedRefreshCompleted );
}
}
protected override void BeginQuery()
{
var queryException = default( Exception );
try
{
this.EnsureDataGridCollectionViewBase();
}
catch( Exception exception )
{
queryException = exception;
}
this.OnQueryFinished( m_currentView, queryException, null, null );
}
internal abstract DataGridCollectionViewBase EnsureDataGridCollectionViewBaseCore();
private void EnsureDataGridCollectionViewBase()
{
var success = false;
try
{
var newView = this.EnsureDataGridCollectionViewBaseCore();
if( newView != m_currentView )
{
this.ClearView();
m_currentView = newView;
if( m_currentView != null )
{
m_currentView.ParentCollectionViewSourceBase = m_parentSource;
}
}
Debug.Assert( ( m_currentView == null ) || ( m_currentView.ParentCollectionViewSourceBase == m_parentSource ) );
success = true;
}
finally
{
if( !success )
{
this.ClearView();
}
}
}
private void ClearView()
{
if( m_currentView == null )
return;
var view = m_currentView;
m_currentView = null;
view.Dispose();
}
private void OnDelayedRefreshCompleted( object sender, EventArgs e )
{
m_delayedRefreshPending = false;
}
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
return this.OnReceiveWeakEvent( managerType, sender, e );
}
protected virtual bool OnReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( managerType == typeof( DataChangedEventManager ) )
{
this.Refresh();
}
else
{
return false;
}
return true;
}
#endregion
private bool m_delayedRefreshPending;
}
}

95
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewDataProvider.cs

@ -1,95 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Windows;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewDataProvider : DataGridCollectionViewBaseDataProvider
{
#region CONSTRUCTORS
public DataGridCollectionViewDataProvider( DataGridCollectionViewSource parentSource )
: base( parentSource )
{
}
#endregion CONSTRUCTORS
internal override DataGridCollectionViewBase EnsureDataGridCollectionViewBaseCore()
{
DataGridCollectionViewSource parentSource = this.ParentSource as DataGridCollectionViewSource;
object source = parentSource.OriginalSource;
Type itemType = parentSource.ItemType;
DataSourceProvider dataSourceProvider = source as DataSourceProvider;
if( dataSourceProvider != m_dataSourceProvider )
{
if( m_dataSourceProvider != null )
DataChangedEventManager.RemoveListener( m_dataSourceProvider, this );
m_dataSourceProvider = dataSourceProvider;
if( m_dataSourceProvider != null )
{
DataChangedEventManager.AddListener( m_dataSourceProvider, this );
m_dataSourceProvider.InitialLoad();
}
}
if( dataSourceProvider != null )
source = dataSourceProvider.Data;
IListSource listSource = source as IListSource;
if( listSource != null )
source = listSource.GetList();
if( source == null )
return null;
IEnumerable enumerableSource = source as IEnumerable;
Debug.Assert( enumerableSource != null );
DataGridCollectionViewBase currentView = this.CurrentView;
if( ( currentView != null )
&& ( currentView.SourceCollection == enumerableSource )
&& ( currentView.DesiredItemType == itemType ) )
{
// No changes.
return currentView;
}
return new DataGridCollectionView(
enumerableSource,
itemType,
parentSource.AutoCreateItemProperties,
parentSource.AutoCreateDetailDescriptions,
parentSource.AutoCreateForeignKeyDescriptions );
}
private DataSourceProvider m_dataSourceProvider;
}
}

162
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewEnumerator.cs

@ -1,162 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewEnumerator : IEnumerator
{
public DataGridCollectionViewEnumerator( DataGridCollectionView collectionView )
{
m_collectionView = collectionView;
m_version = m_collectionView.SortedItemVersion;
this.Reset();
}
#region IEnumerator Members
public object Current
{
get
{
if( m_beforeStart == true )
throw new InvalidOperationException( "MoveNext must be called first." );
if( m_current == null )
throw new InvalidOperationException( "The index is past the end of the list." );
return m_current.DataItem;
}
}
public bool MoveNext()
{
bool retval = false;
if( m_version != m_collectionView.SortedItemVersion )
throw new InvalidOperationException( "The list of items has changed." );
if( m_beforeStart == true )
{
m_beforeStart = false;
if( ( m_currentGroup != null ) && ( m_currentGroup.RawItems.Count == 0 ) )
{
// This should only occur if the first leaf group encountered after the Reset call was empty.
this.MoveToNextNonEmptyLeafGroup();
}
}
if( m_afterEnd == true )
{
m_current = null;
}
else
{
if( ( m_currentGroup == null ) || ( m_currentGroup.RawItems.Count == 0 ) )
{
m_afterEnd = true;
}
else
{
//check indexes
if( m_currentItemIndex < m_currentGroup.RawItems.Count )
{
m_current = m_currentGroup.RawItems[ m_currentItemIndex ];
m_currentItemIndex++;
if( m_currentItemIndex >= m_currentGroup.RawItems.Count )
{
m_currentItemIndex = 0;
m_afterEnd = !this.MoveToNextNonEmptyLeafGroup();
}
retval = true;
}
}
}
return retval;
}
private bool MoveToNextNonEmptyLeafGroup()
{
bool foundNonEmptyLeafGroup = false;
while( foundNonEmptyLeafGroup == false )
{
if( m_currentGroupIndex.Count == 0 )
break;
m_currentGroup = m_currentGroup.Parent;
int index = m_currentGroupIndex.Pop();
index++;
if( index < m_currentGroup.ItemCount )
{
m_currentGroup = this.MoveToFirstLeafGroup( m_currentGroup, index );
foundNonEmptyLeafGroup = ( m_currentGroup.RawItems.Count > 0 );
}
}
return foundNonEmptyLeafGroup;
}
private DataGridCollectionViewGroup MoveToFirstLeafGroup( DataGridCollectionViewGroup referenceGroup, int index )
{
while( !referenceGroup.IsBottomLevel )
{
referenceGroup = referenceGroup.Items[ index ] as DataGridCollectionViewGroup;
m_currentGroupIndex.Push( index );
if( index != 0 )
index = 0;
}
return referenceGroup;
}
public void Reset()
{
m_beforeStart = true;
m_afterEnd = false;
m_current = null;
m_currentItemIndex = 0;
m_currentGroupIndex.Clear();
m_currentGroup = ( m_collectionView.Count == 0 ) ? null : this.MoveToFirstLeafGroup( m_collectionView.RootGroup, 0 );
}
#endregion
private DataGridCollectionViewGroup m_currentGroup;
private RawItem m_current;
private Stack<int> m_currentGroupIndex = new Stack<int>( 16 );
private int m_currentItemIndex;
private bool m_beforeStart;
private bool m_afterEnd;
private int m_version;
private DataGridCollectionView m_collectionView;
}
}

1055
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroup.cs

File diff suppressed because it is too large

134
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroupRoot.cs

@ -1,134 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewGroupRoot : DataGridCollectionViewGroup
{
internal DataGridCollectionViewGroupRoot( DataGridCollectionView parentCollectionView )
: base( 128 )
{
m_parentCollectionView = parentCollectionView;
}
internal DataGridCollectionViewGroupRoot( DataGridCollectionViewGroupRoot template )
: base( template, null )
{
m_parentCollectionView = template.m_parentCollectionView;
}
protected override DataGridCollectionView GetCollectionView()
{
return m_parentCollectionView;
}
internal void SortRootRawItems( IList<SortDescriptionInfo> sortDescriptionInfos, List<RawItem> globalRawItems )
{
Debug.Assert( this.IsBottomLevel );
var itemCount = m_sortedRawItems.Count;
if( itemCount == 0 )
return;
var indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ )
{
indexes[ i ] = m_sortedRawItems[ i ].Index;
}
// "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
var collectionViewSort = new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
collectionViewSort.Sort( itemCount );
var index = 0;
for( int i = 1; i <= itemCount; i++ )
{
var newRawItem = globalRawItems[ indexes[ i ] ];
newRawItem.SetSortedIndex( index );
m_sortedRawItems[ index ] = newRawItem;
index++;
}
}
internal override void InsertRawItem( int index, RawItem rawItem )
{
Debug.Assert( this.IsBottomLevel );
m_globalRawItemCount++;
int count = m_sortedRawItems.Count;
for( int i = index; i < count; i++ )
{
m_sortedRawItems[ i ].SetSortedIndex( i + 1 );
}
m_sortedRawItems.Insert( index, rawItem );
rawItem.SetParentGroup( this );
rawItem.SetSortedIndex( index );
}
internal override void RemoveRawItemAt( int index )
{
Debug.Assert( this.IsBottomLevel );
Debug.Assert( m_sortedRawItems.Count > 0 );
int count = m_sortedRawItems.Count;
if( count == 0 )
return;
if( index != -1 )
{
m_globalRawItemCount--;
for( int i = index + 1; i < count; i++ )
{
m_sortedRawItems[ i ].SetSortedIndex( i - 1 );
}
RawItem rawItem = m_sortedRawItems[ index ];
rawItem.SetParentGroup( null );
rawItem.SetSortedIndex( -1 );
m_sortedRawItems.RemoveAt( index );
}
}
internal override void MoveRawItem( int oldIndex, int newIndex )
{
Debug.Assert( this.IsBottomLevel );
RawItem rawItem = m_sortedRawItems[ oldIndex ];
m_sortedRawItems.RemoveAt( oldIndex );
m_sortedRawItems.Insert( newIndex, rawItem );
int startIndex = Math.Min( oldIndex, newIndex );
int endIndex = Math.Max( oldIndex, newIndex );
for( int i = startIndex; i <= endIndex; i++ )
{
m_sortedRawItems[ i ].SetSortedIndex( i );
}
}
private DataGridCollectionView m_parentCollectionView;
}
}

51
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroupSort.cs

@ -1,51 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
using Xceed.Utils.Collections;
using System.Collections.ObjectModel;
using Xceed.Utils.Data;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewGroupSort : IndexWeakHeapSort
{
public DataGridCollectionViewGroupSort( int[] dataIndexArray, GroupSortComparer groupSortedComparer, DataGridCollectionViewGroup[] protectedItems )
: base( dataIndexArray )
{
if( groupSortedComparer == null )
throw new ArgumentNullException( "groupSortedComparer" );
m_groupSortedComparer = groupSortedComparer;
m_groups = protectedItems;
}
public override int Compare( int xDataIndex, int yDataIndex )
{
DataGridCollectionViewGroup xGroup = m_groups[ xDataIndex ];
DataGridCollectionViewGroup yGroup = m_groups[ yDataIndex ];
return m_groupSortedComparer.Compare( xGroup, yGroup );
}
private GroupSortComparer m_groupSortedComparer;
private DataGridCollectionViewGroup[] m_groups;
}
}

63
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSort.cs

@ -1,63 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Collections.Generic;
using System.ComponentModel;
using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewSort : IndexWeakHeapSort
{
public DataGridCollectionViewSort( int[] dataIndexArray, IList<SortDescriptionInfo> sortDescriptionInfos )
: base( dataIndexArray )
{
m_sortDescriptionInfos = sortDescriptionInfos;
}
public override int Compare( int xDataIndex, int yDataIndex )
{
var lastSortDirection = ListSortDirection.Ascending;
if( m_sortDescriptionInfos != null )
{
foreach( var sortDescriptionInfo in m_sortDescriptionInfos )
{
lastSortDirection = sortDescriptionInfo.SortDirection;
if( sortDescriptionInfo.Property == null )
continue;
var sortComparer = sortDescriptionInfo.SortComparer;
var dataStore = sortDescriptionInfo.DataStore;
var compare = ( sortComparer != null )
? sortComparer.Compare( dataStore.GetData( xDataIndex ), dataStore.GetData( yDataIndex ) )
: dataStore.Compare( xDataIndex, yDataIndex );
if( compare != 0 )
return ( lastSortDirection == ListSortDirection.Descending ) ? -compare : compare;
}
}
if( lastSortDirection == ListSortDirection.Descending )
return yDataIndex - xDataIndex;
return xDataIndex - yDataIndex;
}
private readonly IList<SortDescriptionInfo> m_sortDescriptionInfos;
}
}

111
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSource.cs

@ -1,111 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
public sealed class DataGridCollectionViewSource : DataGridCollectionViewSourceBase
{
#region CONSTRUCTORS
static DataGridCollectionViewSource()
{
CollectionViewSource.CollectionViewTypeProperty.OverrideMetadata(
typeof( DataGridCollectionViewSource ),
new FrameworkPropertyMetadata( typeof( DataGridCollectionView ) ) );
}
public DataGridCollectionViewSource()
: base()
{
}
#endregion CONSTRUCTORS
#region CollectionViewType Property
protected override void OnCollectionViewTypeChanged(
Type oldCollectionViewType,
Type newCollectionViewType )
{
if( newCollectionViewType != typeof( DataGridCollectionView ) )
throw new InvalidOperationException( "An attempt was made to use a view other than DataGridCollectionView." );
base.OnCollectionViewTypeChanged( oldCollectionViewType, newCollectionViewType );
}
#endregion CollectionViewType Property
#region UpdateChangedPropertyStatsOnly Property
internal bool UpdateChangedPropertyStatsOnly
{
get;
set;
}
#endregion
#region SourceItems Property
[Browsable( false )]
[EditorBrowsable( EditorBrowsableState.Never )]
[Obsolete( "The SourceItems property is obsolete and should no longer be used. Unbound data should be wrapped in a collection and assigned to the Source property instead.", true )]
public ObservableCollection<object> SourceItems
{
get
{
throw new NotSupportedException( "The SourceItems property is obsolete and should no longer be used. Unbound data should be wrapped in a collection and assigned to the Source property instead." );
}
}
#endregion SourceItems Property
#region INTERNAL METHODS
internal override DataGridCollectionViewBaseDataProvider CreateDataProvider()
{
return new DataGridCollectionViewDataProvider( this );
}
internal override void ApplyExtraPropertiesToView( DataGridCollectionViewBase currentView )
{
base.ApplyExtraPropertiesToView( currentView );
}
#endregion INTERNAL METHODS
#region PRIVATE METHODS
private static void OnDataGridCollectionViewSourceDependencyPropertyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
DataGridCollectionViewSource source = o as DataGridCollectionViewSource;
if( source == null )
return;
source.AdviseForwardedPropertyChanged();
}
#endregion PRIVATE METHODS
}
}

550
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSourceBase.cs

@ -1,550 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
public abstract class DataGridCollectionViewSourceBase : CollectionViewSource
{
static DataGridCollectionViewSourceBase()
{
CollectionViewSource.SourceProperty.OverrideMetadata(
typeof( DataGridCollectionViewSourceBase ),
new FrameworkPropertyMetadata(
null,
null,
new CoerceValueCallback( DataGridCollectionViewSourceBase.OnSourceCoerceValue ) ) );
}
public DataGridCollectionViewSourceBase()
{
m_itemProperties = new ObservableCollection<DataGridItemPropertyBase>();
m_itemProperties.CollectionChanged += new NotifyCollectionChangedEventHandler( this.ForwardedCollection_CollectionChanged );
m_dataGridDetailDescriptions = new DataGridDetailDescriptionCollection();
m_dataGridDetailDescriptions.CollectionChanged += new NotifyCollectionChangedEventHandler( this.ForwardedCollection_CollectionChanged );
// We force a culture because it is the only way to be
// notified when the Culture changes in order to launch our own
// ApplyExtraPropertiesToView (because the implentation of ApplyPropertiesToView is not virtual!)
//
// See CollectionViewSource.ApplyPropertiesToView in reflector for a better understanding.
this.Culture = CultureInfo.InvariantCulture;
}
#region ItemProperties Property
public ObservableCollection<DataGridItemPropertyBase> ItemProperties
{
get
{
return m_itemProperties;
}
}
private ObservableCollection<DataGridItemPropertyBase> m_itemProperties;
#endregion
#region DetailDescriptions Property
internal ObservableCollection<DataGridDetailDescription> DetailDescriptions
{
get
{
return m_dataGridDetailDescriptions;
}
}
private ObservableCollection<DataGridDetailDescription> m_dataGridDetailDescriptions;
#endregion
#region ItemType Property
public static readonly DependencyProperty ItemTypeProperty = DependencyProperty.Register(
"ItemType", typeof( Type ), typeof( DataGridCollectionViewSourceBase ),
new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.NotDataBindable ) );
public Type ItemType
{
get
{
return this.GetValue( ItemTypeProperty ) as Type;
}
set
{
this.SetValue( ItemTypeProperty, value );
if( m_dataSourceProvider != null )
m_dataSourceProvider.DelayRefresh( this.Dispatcher, System.Windows.Threading.DispatcherPriority.DataBind );
}
}
#endregion
#region CollectionViewType Property
protected override void OnCollectionViewTypeChanged(
Type oldCollectionViewType,
Type newCollectionViewType )
{
if( !typeof( DataGridCollectionViewBase ).IsAssignableFrom( newCollectionViewType ) )
throw new InvalidOperationException( "An attempt was made to use a view other than DataGridCollectionViewBase." );
base.OnCollectionViewTypeChanged( oldCollectionViewType, newCollectionViewType );
}
#endregion
#region AutoCreateItemProperties Property
public static readonly DependencyProperty AutoCreateItemPropertiesProperty = DependencyProperty.Register(
"AutoCreateItemProperties", typeof( bool ), typeof( DataGridCollectionViewSourceBase ),
new FrameworkPropertyMetadata( true,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceChanged ) ) );
public bool AutoCreateItemProperties
{
get
{
return ( bool )this.GetValue( AutoCreateItemPropertiesProperty );
}
set
{
this.SetValue( AutoCreateItemPropertiesProperty, value );
}
}
#endregion
#region AutoCreateDetailDescriptions Property
internal static readonly DependencyProperty AutoCreateDetailDescriptionsProperty = DependencyProperty.Register(
"AutoCreateDetailDescriptions", typeof( bool ), typeof( DataGridCollectionViewSourceBase ),
new FrameworkPropertyMetadata( false,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceChanged ) ) );
internal bool AutoCreateDetailDescriptions
{
get
{
return ( bool )this.GetValue( AutoCreateDetailDescriptionsProperty );
}
set
{
this.SetValue( AutoCreateDetailDescriptionsProperty, value );
}
}
#endregion
#region DistinctValuesConstraints Property
public static readonly DependencyProperty DistinctValuesConstraintProperty = DependencyProperty.Register(
"DistinctValuesConstraint", typeof( DistinctValuesConstraint ), typeof( DataGridCollectionViewSourceBase ),
new UIPropertyMetadata( DistinctValuesConstraint.All,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceBaseDependencyPropertyChanged ) ) );
public DistinctValuesConstraint DistinctValuesConstraint
{
get
{
return ( DistinctValuesConstraint )this.GetValue( DistinctValuesConstraintProperty );
}
set
{
this.SetValue( DistinctValuesConstraintProperty, value );
}
}
#endregion
#region DistinctValuesUpdateMode Property
public static readonly DependencyProperty DistinctValuesUpdateModeProperty = DependencyProperty.Register(
"DistinctValuesUpdateMode", typeof( DistinctValuesUpdateMode ), typeof( DataGridCollectionViewSourceBase ),
new UIPropertyMetadata( DistinctValuesUpdateMode.Manual,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceBaseDependencyPropertyChanged ) ) );
public DistinctValuesUpdateMode DistinctValuesUpdateMode
{
get
{
return ( DistinctValuesUpdateMode )this.GetValue( DistinctValuesUpdateModeProperty );
}
set
{
this.SetValue( DistinctValuesUpdateModeProperty, value );
}
}
#endregion
#region DefaultCalculateDistinctValues Property
public static readonly DependencyProperty DefaultCalculateDistinctValuesProperty = DependencyProperty.Register(
"DefaultCalculateDistinctValues", typeof( bool ), typeof( DataGridCollectionViewSourceBase ),
new UIPropertyMetadata( true,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceBaseDependencyPropertyChanged ) ) );
public bool DefaultCalculateDistinctValues
{
get
{
return ( bool )this.GetValue( DefaultCalculateDistinctValuesProperty );
}
set
{
this.SetValue( DefaultCalculateDistinctValuesProperty, value );
}
}
#endregion
#region Culture Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public new CultureInfo Culture
{
get
{
return base.Culture;
}
set
{
// We force a culture because it is the only way to be
// notified when the Culture changes in order to launch our own
// ApplyExtraPropertiesToView (because the implentation of ApplyPropertiesToView is not virtual!)
//
// See CollectionViewSource.ApplyPropertiesToView in reflector for a better understanding.
if( value == null )
throw new ArgumentNullException( "Culture" );
base.Culture = value;
}
}
#endregion
#region DistinctValuesRefreshNeeded Event
public event EventHandler DistinctValuesRefreshNeeded;
internal void RaiseDistinctValuesRefreshNeeded()
{
//Inform the user DistinctValues need to be refreshed.
if( this.DistinctValuesRefreshNeeded != null )
{
this.DistinctValuesRefreshNeeded( this, EventArgs.Empty );
}
}
#endregion
#region Source property
public new object Source
{
get
{
return m_originalSource;
}
set
{
base.Source = value;
}
}
private static object OnSourceCoerceValue( DependencyObject d, object newValue )
{
if( newValue is DataGridCollectionViewBaseDataProvider )
return newValue;
DataGridCollectionViewSourceBase collectionViewSourceBase = ( DataGridCollectionViewSourceBase )d;
collectionViewSourceBase.m_originalSource = newValue;
if( collectionViewSourceBase.m_dataSourceProvider == null )
{
collectionViewSourceBase.m_dataSourceProvider = collectionViewSourceBase.CreateDataProvider();
}
else
{
collectionViewSourceBase.m_dataSourceProvider.DelayRefresh( collectionViewSourceBase.Dispatcher, System.Windows.Threading.DispatcherPriority.DataBind );
}
return collectionViewSourceBase.m_dataSourceProvider;
}
internal abstract DataGridCollectionViewBaseDataProvider CreateDataProvider();
#endregion
#region OriginalSource Property
internal object OriginalSource
{
get
{
return m_originalSource;
}
}
#endregion
#region AutoCreateForeignKeyDescriptions Property
public static readonly DependencyProperty AutoCreateForeignKeyDescriptionsProperty = DependencyProperty.Register(
"AutoCreateForeignKeyDescriptions",
typeof( bool ),
typeof( DataGridCollectionViewSourceBase ),
new FrameworkPropertyMetadata( false,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceChanged ) ) );
public bool AutoCreateForeignKeyDescriptions
{
get
{
return ( bool )this.GetValue( DataGridCollectionViewSourceBase.AutoCreateForeignKeyDescriptionsProperty );
}
set
{
this.SetValue( DataGridCollectionViewSourceBase.AutoCreateForeignKeyDescriptionsProperty, value );
}
}
#endregion
#region DataSourceProvider Internal Property
internal DataGridCollectionViewBaseDataProvider DataSourceProvider
{
get
{
return m_dataSourceProvider;
}
}
#endregion
#region EVENTS
public event EventHandler<DataGridItemEventArgs> InitializingNewItem;
internal void OnInitializingNewItem( DataGridItemEventArgs e )
{
if( this.InitializingNewItem != null )
this.InitializingNewItem( this, e );
}
public event EventHandler<DataGridCreatingNewItemEventArgs> CreatingNewItem;
internal void OnCreatingNewItem( DataGridCreatingNewItemEventArgs e )
{
if( this.CreatingNewItem != null )
this.CreatingNewItem( this, e );
}
public event EventHandler<DataGridCommittingNewItemEventArgs> CommittingNewItem;
internal void OnCommittingNewItem( DataGridCommittingNewItemEventArgs e )
{
if( this.CommittingNewItem != null )
this.CommittingNewItem( this, e );
}
public event EventHandler<DataGridItemHandledEventArgs> CancelingNewItem;
internal void OnCancelingNewItem( DataGridItemHandledEventArgs e )
{
if( this.CancelingNewItem != null )
this.CancelingNewItem( this, e );
}
public event EventHandler<DataGridItemEventArgs> NewItemCreated;
internal void OnNewItemCreated( DataGridItemEventArgs e )
{
if( this.NewItemCreated != null )
this.NewItemCreated( this, e );
}
public event EventHandler<DataGridItemEventArgs> NewItemCommitted;
internal void OnNewItemCommitted( DataGridItemEventArgs e )
{
if( this.NewItemCommitted != null )
this.NewItemCommitted( this, e );
}
public event EventHandler<DataGridItemEventArgs> NewItemCanceled;
internal void OnNewItemCanceled( DataGridItemEventArgs e )
{
if( this.NewItemCanceled != null )
this.NewItemCanceled( this, e );
}
public event EventHandler<DataGridItemCancelEventArgs> BeginningEdit;
internal void OnBeginningEdit( DataGridItemCancelEventArgs e )
{
if( this.BeginningEdit != null )
this.BeginningEdit( this, e );
}
public event EventHandler<DataGridItemEventArgs> EditBegun;
internal void OnEditBegun( DataGridItemEventArgs e )
{
if( this.EditBegun != null )
this.EditBegun( this, e );
}
public event EventHandler<DataGridItemHandledEventArgs> CancelingEdit;
internal void OnCancelingEdit( DataGridItemHandledEventArgs e )
{
if( this.CancelingEdit != null )
this.CancelingEdit( this, e );
}
public event EventHandler<DataGridItemEventArgs> EditCanceled;
internal void OnEditCanceled( DataGridItemEventArgs e )
{
if( this.EditCanceled != null )
{
this.EditCanceled( this, e );
}
}
public event EventHandler<DataGridItemCancelEventArgs> CommittingEdit;
internal void OnCommittingEdit( DataGridItemCancelEventArgs e )
{
if( this.CommittingEdit != null )
this.CommittingEdit( this, e );
}
public event EventHandler<DataGridItemEventArgs> EditCommitted;
internal void OnEditCommitted( DataGridItemEventArgs e )
{
if( this.EditCommitted != null )
this.EditCommitted( this, e );
}
public event EventHandler<DataGridRemovingItemEventArgs> RemovingItem;
internal void OnRemovingItem( DataGridRemovingItemEventArgs e )
{
if( this.RemovingItem != null )
this.RemovingItem( this, e );
}
public event EventHandler<DataGridItemRemovedEventArgs> ItemRemoved;
internal void OnItemRemoved( DataGridItemRemovedEventArgs e )
{
if( this.ItemRemoved != null )
this.ItemRemoved( this, e );
}
#endregion
internal virtual void ApplyExtraPropertiesToView( DataGridCollectionViewBase currentView )
{
var currentViewItemProperties = currentView.ItemProperties;
foreach( var itemProperty in m_itemProperties )
{
currentViewItemProperties[ itemProperty.Name ] = itemProperty;
}
var defaultCalculateDistinctValues = this.DefaultCalculateDistinctValues;
foreach( var itemProperty in currentViewItemProperties )
{
// Set default value for CalculateDistinctValues if not explicitly set
if( !itemProperty.IsCalculateDistinctValuesInitialized )
{
itemProperty.CalculateDistinctValues = defaultCalculateDistinctValues;
}
}
var autoCreateForeignKeyDescriptions = this.AutoCreateForeignKeyDescriptions;
for( int i = 0; i < m_dataGridDetailDescriptions.Count; i++ )
{
DataGridDetailDescription detailDescription = m_dataGridDetailDescriptions[ i ];
// We assume we want to auto-create ForeignKeyDescriptions for DetailDescriptions
// if this.AutoCreateForeignKeyDescriptions is true and it was auto-created
if( detailDescription.IsAutoCreated )
{
detailDescription.AutoCreateForeignKeyDescriptions = autoCreateForeignKeyDescriptions;
}
}
}
internal static void OnDataGridCollectionViewSourceBaseDependencyPropertyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
DataGridCollectionViewSourceBase source = o as DataGridCollectionViewSourceBase;
if( source == null )
return;
source.AdviseForwardedPropertyChanged();
}
internal static void OnDataGridCollectionViewSourceChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
DataGridCollectionViewSourceBase source = o as DataGridCollectionViewSourceBase;
if( source == null )
return;
if( source.m_dataSourceProvider != null )
source.m_dataSourceProvider.DelayRefresh( source.Dispatcher, System.Windows.Threading.DispatcherPriority.DataBind );
}
internal void ForwardedCollection_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
this.AdviseForwardedPropertyChanged();
}
internal void AdviseForwardedPropertyChanged()
{
// This is the only way to react like we are increasing the version number
// and ending with calling the base.ApplyPropertiesToView
base.Culture = base.Culture;
}
#region Private Fields
private DataGridCollectionViewBaseDataProvider m_dataSourceProvider;
private object m_originalSource;
#endregion
}
}

57
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCommittingNewItemEvent.cs

@ -1,57 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridCommittingNewItemEventArgs : DataGridItemCancelEventArgs
{
public DataGridCommittingNewItemEventArgs( DataGridCollectionViewBase collectionView, object item, bool cancel )
: base( collectionView, item, cancel )
{
m_index = -1;
m_newCount = -1;
}
#region Index Property
public int Index
{
get { return m_index; }
set { m_index = value; }
}
private int m_index;
#endregion Index Property
#region NewCount
public int NewCount
{
get { return m_newCount; }
set { m_newCount = value; }
}
private int m_newCount;
#endregion NewCount
}
}

84
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCreatingNewItemEvent.cs

@ -1,84 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public class DataGridCreatingNewItemEventArgs : CancelEventArgs
{
public DataGridCreatingNewItemEventArgs(
DataGridCollectionViewBase collectionView,
object newItem,
bool cancel )
: base( cancel )
{
m_collectionView = collectionView;
m_newItem = newItem;
}
#region CollectionView Property
public DataGridCollectionViewBase CollectionView
{
get { return m_collectionView; }
}
private DataGridCollectionViewBase m_collectionView;
#endregion CollectionView Property
#region NewItem Property
public object NewItem
{
get
{
return m_newItem;
}
set
{
m_newItem = value;
}
}
private object m_newItem;
#endregion NewItem Property
#region Handled Property
public bool Handled
{
get
{
return m_handled;
}
set
{
m_handled = value;
}
}
private bool m_handled;
#endregion Handled Property
}
}

507
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridDetailDescription.cs

@ -1,507 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid
{
internal abstract class DataGridDetailDescription : DependencyObject, IWeakEventListener
{
protected DataGridDetailDescription()
{
m_itemProperties = new DataGridItemPropertyCollection();
m_detailDescriptions = new DataGridDetailDescriptionCollection();
m_defaultPropertyDescriptions = new PropertyDescriptionRouteDictionary();
m_groupDescriptions = new GroupDescriptionCollection();
m_sortDescriptions = new DataGridSortDescriptionCollection();
this.AutoCreateDetailDescriptions = true;
this.AutoCreateItemProperties = true;
this.DefaultCalculateDistinctValues = true;
CollectionChangedEventManager.AddListener( m_itemProperties, this );
InitializeItemPropertyEventManager.AddListener( m_itemProperties, this );
CollectionChangedEventManager.AddListener( m_detailDescriptions, this );
}
#region RelationName Public Property
public string RelationName
{
get
{
return m_relationName;
}
set
{
if( this.InternalIsSealed == true )
throw new InvalidOperationException( "An attempt was made to change the RelationName property after the DataGridDetailDescription has been sealed." );
m_relationName = value;
}
}
private string m_relationName;
#endregion
#region Title Public Property
public object Title
{
get
{
return m_title;
}
set
{
m_title = value;
}
}
private object m_title;
#endregion
#region TitleTemplate Public Property
public DataTemplate TitleTemplate
{
get
{
return m_titleTemplate;
}
set
{
m_titleTemplate = value;
}
}
private DataTemplate m_titleTemplate;
#endregion
#region AutoCreateItemProperties Public Property
public bool AutoCreateItemProperties
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateItemProperties ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateItemProperties ] = value;
}
}
#endregion
#region AutoCreateDetailDescriptions Public Property
public bool AutoCreateDetailDescriptions
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateDetailDescriptions ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateDetailDescriptions ] = value;
}
}
#endregion
#region AutoCreateForeignKeyDescriptions Public Property
public bool AutoCreateForeignKeyDescriptions
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateForeignKeyDescriptions ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateForeignKeyDescriptions ] = value;
}
}
#endregion
#region DistinctValuesConstraint Public Property
public DistinctValuesConstraint DistinctValuesConstraint
{
get
{
return m_distinctValuesConstraint;
}
set
{
m_distinctValuesConstraint = value;
}
}
private DistinctValuesConstraint m_distinctValuesConstraint = DistinctValuesConstraint.All;
#endregion
#region ItemProperties Public Property
public DataGridItemPropertyCollection ItemProperties
{
get
{
return m_itemProperties;
}
}
private readonly DataGridItemPropertyCollection m_itemProperties;
#endregion
#region DefaultCalculateDistinctValues Public Property
public bool DefaultCalculateDistinctValues
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.DefaultCalculateDistinctValues ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.DefaultCalculateDistinctValues ] = value;
}
}
#endregion
#region DetailDescriptions Public Property
public DataGridDetailDescriptionCollection DetailDescriptions
{
get
{
return m_detailDescriptions;
}
}
private readonly DataGridDetailDescriptionCollection m_detailDescriptions;
#endregion
#region GroupDescriptions Public Property
public ObservableCollection<GroupDescription> GroupDescriptions
{
get
{
return m_groupDescriptions;
}
}
private readonly GroupDescriptionCollection m_groupDescriptions;
#endregion
#region SortDescriptions Public Propertiy
public SortDescriptionCollection SortDescriptions
{
get
{
return m_sortDescriptions;
}
}
private readonly DataGridSortDescriptionCollection m_sortDescriptions;
#endregion
#region AutoCreateItemPropertiesCompleted Internal Property
internal bool AutoCreateItemPropertiesCompleted
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateItemPropertiesCompleted ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateItemPropertiesCompleted ] = value;
}
}
#endregion
#region AutoCreateDetailDescriptionsCompleted Internal Property
internal bool AutoCreateDetailDescriptionsCompleted
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateDetailDescriptionsCompleted ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.AutoCreateDetailDescriptionsCompleted ] = value;
}
}
#endregion
#region DefaultItemPropertiesInitialized Internal Property
internal bool DefaultItemPropertiesInitialized
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.DefaultItemPropertiesInitialized ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.DefaultItemPropertiesInitialized ] = value;
}
}
#endregion
#region DefaultPropertyDescriptionsCreated Internal Property
internal bool DefaultPropertyDescriptionsCreated
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.DefaultPropertyDescriptionsCreated ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.DefaultPropertyDescriptionsCreated ] = value;
}
}
#endregion
#region DefaultPropertyDescriptions Internal Property
internal PropertyDescriptionRouteDictionary DefaultPropertyDescriptions
{
get
{
return m_defaultPropertyDescriptions;
}
}
private readonly PropertyDescriptionRouteDictionary m_defaultPropertyDescriptions;
#endregion
#region IsAutoCreated Internal Property
internal bool IsAutoCreated
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.IsAutoCreated ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.IsAutoCreated ] = value;
}
}
#endregion
#region InternalIsSealed Internal Property
internal bool InternalIsSealed
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.IsSealed ];
}
private set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.IsSealed ] = value;
}
}
#endregion
#region IsInitialized Internal Property
internal bool IsInitialized
{
get
{
return m_flags[ ( int )DataGridDetailDescriptionFlags.IsInitialized ];
}
set
{
m_flags[ ( int )DataGridDetailDescriptionFlags.IsInitialized ] = value;
}
}
#endregion
#region ItemType Internal Property
internal Type ItemType
{
get
{
return m_itemType;
}
set
{
if( value == m_itemType )
return;
m_itemType = value;
}
}
private Type m_itemType; //null
#endregion
#region DataGridSortDescriptions Internal Property
internal DataGridSortDescriptionCollection DataGridSortDescriptions
{
get
{
return m_sortDescriptions;
}
}
#endregion
protected internal virtual void Initialize( DataGridCollectionViewBase parentCollectionView )
{
}
protected internal abstract IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem );
internal void Seal()
{
this.InternalIsSealed = true;
}
internal void InternalInitialize( DataGridCollectionViewBase parentCollectionView )
{
if( string.IsNullOrEmpty( this.RelationName ) )
throw new InvalidOperationException( "An attempt was made to initialize a detail description that does not have a relation name." );
this.Initialize( parentCollectionView );
}
private void OnItemPropertiesCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
var removedItems = default( IEnumerable<DataGridItemPropertyBase> );
switch( e.Action )
{
case NotifyCollectionChangedAction.Replace:
removedItems = e.OldItems.Cast<DataGridItemPropertyBase>();
break;
case NotifyCollectionChangedAction.Remove:
removedItems = e.OldItems.Cast<DataGridItemPropertyBase>();
break;
case NotifyCollectionChangedAction.Reset:
throw new NotSupportedException();
}
}
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
return this.OnReceiveWeakEvent( managerType, sender, e );
}
protected virtual bool OnReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( ( managerType == null ) || ( sender == null ) || ( e == null ) )
return false;
if( managerType == typeof( CollectionChangedEventManager ) )
{
var eventArgs = ( NotifyCollectionChangedEventArgs )e;
if( m_itemProperties == sender )
{
this.OnItemPropertiesCollectionChanged( sender, eventArgs );
}
else if( m_detailDescriptions == sender )
{
}
}
else if( managerType == typeof( InitializeItemPropertyEventManager ) )
{
var eventArgs = ( InitializeItemPropertyEventArgs )e;
if( m_itemProperties == sender )
{
var itemProperty = eventArgs.ItemProperty;
var itemPropertyRoute = DataGridItemPropertyRoute.Create( itemProperty );
ItemsSourceHelper.SetPropertyDescriptionsFromItemProperty( m_defaultPropertyDescriptions, null, null, m_itemType, itemPropertyRoute );
ItemsSourceHelper.InitializePropertyDescriptions( m_defaultPropertyDescriptions, itemPropertyRoute, m_itemType, this.DefaultPropertyDescriptionsCreated );
}
}
else
{
return false;
}
return true;
}
#endregion
private BitVector32 m_flags = new BitVector32();
[Flags]
private enum DataGridDetailDescriptionFlags
{
IsSealed = 1 << 0,
DefaultCalculateDistinctValues = 1 << 1,
IsInitialized = 1 << 2,
AutoCreateItemProperties = 1 << 3,
AutoCreateDetailDescriptions = 1 << 4,
AutoCreateForeignKeyDescriptions = 1 << 5,
IsAutoCreated = 1 << 6,
AutoCreateItemPropertiesCompleted = 1 << 7,
AutoCreateDetailDescriptionsCompleted = 1 << 8,
DefaultItemPropertiesInitialized = 1 << 9,
DefaultPropertyDescriptionsCreated = 1 << 10,
}
}
}

77
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridDetailDescriptionCollection.cs

@ -1,77 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridDetailDescriptionCollection : ObservableCollection<DataGridDetailDescription>
{
public DataGridDetailDescriptionCollection()
{
}
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1002:DoNotExposeGenericLists" )]
public DataGridDetailDescriptionCollection( List<DataGridDetailDescription> detailDescriptions )
: base( detailDescriptions )
{
}
public DataGridDetailDescription this[ string relationName ]
{
get
{
var index = this.IndexOf( relationName );
if( index < 0 )
return null;
return this.Items[ index ];
}
}
public int IndexOf( string relationName )
{
var items = this.Items;
var count = items.Count;
for( int i = 0; i < count; i++ )
{
if( string.Equals( items[ i ].RelationName, relationName ) )
return i;
}
return -1;
}
protected override void SetItem( int index, DataGridDetailDescription item )
{
if( string.IsNullOrEmpty( item.RelationName ) )
throw new ArgumentException( "The RelationName property of the specified DataGridDetailDescription cannot be null or empty.", "item" );
base.SetItem( index, item );
}
protected override void InsertItem( int index, DataGridDetailDescription item )
{
if( string.IsNullOrEmpty( item.RelationName ) )
throw new ArgumentException( "The RelationName property of the specified DataGridDetailDescription cannot be null or empty.", "item" );
base.InsertItem( index, item );
}
}
}

122
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridGroupDescription.cs

@ -1,122 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Collections;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
public class DataGridGroupDescription : GroupDescription
{
public DataGridGroupDescription()
{
}
public DataGridGroupDescription( string propertyName )
{
m_propertyGroupDescription.PropertyName = propertyName;
}
public string PropertyName
{
get
{
return m_propertyGroupDescription.PropertyName;
}
set
{
m_propertyGroupDescription.PropertyName = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "PropertyName" ) );
}
}
public IComparer SortComparer
{
get
{
return m_sortComparer;
}
set
{
m_sortComparer = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "SortComparer" ) );
}
}
public GroupConfiguration GroupConfiguration
{
get
{
return m_groupConfiguration;
}
set
{
m_groupConfiguration = value;
}
}
public override object GroupNameFromItem( object item, int level, CultureInfo culture )
{
return this.GetPropertyValue( item );
}
public override sealed bool NamesMatch( object groupName, object itemName )
{
// We sealed up the NamesMatch because we will use a HashTable to find existing key
// for performance reason.
//
// We do not throw, because we want our GroupDescription to be usable in other CollectionView
return base.NamesMatch( groupName, itemName );
}
protected object GetPropertyValue( object item )
{
if( m_contextProperty != null )
return ItemsSourceHelper.GetValueFromItemProperty( m_contextProperty, item );
return m_propertyGroupDescription.GroupNameFromItem( item, 0, CultureInfo.InvariantCulture );
}
internal void SetContext( DataGridCollectionView collectionView )
{
if( collectionView == null )
{
m_contextProperty = null;
}
else
{
var propertyName = m_propertyGroupDescription.PropertyName;
if( string.IsNullOrEmpty( propertyName ) )
{
m_contextProperty = null;
}
else
{
m_contextProperty = ItemsSourceHelper.GetItemPropertyFromProperty( collectionView.ItemProperties, propertyName );
}
}
}
private IComparer m_sortComparer;
private DataGridItemPropertyBase m_contextProperty;
private PropertyGroupDescription m_propertyGroupDescription = new PropertyGroupDescription();
private GroupConfiguration m_groupConfiguration; // = null
}
}

71
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridGroupInfo.cs

@ -1,71 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public class DataGridGroupInfo
{
internal DataGridGroupInfo( GroupDescription groupDescription, CollectionViewGroup collectionViewGroup )
{
if( groupDescription == null )
throw new ArgumentNullException( "groupDescription" );
if( collectionViewGroup == null )
throw new ArgumentNullException( "collectionViewGroup" );
this.GroupDescription = groupDescription;
this.PropertyName = DataGridCollectionViewBase.GetPropertyNameFromGroupDescription( groupDescription );
this.Value = collectionViewGroup.Name;
}
#region GroupDescription PROPERTY
public GroupDescription GroupDescription
{
get;
private set;
}
#endregion GroupDescription PROPERTY
#region Value PROPERTY
public object Value
{
get;
private set;
}
#endregion Value PROPERTY
#region PropertyName PROPERTY
public string PropertyName
{
get;
private set;
}
#endregion PropertyName PROPERTY
}
}

53
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemCancelEvent.cs

@ -1,53 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemCancelEventArgs : DataGridItemHandledEventArgs
{
public DataGridItemCancelEventArgs(
DataGridCollectionViewBase collectionView,
object item,
bool cancel )
: base( collectionView, item )
{
m_cancel = cancel;
}
#region Cancel Property
public bool Cancel
{
get
{
return m_cancel;
}
set
{
m_cancel = value;
}
}
private bool m_cancel;
#endregion Cancel Property
}
}

60
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemEvent.cs

@ -1,60 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemEventArgs : EventArgs
{
public DataGridItemEventArgs(
DataGridCollectionViewBase collectionView,
object item )
{
m_collectionView = collectionView;
m_item = item;
}
#region CollectionView Property
public DataGridCollectionViewBase CollectionView
{
get { return m_collectionView; }
}
private DataGridCollectionViewBase m_collectionView;
#endregion CollectionView Property
#region Item Property
public object Item
{
get
{
return m_item;
}
}
private object m_item;
#endregion Item Property
}
}

51
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemHandledEvent.cs

@ -1,51 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemHandledEventArgs : DataGridItemEventArgs
{
public DataGridItemHandledEventArgs(
DataGridCollectionViewBase collectionView,
object item )
: base( collectionView, item )
{
}
#region Handled Property
public bool Handled
{
get
{
return m_handled;
}
set
{
m_handled = value;
}
}
private bool m_handled;
#endregion Handled Property
}
}

68
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemProperty.PropertyDescriptorFromItemProperty.cs

@ -1,68 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public partial class DataGridItemProperty
{
internal class PropertyDescriptorFromItemProperty : DataGridItemPropertyBase.PropertyDescriptorFromItemPropertyBase
{
public PropertyDescriptorFromItemProperty( DataGridItemProperty dataGridItemProperty )
: base( dataGridItemProperty )
{
m_propertyDescriptorForValueChanged = dataGridItemProperty.PropertyDescriptor;
}
public override void AddValueChanged( object component, EventHandler handler )
{
if( m_propertyDescriptorForValueChanged != null )
{
if( !( component is EmptyDataItem ) )
{
m_propertyDescriptorForValueChanged.AddValueChanged( component, handler );
}
}
else
{
base.AddValueChanged( component, handler );
}
}
public override void RemoveValueChanged( object component, EventHandler handler )
{
if( m_propertyDescriptorForValueChanged != null )
{
if( !( component is EmptyDataItem ) )
{
m_propertyDescriptorForValueChanged.RemoveValueChanged( component, handler );
}
}
else
{
base.RemoveValueChanged( component, handler );
}
}
private PropertyDescriptor m_propertyDescriptorForValueChanged;
}
}
}

629
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemProperty.cs

@ -1,629 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
[DebuggerDisplay( "Name = {Name}" )]
public partial class DataGridItemProperty : DataGridItemPropertyBase
{
public DataGridItemProperty()
{
}
public DataGridItemProperty( string name, string valuePath, Type dataType )
: this( name, null, valuePath, dataType )
{
}
public DataGridItemProperty( string name, string valueXPath, string valuePath, Type dataType )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "name cannot be null or empty.", "name" );
if( ( string.IsNullOrEmpty( valuePath ) ) && ( string.IsNullOrEmpty( valueXPath ) ) )
throw new ArgumentException( "valuePath or valueXPath cannot be null or empty." );
this.Initialize(
name,
null,
null,
valueXPath,
valuePath,
dataType,
false,
null,
null,
null,
null,
null );
}
public DataGridItemProperty( string name, string valuePath, Type dataType, bool isReadOnly )
: this( name, null, valuePath, dataType, isReadOnly )
{
}
public DataGridItemProperty( string name, string valueXPath, string valuePath, Type dataType, bool isReadOnly )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "name cannot be null or empty.", "name" );
if( ( string.IsNullOrEmpty( valuePath ) ) && ( string.IsNullOrEmpty( valueXPath ) ) )
throw new ArgumentException( "valuePath or valueXPath cannot be null or empty." );
this.Initialize(
name,
null,
null,
valueXPath,
valuePath,
dataType,
false,
isReadOnly,
null,
null,
null,
null );
}
public DataGridItemProperty( PropertyDescriptor propertyDescriptor )
: this( propertyDescriptor, false )
{
}
public DataGridItemProperty( string name, Type dataType )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "The name must not be null (Nothing in Visual Basic) or empty.", "name" );
if( dataType == null )
throw new ArgumentNullException( "dataType" );
this.Initialize(
name,
null,
null,
null,
null,
dataType,
false,
null,
null,
null,
null,
null );
}
public DataGridItemProperty( string name, Type dataType, bool isReadOnly )
: this( name, dataType, isReadOnly, null )
{
}
public DataGridItemProperty( string name, Type dataType, bool isReadOnly, Nullable<bool> overrideReadOnlyForInsertion )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "The name must not be null (Nothing in Visual Basic) or empty.", "name" );
if( dataType == null )
throw new ArgumentNullException( "dataType" );
this.Initialize(
name,
null,
null,
null,
null,
dataType,
false,
isReadOnly,
overrideReadOnlyForInsertion,
null,
null,
null );
}
public DataGridItemProperty( string name, PropertyDescriptor propertyDescriptor )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "The name must not be null (Nothing in Visual Basic) or empty.", "name" );
if( propertyDescriptor == null )
throw new ArgumentNullException( "propertyDescriptor" );
this.Initialize(
name,
propertyDescriptor,
null,
null,
null,
null,
false,
null,
null,
null,
null,
null );
}
internal DataGridItemProperty( PropertyDescriptor propertyDescriptor, bool isAutoCreated )
{
if( propertyDescriptor == null )
throw new ArgumentNullException( "propertyDescriptor" );
this.Initialize(
propertyDescriptor.Name,
propertyDescriptor,
null,
null,
null,
null,
isAutoCreated,
null,
null,
null,
null,
null );
}
internal DataGridItemProperty(
string name,
PropertyDescriptor propertyDescriptor,
string title,
string valueXPath,
string valuePath,
Type dataType,
bool isAutoCreated,
Nullable<bool> isReadOnly,
Nullable<bool> overrideReadOnlyForInsertion,
Nullable<bool> isDisplayable,
Nullable<bool> isASubRelationship,
DataGridForeignKeyDescription foreignKeyDescription )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "name cannot be null or empty.", "name" );
if( ( string.IsNullOrEmpty( valuePath ) ) && ( string.IsNullOrEmpty( valueXPath ) ) && ( propertyDescriptor == null ) )
throw new ArgumentException( "The valuePath, valueXPath, or propertyDescriptor must be provided." );
this.Initialize(
name,
propertyDescriptor,
title,
valueXPath,
valuePath,
dataType,
isAutoCreated,
isReadOnly,
overrideReadOnlyForInsertion,
isDisplayable,
isASubRelationship,
foreignKeyDescription );
}
[Browsable( false )]
[EditorBrowsable( EditorBrowsableState.Never )]
[Obsolete( "This constructor is obsolete and should no longer be used.", true )]
protected DataGridItemProperty( DataGridItemProperty template )
{
throw new NotSupportedException();
}
private void Initialize(
string name,
PropertyDescriptor propertyDescriptor,
string title,
string valueXPath,
string valuePath,
Type dataType,
bool isAutoCreated,
Nullable<bool> isReadOnly,
Nullable<bool> overrideReadOnlyForInsertion,
Nullable<bool> isDisplayable,
Nullable<bool> isASubRelationship,
DataGridForeignKeyDescription foreignKeyDescription )
{
this.IsAutoCreated = isAutoCreated;
m_valueXPath = valueXPath;
m_valuePath = valuePath;
m_propertyDescriptor = propertyDescriptor;
if( m_propertyDescriptor == null )
{
if( ( string.IsNullOrEmpty( m_valueXPath ) ) && ( m_valuePath == "." ) )
m_propertyDescriptor = new SelfPropertyDescriptor( dataType );
}
if( m_propertyDescriptor != null )
{
this.IsBrowsable = m_propertyDescriptor.IsBrowsable;
if( m_propertyDescriptor.IsReadOnly )
isReadOnly = m_propertyDescriptor.IsReadOnly;
}
if( title == null )
{
if( m_propertyDescriptor != null )
{
title = m_propertyDescriptor.DisplayName;
}
}
if( isReadOnly == null )
{
if( m_propertyDescriptor != null )
{
isReadOnly = m_propertyDescriptor.IsReadOnly;
}
}
if( dataType == null )
{
if( m_propertyDescriptor != null )
{
dataType = m_propertyDescriptor.PropertyType;
}
}
this.ForeignKeyDescription = foreignKeyDescription;
base.Initialize( name, title, dataType, isReadOnly, overrideReadOnlyForInsertion, isDisplayable, isASubRelationship );
}
#region ValuePath Property
public string ValuePath
{
get
{
return m_valuePath;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the ValuePath of a property already added to a containing collection." );
this.SetValuePath( value );
}
}
internal void SetValuePath( string valuePath )
{
m_valuePath = valuePath;
m_bindingPathValueExtractorForRead = null;
m_bindingPathValueExtractorForWrite = null;
}
private string m_valuePath;
#endregion
#region ValueXPath Property
public string ValueXPath
{
get
{
return m_valueXPath;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the ValueXPath of a property already added to a containing collection." );
this.SetValueXPath( value );
}
}
internal void SetValueXPath( string valueXPath )
{
m_valueXPath = valueXPath;
m_bindingPathValueExtractorForRead = null;
m_bindingPathValueExtractorForWrite = null;
}
private string m_valueXPath;
#endregion
#region PropertyDescriptor Property
public PropertyDescriptor PropertyDescriptor
{
get
{
return m_propertyDescriptor;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the PropertyDescriptor of a property already added to a containing collection." );
this.SetPropertyDescriptor( value );
}
}
internal void SetPropertyDescriptor( PropertyDescriptor propertyDescriptor )
{
m_propertyDescriptor = propertyDescriptor;
if( ( m_propertyDescriptor != null ) && ( !this.IsReadOnly ) )
{
this.SetIsReadOnly( propertyDescriptor.IsReadOnly );
}
m_bindingPathValueExtractorForRead = null;
m_bindingPathValueExtractorForWrite = null;
}
private PropertyDescriptor m_propertyDescriptor;
#endregion
#region IsAutoCreated Property
public bool IsAutoCreated
{
get;
private set;
}
#endregion
#region FieldName Internal Property
internal override string FieldName
{
get
{
var descriptor = this.PropertyDescriptor;
if( descriptor != null )
return descriptor.Name;
return base.FieldName;
}
}
#endregion
protected override object GetValueCore( object component )
{
if( m_propertyDescriptor != null )
{
object value;
try
{
value = m_propertyDescriptor.GetValue( component );
}
catch( DataException )
{
// We have to return null if the datarow is deleted from the DataTable. When the System.Data.DataRow has RowState == detached,
// it can be because it has been deleted or it being inserted, nothing special found to differentiate that 2 state. So doing a try catch.
value = null;
}
CultureInfo converterCulture = this.ConverterCulture;
if( converterCulture == null )
{
converterCulture = CultureInfo.InvariantCulture;
}
return this.GetBindingConverter( component ).Convert( value, this.DataType, this.ConverterParameter, converterCulture );
}
if( m_bindingPathValueExtractorForRead == null )
{
CultureInfo converterCulture = this.ConverterCulture;
if( converterCulture == null )
{
converterCulture = CultureInfo.InvariantCulture;
}
PropertyPath propertyPath = null;
if( !string.IsNullOrEmpty( this.ValuePath ) )
{
propertyPath = new PropertyPath( this.ValuePath, BindingPathValueExtractor.EmptyObjectArray );
}
m_bindingPathValueExtractorForRead = new BindingPathValueExtractor( this.ValueXPath, propertyPath, false, this.DataType,
this.GetBindingConverter( component ), this.ConverterParameter, converterCulture );
}
return m_bindingPathValueExtractorForRead.GetValueFromItem( component );
}
protected override void SetValueCore( object component, object value )
{
if( m_propertyDescriptor != null )
{
CultureInfo converterCulture = this.ConverterCulture;
if( converterCulture == null )
{
converterCulture = CultureInfo.InvariantCulture;
}
object convertedValue = this.GetBindingConverter( component ).ConvertBack( value, m_propertyDescriptor.PropertyType, this.ConverterParameter, converterCulture );
m_propertyDescriptor.SetValue( component, convertedValue );
}
else
{
if( m_bindingPathValueExtractorForWrite == null )
{
CultureInfo converterCulture = this.ConverterCulture;
if( converterCulture == null )
{
converterCulture = CultureInfo.InvariantCulture;
}
PropertyPath propertyPath = null;
if( !string.IsNullOrEmpty( this.ValuePath ) )
{
propertyPath = new PropertyPath( this.ValuePath, BindingPathValueExtractor.EmptyObjectArray );
}
m_bindingPathValueExtractorForWrite = new BindingPathValueExtractor( this.ValueXPath, propertyPath, true, this.DataType,
this.GetBindingConverter( component ), this.ConverterParameter, converterCulture );
}
m_bindingPathValueExtractorForWrite.SetValueToItem( component, value );
}
base.SetValueCore( component, value );
}
internal override PropertyDescriptorFromItemPropertyBase GetPropertyDescriptorForBindingCore()
{
return new PropertyDescriptorFromItemProperty( this );
}
internal override void SetUnspecifiedPropertiesValues(
PropertyDescription description,
Type itemType,
bool defaultItemPropertiesCreated )
{
var itemIsXceedDataRow = ( itemType != null ) ? typeof( DataRow ).IsAssignableFrom( itemType ) : false;
if( ( this.PropertyDescriptor == null ) && string.IsNullOrEmpty( this.ValuePath ) && string.IsNullOrEmpty( this.ValueXPath ) )
{
if( itemIsXceedDataRow )
{
this.SetPropertyDescriptor( new UnboundDataRowPropertyDescriptor( this.Name, this.DataType ) );
}
else
{
if( description == null )
{
if( this.Name == "." )
{
this.SetPropertyDescriptor( new SelfPropertyDescriptor( this.DataType ) );
this.SetValuePath( "." );
this.SetIsReadOnly( true );
this.SetOverrideReadOnlyForInsertion( false );
}
}
else
{
this.SetPropertyDescriptor( description.PropertyDescriptor );
this.SetValuePath( description.Path );
this.SetValueXPath( description.XPath );
}
}
if( defaultItemPropertiesCreated && ( this.PropertyDescriptor == null ) && string.IsNullOrEmpty( this.ValuePath ) && string.IsNullOrEmpty( this.ValueXPath ) )
{
// I have to add this particular exception case to make sure that when the ItemProperty is "re-normalized" when the first DataGridCollectionView
// is created for it, then the ValuePath is still null or empty (allowing it to be re-normalized)
this.SetValuePath( this.Name );
}
}
if( this.DataType == null )
{
//only try to affect the DataType if the DefaultPropertyDescriptions were set. (will not be the case when XAML parsing DetailDescriptions)
if( defaultItemPropertiesCreated )
{
if( description == null )
throw new InvalidOperationException( "An attempt was made to add an item (" + this.Name + ") without specifying its data type." );
this.SetDataType( description.DataType );
}
}
if( string.IsNullOrEmpty( this.Title ) )
{
if( !itemIsXceedDataRow && ( description != null ) && !string.IsNullOrEmpty( description.DisplayName ) )
{
this.Title = description.DisplayName;
}
else
{
this.Title = this.Name;
}
}
if( !this.IsReadOnly )
{
if( description != null )
{
this.SetIsReadOnly( description.IsReadOnly );
}
}
if( this.OverrideReadOnlyForInsertion == null )
{
//only try to affect the DataType if the DefaultItemProperties were set. (will not be the case when XAML parsing DetailDescriptions)
if( defaultItemPropertiesCreated )
{
this.SetOverrideReadOnlyForInsertion( ( description != null ) ? description.OverrideReadOnlyForInsertion : false );
}
}
if( ( !string.IsNullOrEmpty( this.ValueXPath ) ) && ( string.IsNullOrEmpty( this.ValuePath ) ) )
{
this.SetValuePath( "InnerText" );
}
var foreignKeyDescriptionIsNull = ( this.ForeignKeyDescription == null );
var foreignKeyDescriptionItemsSourceIsNull = false;
if( !foreignKeyDescriptionIsNull )
{
foreignKeyDescriptionItemsSourceIsNull = ( this.ForeignKeyDescription.ItemsSource == null );
}
// Update the ForeignKeyDescription if not set
if( foreignKeyDescriptionIsNull || foreignKeyDescriptionItemsSourceIsNull )
{
if( ( description != null ) && ( description.ForeignKeyDescription != null ) )
{
if( foreignKeyDescriptionIsNull )
{
this.SetForeignKeyDescription( description.ForeignKeyDescription );
}
else
{
if( foreignKeyDescriptionItemsSourceIsNull )
{
this.ForeignKeyDescription.ItemsSource = description.ForeignKeyDescription.ItemsSource;
}
}
}
}
}
#region Private Fields
private BindingPathValueExtractor m_bindingPathValueExtractorForRead;
private BindingPathValueExtractor m_bindingPathValueExtractorForWrite;
#endregion
}
}

113
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyBase.PropertyDescriptorFromItemPropertyBase.cs

@ -1,113 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
namespace Xceed.Wpf.DataGrid
{
public abstract partial class DataGridItemPropertyBase
{
internal class PropertyDescriptorFromItemPropertyBase : EmptyDataItemSafePropertyDescriptor
{
public PropertyDescriptorFromItemPropertyBase( DataGridItemPropertyBase dataGridItemProperty )
: base( dataGridItemProperty.FieldName )
{
m_dataGridItemProperty = new WeakReference( dataGridItemProperty );
m_propertyType = dataGridItemProperty.DataType;
}
public DataGridItemPropertyBase DataGridItemProperty
{
get
{
return m_dataGridItemProperty.Target as DataGridItemPropertyBase;
}
}
public override string DisplayName
{
get
{
DataGridItemPropertyBase dataGridItemProperty = this.DataGridItemProperty;
if( dataGridItemProperty != null )
return dataGridItemProperty.Title;
return string.Empty;
}
}
public override bool IsReadOnly
{
get
{
DataGridItemPropertyBase dataGridItemProperty = this.DataGridItemProperty;
if( dataGridItemProperty == null )
return true;
return ( dataGridItemProperty.OverrideReadOnlyForInsertion ?? false )
? false : dataGridItemProperty.IsReadOnly;
}
}
public override Type PropertyType
{
get
{
// This value need to not be changed during the life time of the PropertyDescriptor
return m_propertyType;
}
}
public override object GetValue( object component )
{
DataGridItemPropertyBase dataGridItemProperty = this.DataGridItemProperty;
if( dataGridItemProperty == null )
return null;
return dataGridItemProperty.GetValue( base.GetValue( component ) );
}
public override void SetValue( object component, object value )
{
if( component is EmptyDataItem )
throw new InvalidOperationException( "An attempt was made to set a value on an empty data item." );
DataGridItemPropertyBase dataGridItemProperty = this.DataGridItemProperty;
if( dataGridItemProperty == null )
return;
dataGridItemProperty.SetValue( component, value );
}
public void RaiseValueChanged( object component )
{
EventHandler valueChangedHandler = this.GetValueChangedHandler( component );
if( valueChangedHandler != null )
{
valueChangedHandler.Invoke( component, EventArgs.Empty );
}
}
private WeakReference m_dataGridItemProperty;
private Type m_propertyType;
}
}
}

955
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyBase.cs

@ -1,955 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Threading;
using System.Windows.Data;
using Xceed.Wpf.DataGrid.Converters;
using Xceed.Wpf.DataGrid.Utils;
namespace Xceed.Wpf.DataGrid
{
[DebuggerDisplay( "Name = {Name}" )]
public abstract partial class DataGridItemPropertyBase : INotifyPropertyChanged, ICloneable
{
#region Static Fields
internal static readonly string CalculateDistinctValuesPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.CalculateDistinctValues );
internal static readonly string ContainingCollectionPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.ContainingCollection );
internal static readonly string ForeignKeyDescriptionPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.ForeignKeyDescription );
internal static readonly string GroupSortStatResultPropertyNamePropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.GroupSortStatResultPropertyName );
internal static readonly string IsNameSealedPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.IsNameSealed );
internal static readonly string IsSealedPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.IsSealed );
internal static readonly string ItemPropertiesInternalPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.ItemPropertiesInternal );
internal static readonly string MaxDistinctValuesPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.MaxDistinctValues );
internal static readonly string SynonymPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyBase i ) => i.Synonym );
#endregion
protected DataGridItemPropertyBase()
{
this.SetIsDisplayable( true );
this.IsBrowsable = true;
}
[Browsable( false )]
[EditorBrowsable( EditorBrowsableState.Never )]
[Obsolete( "This constructor is obsolete and should no longer be used.", true )]
protected DataGridItemPropertyBase( DataGridItemPropertyBase template )
: this()
{
throw new NotSupportedException();
}
protected void Initialize(
string name,
string title,
Type dataType,
Nullable<bool> isReadOnly,
Nullable<bool> overrideReadOnlyForInsertion,
Nullable<bool> isDisplayable,
Nullable<bool> isASubRelationship )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "name cannot be null or empty.", "name" );
m_name = name;
if( title == null )
{
m_title = name;
}
else
{
m_title = title;
}
if( isReadOnly.HasValue )
{
this.SetIsReadOnly( isReadOnly.Value );
}
this.SetOverrideReadOnlyForInsertion( overrideReadOnlyForInsertion );
m_dataType = dataType;
if( isDisplayable.HasValue )
{
this.SetIsDisplayable( isDisplayable.Value );
}
if( isASubRelationship != null )
{
this.SetIsASubRelationship( isASubRelationship );
}
}
#region Name Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public string Name
{
get
{
return m_name;
}
set
{
if( string.IsNullOrEmpty( value ) )
throw new ArgumentException( "Name is null (Nothing in Visual Basic) or empty.", "Name" );
if( this.IsNameSealed || this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the name of a property already added to a containing collection." );
m_name = value;
}
}
private string m_name;
#endregion
#region DataType Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public Type DataType
{
get
{
return m_dataType;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the DataType of a property already added to a containing collection." );
this.SetDataType( value );
}
}
internal void SetDataType( Type dataType )
{
if( dataType == null )
throw new ArgumentNullException( "dataType" );
m_dataType = dataType;
}
private Type m_dataType;
#endregion
#region IsReadOnly Property
public bool IsReadOnly
{
get
{
return m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ];
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the IsReadOnly property of a DataGridItemProperty already added to a containing collection." );
this.SetIsReadOnly( value );
}
}
internal void SetIsReadOnly( bool isReadOnly )
{
m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ] = isReadOnly;
}
#endregion
#region OverrideReadOnlyForInsertion Property
public Nullable<bool> OverrideReadOnlyForInsertion
{
get
{
if( !m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] )
return null;
return m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ];
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the OverrideReadOnlyForInsertion property of a DataGridItemProperty already added to a containing collection." );
this.SetOverrideReadOnlyForInsertion( value );
}
}
internal void SetOverrideReadOnlyForInsertion( Nullable<bool> overrideReadOnlyForInsertion )
{
if( overrideReadOnlyForInsertion.HasValue )
{
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ] = overrideReadOnlyForInsertion.Value;
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] = true;
}
else
{
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet
| DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ] = false;
}
}
#endregion
#region Title Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public string Title
{
get
{
return m_title;
}
set
{
if( value == null )
throw new ArgumentNullException( "Title" );
m_title = value;
}
}
private string m_title;
#endregion
#region Synonym Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public string Synonym
{
get
{
return m_synonym;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the Synonym of a property already added to a containing collection." );
this.SetSynonym( value );
}
}
internal void SetSynonym( string value )
{
if( value == m_synonym )
return;
var wasSealed = this.IsSealed;
this.IsSealed = false;
m_synonym = value;
this.IsSealed = wasSealed;
this.OnPropertyChanged( DataGridItemPropertyBase.SynonymPropertyName );
}
private string m_synonym;
#endregion
#region SortComparer Property
public IComparer SortComparer
{
get
{
return m_sortComparer;
}
set
{
m_sortComparer = value;
}
}
private IComparer m_sortComparer;
#endregion
#region Converter Property
public IValueConverter Converter
{
get
{
return m_converter;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the Converter property of a DataGridItemProperty already added to a containing collection." );
m_converter = value;
}
}
internal IValueConverter GetBindingConverter( object sourceItem )
{
if( !this.IsSealed )
throw new InvalidOperationException( "An attempt was made to apply a binding to a DataGridItemProperty that has not be added to the ItemProperties collection." );
if( m_bindingConverter == null )
{
if( m_converter != null )
{
m_bindingConverter = m_converter;
}
else
{
m_bindingConverter = new SourceDataConverter( ItemsSourceHelper.IsItemSupportingDBNull( sourceItem ), CultureInfo.InvariantCulture );
}
}
return m_bindingConverter;
}
private IValueConverter m_converter;
private IValueConverter m_bindingConverter;
#endregion
#region ConverterCulture Property
public CultureInfo ConverterCulture
{
get
{
return m_converterCulture;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the ConverterCulture property of a DataGridItemProperty already added to a containing collection." );
m_converterCulture = value;
}
}
private CultureInfo m_converterCulture;
#endregion
#region ConverterParameter Property
public object ConverterParameter
{
get
{
return m_converterParameter;
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the ConverterParameter property of a DataGridItemProperty already added to a containing collection." );
m_converterParameter = value;
}
}
private object m_converterParameter;
#endregion
#region CalculateDistinctValues Property
public bool CalculateDistinctValues
{
get
{
// Always activate DistinctValues if not explicitly specified
if( !this.IsCalculateDistinctValuesInitialized )
return true;
return m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ];
}
set
{
if( value != m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] )
{
m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] = value;
this.OnPropertyChanged( DataGridItemPropertyBase.CalculateDistinctValuesPropertyName );
}
this.IsCalculateDistinctValuesInitialized = true;
}
}
internal bool IsCalculateDistinctValuesInitialized
{
get
{
return m_flags[ DataGridItemPropertyBaseFlags.IsCalculateDistinctValuesInitialized ];
}
set
{
m_flags[ DataGridItemPropertyBaseFlags.IsCalculateDistinctValuesInitialized ] = value;
}
}
#endregion
#region MaxDistinctValues Property
public int MaxDistinctValues
{
get
{
return m_maxDistinctValues;
}
set
{
if( m_maxDistinctValues != value )
{
m_maxDistinctValues = value;
this.OnPropertyChanged( DataGridItemPropertyBase.MaxDistinctValuesPropertyName );
}
}
}
private int m_maxDistinctValues = -1; // -1 ==> no maximum
#endregion
#region DistinctValuesSortComparer Property
public IComparer DistinctValuesSortComparer
{
get;
set;
}
#endregion
#region DistinctValuesEqualityComparer Property
public IEqualityComparer DistinctValuesEqualityComparer
{
get;
set;
}
#endregion
#region ForeignKeyDescription Property
public DataGridForeignKeyDescription ForeignKeyDescription
{
get
{
return m_foreignKeyDescription;
}
set
{
this.SetForeignKeyDescription( value );
}
}
internal void SetForeignKeyDescription( DataGridForeignKeyDescription description )
{
if( m_foreignKeyDescription != description )
{
m_foreignKeyDescription = description;
this.OnPropertyChanged( DataGridItemPropertyBase.ForeignKeyDescriptionPropertyName );
}
}
private DataGridForeignKeyDescription m_foreignKeyDescription; // = null;
#endregion
#region GroupSortStatResultPropertyName Property
public string GroupSortStatResultPropertyName
{
get
{
return m_groupSortStatResultPropertyName;
}
set
{
if( value == m_groupSortStatResultPropertyName )
return;
m_groupSortStatResultPropertyName = value;
this.OnPropertyChanged( DataGridItemPropertyBase.GroupSortStatResultPropertyNamePropertyName );
}
}
private string m_groupSortStatResultPropertyName;
#endregion
#region GroupSortStatResultComparer Property
public IComparer GroupSortStatResultComparer
{
get;
set;
}
#endregion
#region IsDisplayable Property
public bool IsDisplayable
{
get
{
return m_flags[ DataGridItemPropertyBaseFlags.IsDisplayable ];
}
set
{
if( this.IsSealed )
throw new InvalidOperationException( "An attempt was made to change the IsDisplayable property of a DataGridItemProperty already added to a containing collection." );
this.SetIsDisplayable( value );
}
}
internal void SetIsDisplayable( bool value )
{
m_flags[ DataGridItemPropertyBaseFlags.IsDisplayable ] = value;
}
#endregion
#region ItemProperties Property
public DataGridItemPropertyCollection ItemProperties
{
get
{
if( m_itemProperties == null )
{
Interlocked.CompareExchange( ref m_itemProperties, new DataGridItemPropertyCollection( this ), null );
Debug.Assert( m_itemProperties != null );
this.OnPropertyChanged( DataGridItemPropertyBase.ItemPropertiesInternalPropertyName );
}
return m_itemProperties;
}
}
internal DataGridItemPropertyCollection ItemPropertiesInternal
{
get
{
return m_itemProperties;
}
}
private DataGridItemPropertyCollection m_itemProperties;
#endregion
#region FieldName Internal Property
internal virtual string FieldName
{
get
{
return this.Name;
}
}
#endregion
#region IsNameSealed Internal Property
internal bool IsNameSealed
{
get
{
return m_flags[ DataGridItemPropertyBaseFlags.IsNameSealed ];
}
set
{
if( value == this.IsNameSealed )
return;
m_flags[ DataGridItemPropertyBaseFlags.IsNameSealed ] = value;
this.OnPropertyChanged( DataGridItemPropertyBase.IsNameSealedPropertyName );
}
}
#endregion
#region IsSealed Internal Property
internal bool IsSealed
{
get
{
return m_flags[ DataGridItemPropertyBaseFlags.IsSealed ];
}
set
{
if( value == this.IsSealed )
return;
m_flags[ DataGridItemPropertyBaseFlags.IsSealed ] = value;
this.OnPropertyChanged( DataGridItemPropertyBase.IsSealedPropertyName );
}
}
#endregion
#region IsBrowsable Internal Property
// That property only indicates for the DefaultProperties generated if the property should take place in the real property list by default.
internal bool IsBrowsable
{
get
{
return m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ];
}
set
{
m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ] = value;
}
}
#endregion
#region IsASubRelationship Internal Property
internal bool IsASubRelationship
{
get
{
if( m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] )
return m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ];
if( m_dataType == null )
return false;
bool isASubRelationship = ItemsSourceHelper.IsASubRelationship( m_dataType );
if( this.IsSealed )
{
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ] = isASubRelationship;
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] = true;
}
return isASubRelationship;
}
}
private void SetIsASubRelationship( Nullable<bool> isASubRelationship )
{
if( isASubRelationship.HasValue )
{
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ] = isASubRelationship.Value;
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] = true;
}
else
{
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet
| DataGridItemPropertyBaseFlags.IsASubRelationship ] = false;
}
}
#endregion
#region IsSortingOnForeignKeyDescription Internal Property
internal bool IsSortingOnForeignKeyDescription
{
get;
set;
}
#endregion
#region ContainingCollection Internal Property
internal DataGridItemPropertyCollection ContainingCollection
{
get
{
return m_containingCollection;
}
private set
{
if( value == m_containingCollection )
return;
if( ( value != null ) && ( m_containingCollection != null ) )
throw new InvalidOperationException( "The property is already assigned to a DataGridItemPropertyCollection." );
m_containingCollection = value;
this.OnPropertyChanged( DataGridItemPropertyBase.ContainingCollectionPropertyName );
}
}
private DataGridItemPropertyCollection m_containingCollection; //null
#endregion
#region ValueChanged Internal Event
internal event EventHandler<ValueChangedEventArgs> ValueChanged;
private void OnValueChanged( ValueChangedEventArgs e )
{
var handler = this.ValueChanged;
if( handler == null )
return;
handler.Invoke( this, e );
}
#endregion
#region DistinctValueSelector Event
public event EventHandler<QueryDistinctValueEventArgs> QueryDistinctValue
{
add
{
m_queryDistinctValue = ( EventHandler<QueryDistinctValueEventArgs> )Delegate.Combine( m_queryDistinctValue, value );
}
remove
{
m_queryDistinctValue = ( EventHandler<QueryDistinctValueEventArgs> )Delegate.Remove( m_queryDistinctValue, value );
}
}
private EventHandler<QueryDistinctValueEventArgs> m_queryDistinctValue;
internal object GetDistinctValueFromItem( object dataSourceValue )
{
if( m_queryDistinctValue == null )
return dataSourceValue;
QueryDistinctValueEventArgs args = new QueryDistinctValueEventArgs( dataSourceValue );
m_queryDistinctValue( this, args );
return args.DistinctValue;
}
#endregion
public object GetValue( object component )
{
var unboundDataItem = component as UnboundDataItem;
if( unboundDataItem != null )
{
component = unboundDataItem.DataItem;
}
// Since EmptyDataItemSafePropertyDescriptor ensures to return null to avoid Binding exceptions when a CollectionView other
// than the DataGridCollectionView is used, we must return null to avoid calling GetValueCore using null as component.
if( ( component == null ) || ( component is EmptyDataItem ) )
return null;
return this.GetValueCore( component );
}
public void SetValue( object component, object value )
{
var unboundDataItem = component as UnboundDataItem;
if( unboundDataItem != null )
{
component = unboundDataItem.DataItem;
}
if( component == null )
throw new InvalidOperationException( "An attempt was made to set a value on a null data item." );
if( component is EmptyDataItem )
throw new InvalidOperationException( "An attempt was made to set a value on an empty data item." );
if( this.IsReadOnly && !this.OverrideReadOnlyForInsertion.GetValueOrDefault( false ) )
throw new InvalidOperationException( "An attempt was made to set a read-only property." );
this.SetValueCore( component, value );
}
[Browsable( false )]
[EditorBrowsable( EditorBrowsableState.Never )]
[Obsolete( "The ICloneable interface is no longer supported.", true )]
public virtual object Clone()
{
throw new NotSupportedException();
}
protected abstract object GetValueCore( object component );
protected virtual void SetValueCore( object component, object value )
{
this.OnValueChanged( new ValueChangedEventArgs( component ) );
}
internal PropertyDescriptorFromItemPropertyBase GetPropertyDescriptorForBinding()
{
if( m_propertyDescriptorFromItemProperty == null )
{
m_propertyDescriptorFromItemProperty = this.GetPropertyDescriptorForBindingCore();
}
return m_propertyDescriptorFromItemProperty;
}
internal virtual PropertyDescriptorFromItemPropertyBase GetPropertyDescriptorForBindingCore()
{
return new PropertyDescriptorFromItemPropertyBase( this );
}
internal virtual void SetUnspecifiedPropertiesValues( PropertyDescription description, Type itemType, bool defaultItemPropertiesCreated )
{
}
internal void AttachToContainingCollection( DataGridItemPropertyCollection collection )
{
if( collection == null )
throw new ArgumentNullException( "collection" );
this.ContainingCollection = collection;
}
internal void DetachFromContainingCollection()
{
this.ContainingCollection = null;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged( string propertyName )
{
var handler = this.PropertyChanged;
if( handler == null )
return;
handler.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
#endregion
private PropertyDescriptorFromItemPropertyBase m_propertyDescriptorFromItemProperty;
private BitFlags m_flags;
#region ValueChangedEventArgs Internal Class
internal class ValueChangedEventArgs : EventArgs
{
public ValueChangedEventArgs( object component )
{
this.Component = component;
}
public object Component
{
get;
private set;
}
}
#endregion
#region BitFlags Private Struct
private struct BitFlags
{
internal bool this[ DataGridItemPropertyBaseFlags flag ]
{
get
{
return ( ( m_data & flag ) == flag );
}
set
{
this.CheckIfIsDefined( flag );
if( value )
{
m_data |= flag;
}
else
{
m_data &= ~flag;
}
}
}
[Conditional( "DEBUG" )]
private void CheckIfIsDefined( DataGridItemPropertyBaseFlags value )
{
if( Enum.IsDefined( typeof( DataGridItemPropertyBaseFlags ), value ) )
return;
int flags = Convert.ToInt32( value );
foreach( var flag in Enum.GetValues( typeof( DataGridItemPropertyBaseFlags ) ) )
{
int flagValue = Convert.ToInt32( flag );
if( ( flags & flagValue ) == flagValue )
{
flags &= ~flagValue;
if( flags == 0 )
break;
}
}
Debug.Assert( flags == 0 );
}
private DataGridItemPropertyBaseFlags m_data;
}
#endregion
#region DataGridItemPropertyBaseFlags Private Enum
[Flags]
private enum DataGridItemPropertyBaseFlags : ushort
{
IsReadOnly = 0x0001,
IsOverrideReadOnlyForInsertionSet = 0x0002,
IsOverrideReadOnlyForInsertion = 0x0004,
IsASubRelationshipSet = 0x0008,
IsASubRelationship = 0x0010,
CalculateDistinctValues = 0x0020,
IsCalculateDistinctValuesInitialized = 0x0040,
IsNameSealed = 0x0080,
IsSealed = 0x0100,
IsBrowsable = 0x0200,
IsDisplayable = 0x0400,
}
#endregion
}
}

978
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyCollection.cs

@ -1,978 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Xceed.Utils.Wpf;
using Xceed.Wpf.DataGrid.Utils;
namespace Xceed.Wpf.DataGrid
{
[DebuggerDisplay( "Count = {Count}" )]
public sealed class DataGridItemPropertyCollection :
IList<DataGridItemPropertyBase>,
IList,
ICollection<DataGridItemPropertyBase>,
ICollection,
IEnumerable<DataGridItemPropertyBase>,
IEnumerable,
INotifyCollectionChanged,
INotifyPropertyChanged
{
#region Static Fields
private static readonly string CountPropertyName = PropertyHelper.GetPropertyName( ( DataGridItemPropertyCollection c ) => c.Count );
private static readonly string ItemsPropertyName = "Item[]";
#endregion
internal DataGridItemPropertyCollection()
: this( null )
{
}
internal DataGridItemPropertyCollection( DataGridItemPropertyBase owner )
{
m_owner = owner;
}
#region [] Property
public DataGridItemPropertyBase this[ string name ]
{
get
{
if( !string.IsNullOrEmpty( name ) )
{
DataGridItemPropertyBase item;
if( m_nameToItem.TryGetValue( name, out item ) )
return item;
}
return null;
}
set
{
if( value == null )
throw new ArgumentNullException( "value" );
if( string.IsNullOrEmpty( value.Name ) )
throw new ArgumentException( "An attempt was made to add an item that does not have a name.", "value" );
if( value.Name != name )
throw new ArgumentException( "The item's name is not the same as the parameter.", "name" );
var oldItem = this[ name ];
if( oldItem == null )
{
this.InsertItemAndNotify( m_collection.Count, value );
}
else
{
if( value == oldItem )
return;
var index = this.IndexOf( oldItem );
Debug.Assert( index >= 0 );
this.ReplaceItemAndNotify( index, oldItem, value );
}
}
}
#endregion
#region DataGridItemPropertyBase Internal Owner
internal DataGridItemPropertyBase Owner
{
get
{
return m_owner;
}
}
private readonly DataGridItemPropertyBase m_owner;
#endregion
#region SyncRoot Private Property
private object SyncRoot
{
get
{
return ( ( ICollection )this ).SyncRoot;
}
}
#endregion
#region ItemPropertyGroupSortStatNameChanged Internal Event
internal event EventHandler ItemPropertyGroupSortStatNameChanged;
private void OnItemPropertyGroupSortStatNameChanged()
{
var handler = this.ItemPropertyGroupSortStatNameChanged;
if( handler == null )
return;
handler.Invoke( this, EventArgs.Empty );
}
#endregion
#region InitializeItemProperty Internal Event
internal event EventHandler<InitializeItemPropertyEventArgs> InitializeItemProperty;
private void OnInitializeItemProperty( DataGridItemPropertyBase itemProperty )
{
var handler = this.InitializeItemProperty;
if( handler == null )
return;
handler.Invoke( this, new InitializeItemPropertyEventArgs( itemProperty ) );
}
private void RelayInitializeItemProperty( InitializeItemPropertyEventArgs e )
{
var handler = this.InitializeItemProperty;
if( handler == null )
return;
Debug.Assert( e != null );
handler.Invoke( this, e );
}
#endregion
internal IDisposable DeferCollectionChanged()
{
return new DeferredDisposable( new DeferState( this ) );
}
internal bool Contains( string name )
{
if( string.IsNullOrEmpty( name ) )
return false;
return m_nameToItem.ContainsKey( name );
}
internal DataGridItemPropertyBase GetForSynonym( string name )
{
if( string.IsNullOrEmpty( name ) )
return null;
DataGridItemPropertyBase[] synonyms;
if( !m_synonymToItem.TryGetValue( name, out synonyms ) )
return null;
Debug.Assert( synonyms.Length > 0 );
if( synonyms.Length <= 0 )
return null;
return synonyms[ 0 ];
}
internal void RefreshUnboundItemProperty( object component )
{
if( m_unboundItems.Count <= 0 || ( component == null ) )
return;
var unboundDataItem = UnboundDataItem.GetUnboundDataItem( component );
if( unboundDataItem == null )
return;
var dataItem = unboundDataItem.DataItem;
if( ( dataItem == null ) || ( dataItem is EmptyDataItem ) )
return;
State state;
if( m_dataItems.TryGetValue( dataItem, out state ) && ( state.Refreshing || state.Suspended ) )
return;
m_dataItems.Add( dataItem, new State( true, false ) );
try
{
foreach( var item in m_unboundItems )
{
item.Refresh( unboundDataItem );
}
}
finally
{
state = m_dataItems[ dataItem ];
if( state.Suspended )
{
m_dataItems[ dataItem ] = new State( false, true );
}
else
{
m_dataItems.Remove( dataItem );
}
}
}
internal void SuspendUnboundItemPropertyChanged( object component )
{
if( component == null )
return;
var unboundDataItem = UnboundDataItem.GetUnboundDataItem( component );
if( unboundDataItem == null )
return;
var dataItem = unboundDataItem.DataItem;
if( ( dataItem == null ) || ( dataItem is EmptyDataItem ) )
return;
State state;
bool refreshing = false;
if( m_dataItems.TryGetValue( dataItem, out state ) )
{
if( state.Suspended )
return;
refreshing = state.Refreshing;
}
m_dataItems[ dataItem ] = new State( refreshing, true );
}
internal void ResumeUnboundItemPropertyChanged( object component )
{
if( component == null )
return;
var unboundDataItem = UnboundDataItem.GetUnboundDataItem( component );
if( unboundDataItem == null )
return;
var dataItem = unboundDataItem.DataItem;
if( ( dataItem == null ) || ( dataItem is EmptyDataItem ) )
return;
State state;
if( !m_dataItems.TryGetValue( dataItem, out state ) || !state.Suspended )
{
Debug.Fail( "The item is not suspended." );
return;
}
if( state.Refreshing )
{
m_dataItems[ dataItem ] = new State( true, false );
}
else
{
m_dataItems.Remove( dataItem );
this.RefreshUnboundItemProperty( dataItem );
}
}
private static NotifyCollectionChangedEventArgs Combine( NotifyCollectionChangedEventArgs x, NotifyCollectionChangedEventArgs y )
{
if( x == null )
return y;
if( y == null )
return x;
var addedItems = DataGridItemPropertyCollection.GetAddedItems( x ).ToList();
var removedItems = DataGridItemPropertyCollection.GetRemovedItems( x ).ToList();
foreach( var item in DataGridItemPropertyCollection.GetAddedItems( y ) )
{
if( !removedItems.Remove( item ) )
{
Debug.Assert( !addedItems.Contains( item ) );
addedItems.Add( item );
}
}
foreach( var item in DataGridItemPropertyCollection.GetRemovedItems( y ) )
{
if( !addedItems.Remove( item ) )
{
Debug.Assert( !removedItems.Contains( item ) );
removedItems.Add( item );
}
}
var addedItemsCount = addedItems.Count;
var removedItemsCount = removedItems.Count;
if( ( addedItemsCount > 0 ) && ( removedItemsCount > 0 ) )
{
if( ( x.Action != NotifyCollectionChangedAction.Replace ) || ( y.Action != NotifyCollectionChangedAction.Replace ) || ( addedItemsCount != removedItemsCount ) )
throw new NotSupportedException();
return new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace, addedItems, removedItems );
}
if( addedItemsCount > 0 )
return new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Add, addedItems );
if( removedItemsCount > 0 )
return new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Remove, removedItems );
return null;
}
private static IEnumerable<DataGridItemPropertyBase> GetAddedItems( NotifyCollectionChangedEventArgs source )
{
if( ( source != null ) && ( source.NewItems != null ) )
return source.NewItems.Cast<DataGridItemPropertyBase>();
return Enumerable.Empty<DataGridItemPropertyBase>();
}
private static IEnumerable<DataGridItemPropertyBase> GetRemovedItems( NotifyCollectionChangedEventArgs source )
{
if( ( source != null ) && ( source.OldItems != null ) )
return source.OldItems.Cast<DataGridItemPropertyBase>();
return Enumerable.Empty<DataGridItemPropertyBase>();
}
private void InsertItemAndNotify( int index, DataGridItemPropertyBase item )
{
this.InsertItem( index, item );
this.OnPropertyChanged( DataGridItemPropertyCollection.CountPropertyName );
this.OnPropertyChanged( DataGridItemPropertyCollection.ItemsPropertyName );
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Add, item, index ) );
}
private void ReplaceItemAndNotify( int index, DataGridItemPropertyBase oldItem, DataGridItemPropertyBase newItem )
{
this.RemoveItem( index, oldItem );
this.InsertItem( index, newItem );
this.OnPropertyChanged( DataGridItemPropertyCollection.ItemsPropertyName );
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace, newItem, oldItem, index ) );
}
private void RemoveItemAndNotify( int index, DataGridItemPropertyBase item )
{
this.RemoveItem( index, item );
this.OnPropertyChanged( DataGridItemPropertyCollection.CountPropertyName );
this.OnPropertyChanged( DataGridItemPropertyCollection.ItemsPropertyName );
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Remove, item, index ) );
}
private void InsertItem( int index, DataGridItemPropertyBase item )
{
Debug.Assert( ( index >= 0 ) && ( index <= m_collection.Count ) );
Debug.Assert( item != null );
Debug.Assert( !string.IsNullOrEmpty( item.Name ) );
var name = item.Name;
if( m_nameToItem.ContainsKey( name ) )
throw new InvalidOperationException( "An item with the same name is already in the collection." );
if( item.ContainingCollection != null )
throw new InvalidOperationException( "The item is already contained in a collection." );
item.IsNameSealed = true;
m_collection.Insert( index, item );
m_nameToItem.Add( name, item );
var unboundItem = item as DataGridUnboundItemProperty;
if( unboundItem != null )
{
m_unboundItems.Add( unboundItem );
}
item.AttachToContainingCollection( this );
this.OnInitializeItemProperty( item );
this.RegisterEvents( item );
item.IsSealed = true;
}
private void RemoveItem( int index, DataGridItemPropertyBase item )
{
Debug.Assert( ( index >= 0 ) && ( index < m_collection.Count ) );
Debug.Assert( item != null );
Debug.Assert( object.ReferenceEquals( item, m_collection[ index ] ) );
this.UnregisterEvents( item );
m_collection.RemoveAt( index );
m_nameToItem.Remove( item.Name );
var unboundItem = item as DataGridUnboundItemProperty;
if( unboundItem != null )
{
m_unboundItems.Remove( unboundItem );
}
this.RemoveSynonym( item );
this.ClearItem( item );
}
private void AddSynonym( DataGridItemPropertyBase item )
{
Debug.Assert( item != null );
var synonym = item.Synonym;
if( string.IsNullOrEmpty( synonym ) )
return;
DataGridItemPropertyBase[] synonyms;
if( m_synonymToItem.TryGetValue( synonym, out synonyms ) )
{
Array.Resize( ref synonyms, synonyms.Length + 1 );
}
else
{
Array.Resize( ref synonyms, 1 );
}
synonyms[ synonyms.Length - 1 ] = item;
m_synonymToItem[ synonym ] = synonyms;
}
private void RemoveSynonym( DataGridItemPropertyBase item )
{
Debug.Assert( item != null );
var synonym = item.Synonym;
if( string.IsNullOrEmpty( synonym ) )
return;
DataGridItemPropertyBase[] synonyms;
if( !m_synonymToItem.TryGetValue( synonym, out synonyms ) )
return;
var removeAt = Array.IndexOf( synonyms, item );
Debug.Assert( removeAt >= 0 );
if( removeAt < 0 )
return;
if( synonyms.Length > 1 )
{
for( int i = removeAt + 1; i < synonyms.Length; i++ )
{
synonyms[ i - 1 ] = synonyms[ i ];
}
Array.Resize( ref synonyms, synonyms.Length - 1 );
m_synonymToItem[ synonym ] = synonyms;
}
else
{
m_synonymToItem.Remove( synonym );
}
}
private void ClearItem( DataGridItemPropertyBase item )
{
Debug.Assert( item != null );
item.IsNameSealed = false;
item.IsSealed = false;
item.DetachFromContainingCollection();
}
private void RegisterEvents( DataGridItemPropertyBase item )
{
Debug.Assert( item != null );
item.PropertyChanged += new PropertyChangedEventHandler( this.OnItemPropertyChanged );
item.ValueChanged += new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( this.OnItemValueChanged );
if( item.ItemPropertiesInternal != null )
{
item.ItemPropertiesInternal.InitializeItemProperty += new EventHandler<InitializeItemPropertyEventArgs>( this.OnItemInitializeItemProperty );
}
}
private void UnregisterEvents( DataGridItemPropertyBase item )
{
Debug.Assert( item != null );
item.PropertyChanged -= new PropertyChangedEventHandler( this.OnItemPropertyChanged );
item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( this.OnItemValueChanged );
if( item.ItemPropertiesInternal != null )
{
item.ItemPropertiesInternal.InitializeItemProperty -= new EventHandler<InitializeItemPropertyEventArgs>( this.OnItemInitializeItemProperty );
}
}
private void OnItemPropertyChanged( object sender, PropertyChangedEventArgs e )
{
var item = ( DataGridItemPropertyBase )sender;
var propertyName = e.PropertyName;
if( string.IsNullOrEmpty( e.PropertyName ) || ( propertyName == DataGridItemPropertyBase.GroupSortStatResultPropertyNamePropertyName ) )
{
this.OnItemPropertyGroupSortStatNameChanged();
}
if( string.IsNullOrEmpty( e.PropertyName ) || ( propertyName == DataGridItemPropertyBase.ItemPropertiesInternalPropertyName ) )
{
this.OnItemItemPropertiesInternalChanged( ( DataGridItemPropertyBase )sender );
}
if( string.IsNullOrEmpty( e.PropertyName ) || ( propertyName == DataGridItemPropertyBase.IsSealedPropertyName ) )
{
if( item.IsSealed )
{
this.AddSynonym( item );
}
else
{
this.RemoveSynonym( item );
}
}
}
private void OnItemValueChanged( object sender, DataGridItemPropertyBase.ValueChangedEventArgs e )
{
this.RefreshUnboundItemProperty( e.Component );
}
private void OnItemItemPropertiesInternalChanged( DataGridItemPropertyBase itemProperty )
{
if( ( itemProperty == null ) || ( itemProperty.ItemPropertiesInternal == null ) )
return;
itemProperty.ItemPropertiesInternal.InitializeItemProperty += new EventHandler<InitializeItemPropertyEventArgs>( this.OnItemInitializeItemProperty );
}
private void OnItemInitializeItemProperty( object sender, InitializeItemPropertyEventArgs e )
{
var itemProperties = sender as DataGridItemPropertyCollection;
if( itemProperties == null )
return;
this.RelayInitializeItemProperty( e );
}
#region IList<> Members
public DataGridItemPropertyBase this[ int index ]
{
get
{
if( ( index < 0 ) || ( index >= m_collection.Count ) )
throw new ArgumentOutOfRangeException( "index" );
return m_collection[ index ];
}
set
{
if( ( index < 0 ) || ( index > m_collection.Count ) )
throw new ArgumentOutOfRangeException( "index" );
if( value == null )
throw new ArgumentNullException( "value" );
if( string.IsNullOrEmpty( value.Name ) )
throw new ArgumentException( "The item must have a non empty name.", "value" );
if( index < m_collection.Count )
{
var oldItem = m_collection[ index ];
if( value == oldItem )
return;
this.ReplaceItemAndNotify( index, oldItem, value );
}
else
{
this.InsertItemAndNotify( index, value );
}
}
}
public int IndexOf( DataGridItemPropertyBase item )
{
if( !this.Contains( item ) )
return -1;
return m_collection.IndexOf( item );
}
public void Insert( int index, DataGridItemPropertyBase item )
{
if( ( index < 0 ) || ( index > m_collection.Count ) )
throw new ArgumentOutOfRangeException( "index" );
if( item == null )
throw new ArgumentNullException( "item" );
if( string.IsNullOrEmpty( item.Name ) )
throw new ArgumentException( "The item must have a non empty name.", "item" );
this.InsertItemAndNotify( index, item );
}
public void RemoveAt( int index )
{
if( ( index < 0 ) || ( index >= m_collection.Count ) )
throw new ArgumentOutOfRangeException( "index" );
this.RemoveItemAndNotify( index, m_collection[ index ] );
}
#endregion
#region IList Members
bool IList.IsFixedSize
{
get
{
return false;
}
}
bool IList.IsReadOnly
{
get
{
return ( ( ICollection<DataGridItemPropertyBase> )this ).IsReadOnly;
}
}
object IList.this[ int index ]
{
get
{
return this[ index ];
}
set
{
this[ index ] = ( DataGridItemPropertyBase )value;
}
}
int IList.Add( object value )
{
var item = value as DataGridItemPropertyBase;
if( item == null )
return -1;
this.Add( item );
return m_collection.Count - 1;
}
bool IList.Contains( object value )
{
return this.Contains( value as DataGridItemPropertyBase );
}
int IList.IndexOf( object value )
{
var item = value as DataGridItemPropertyBase;
if( !this.Contains( item ) )
return -1;
return m_collection.IndexOf( item );
}
void IList.Insert( int index, object value )
{
this.Insert( index, ( DataGridItemPropertyBase )value );
}
void IList.Remove( object value )
{
this.Remove( value as DataGridItemPropertyBase );
}
void IList.RemoveAt( int index )
{
this.RemoveAt( index );
}
#endregion
#region ICollection<> Members
bool ICollection<DataGridItemPropertyBase>.IsReadOnly
{
get
{
return false;
}
}
public void Add( DataGridItemPropertyBase item )
{
this.Insert( m_collection.Count, item );
}
public void Clear()
{
if( m_collection.Count == 0 )
return;
var removedItems = m_collection.ToList();
m_collection.Clear();
m_nameToItem.Clear();
m_synonymToItem.Clear();
m_unboundItems.Clear();
foreach( var item in removedItems )
{
this.UnregisterEvents( item );
this.ClearItem( item );
}
this.OnPropertyChanged( DataGridItemPropertyCollection.CountPropertyName );
this.OnPropertyChanged( DataGridItemPropertyCollection.ItemsPropertyName );
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Remove, removedItems ) );
}
public bool Contains( DataGridItemPropertyBase item )
{
if( item == null )
return false;
var name = item.Name;
if( string.IsNullOrEmpty( name ) )
return false;
DataGridItemPropertyBase stored;
if( !m_nameToItem.TryGetValue( name, out stored ) )
return false;
return ( item == stored );
}
void ICollection<DataGridItemPropertyBase>.CopyTo( DataGridItemPropertyBase[] array, int index )
{
m_collection.CopyTo( array, index );
}
public bool Remove( DataGridItemPropertyBase item )
{
if( !this.Contains( item ) )
return false;
var index = m_collection.IndexOf( item );
Debug.Assert( index >= 0 );
this.RemoveItemAndNotify( index, item );
return true;
}
#endregion
#region ICollection Members
public int Count
{
get
{
return m_collection.Count;
}
}
bool ICollection.IsSynchronized
{
get
{
return false;
}
}
object ICollection.SyncRoot
{
get
{
return ( ( ICollection )m_collection ).SyncRoot;
}
}
void ICollection.CopyTo( Array array, int index )
{
( ( ICollection )m_collection ).CopyTo( array, index );
}
#endregion
#region IEnumerable<> Members
public IEnumerator<DataGridItemPropertyBase> GetEnumerator()
{
return m_collection.GetEnumerator();
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
#endregion
#region INotifyCollectionChanged Members
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void OnCollectionChanged( NotifyCollectionChangedEventArgs e )
{
if( e.Action == NotifyCollectionChangedAction.Reset )
throw new NotSupportedException();
var handler = this.CollectionChanged;
if( handler == null )
return;
lock( this.SyncRoot )
{
if( m_deferCollectionChangedCount != 0 )
{
m_deferCollectionChangedEventArgs = DataGridItemPropertyCollection.Combine( m_deferCollectionChangedEventArgs, e );
return;
}
}
handler.Invoke( this, e );
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged( string propertyName )
{
var handler = this.PropertyChanged;
if( handler == null )
return;
handler.Invoke( this, new PropertyChangedEventArgs( propertyName ) );
}
#endregion
private int m_deferCollectionChangedCount; //0
private NotifyCollectionChangedEventArgs m_deferCollectionChangedEventArgs; //null
private readonly List<DataGridItemPropertyBase> m_collection = new List<DataGridItemPropertyBase>();
private readonly Dictionary<string, DataGridItemPropertyBase> m_nameToItem = new Dictionary<string, DataGridItemPropertyBase>();
private readonly Dictionary<string, DataGridItemPropertyBase[]> m_synonymToItem = new Dictionary<string, DataGridItemPropertyBase[]>();
private readonly HashSet<DataGridUnboundItemProperty> m_unboundItems = new HashSet<DataGridUnboundItemProperty>();
private readonly Dictionary<object, State> m_dataItems = new Dictionary<object, State>( 0 );
#region DeferState Private Class
private sealed class DeferState : DeferredDisposableState
{
internal DeferState( DataGridItemPropertyCollection target )
{
Debug.Assert( target != null );
m_target = target;
}
protected override object SyncRoot
{
get
{
return m_target.SyncRoot;
}
}
protected override bool IsDeferred
{
get
{
return ( m_target.m_deferCollectionChangedCount != 0 );
}
}
protected override void Increment()
{
m_target.m_deferCollectionChangedCount++;
}
protected override void Decrement()
{
m_target.m_deferCollectionChangedCount--;
}
protected override void OnDeferEnding( bool disposing )
{
m_eventArgs = m_target.m_deferCollectionChangedEventArgs;
m_target.m_deferCollectionChangedEventArgs = null;
base.OnDeferEnding( disposing );
}
protected override void OnDeferEnded( bool disposing )
{
if( m_eventArgs == null )
return;
m_target.OnCollectionChanged( m_eventArgs );
}
private readonly DataGridItemPropertyCollection m_target;
private NotifyCollectionChangedEventArgs m_eventArgs;
}
#endregion
#region State Private Struct
private struct State
{
internal State( bool refreshing, bool suspended )
{
this.Refreshing = refreshing;
this.Suspended = suspended;
}
internal readonly bool Refreshing;
internal readonly bool Suspended;
}
#endregion
}
}

35
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyCommittingValue.cs

@ -1,35 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemPropertyCommittingValueEventArgs : EventArgs
{
public DataGridItemPropertyCommittingValueEventArgs( object item, object value )
{
this.Item = item;
this.Value = value;
}
public object Item { get; private set; }
public object Value { get; private set; }
}
}

47
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyDictionary.cs

@ -1,47 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemPropertyDictionary : Dictionary<DataGridItemPropertyBase, object>
{
internal DataGridItemPropertyDictionary()
{
}
public object this[ string name ]
{
get
{
foreach( object item in this.Keys )
{
DataGridItemPropertyBase dataGridItemProperty = item as DataGridItemPropertyBase;
Debug.Assert( dataGridItemProperty != null );
if( dataGridItemProperty.Name.Equals( name ) )
return this[ dataGridItemProperty ];
}
return null;
}
}
}
}

625
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyMap.cs

@ -1,625 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using Xceed.Utils.Wpf;
namespace Xceed.Wpf.DataGrid
{
internal sealed class DataGridItemPropertyMap : IWeakEventListener
{
#region MasterItemProperties Property
internal DataGridItemPropertyCollection MasterItemProperties
{
get
{
return m_masterItemProperties;
}
set
{
if( value == m_masterItemProperties )
return;
using( this.DeferMappingChanged() )
{
this.UnregisterItemProperties( m_masterItemProperties );
this.UnmapItemProperties();
m_masterItemProperties = value;
this.MapItemProperties();
this.RegisterItemProperties( m_masterItemProperties );
}
}
}
private DataGridItemPropertyCollection m_masterItemProperties;
#endregion
#region DetailItemProperties Property
internal DataGridItemPropertyCollection DetailItemProperties
{
get
{
return m_detailItemProperties;
}
set
{
if( value == m_detailItemProperties )
return;
using( this.DeferMappingChanged() )
{
this.UnregisterItemProperties( m_detailItemProperties );
this.UnmapItemProperties();
m_detailItemProperties = value;
this.MapItemProperties();
this.RegisterItemProperties( m_detailItemProperties );
}
}
}
private DataGridItemPropertyCollection m_detailItemProperties;
#endregion
#region IsMapping Property
internal bool IsMapping
{
get
{
return ( m_masterItemProperties != null )
&& ( m_detailItemProperties != null );
}
}
#endregion
#region MappingChanged Event
internal event EventHandler MappingChanged;
private void OnMappingChanged()
{
if( m_deferRaiseMappingChangedCount != 0 )
{
m_raiseMappingChanged = true;
}
else
{
m_raiseMappingChanged = false;
var handler = this.MappingChanged;
if( handler == null )
return;
handler.Invoke( this, EventArgs.Empty );
}
}
#endregion
internal IDisposable DeferMappingChanged()
{
return new DeferredDisposable( new DeferMappingChangedEvent( this ) );
}
internal bool TryGetMasterItemProperty( DataGridItemPropertyBase detailItemProperty, out DataGridItemPropertyBase masterItemProperty )
{
return DataGridItemPropertyMap.TryGetTargetItemProperty( m_detailToMaster, detailItemProperty, out masterItemProperty );
}
internal bool TryGetDetailItemProperty( DataGridItemPropertyBase masterItemProperty, out DataGridItemPropertyBase detailItemProperty )
{
return DataGridItemPropertyMap.TryGetTargetItemProperty( m_masterToDetail, masterItemProperty, out detailItemProperty );
}
private static bool TryGetTargetItemProperty( Dictionary<DataGridItemPropertyBase, DataGridItemPropertyBase> collection, DataGridItemPropertyBase sourceItemProperty, out DataGridItemPropertyBase targetItemProperty )
{
if( ( collection != null ) && ( sourceItemProperty != null ) && collection.TryGetValue( sourceItemProperty, out targetItemProperty ) )
return true;
targetItemProperty = default( DataGridItemPropertyBase );
return false;
}
private void RegisterItemProperties( DataGridItemPropertyCollection itemProperties )
{
if( itemProperties == null )
return;
CollectionChangedEventManager.AddListener( itemProperties, this );
foreach( var itemProperty in itemProperties )
{
this.RegisterItemProperty( itemProperty );
}
}
private void UnregisterItemProperties( DataGridItemPropertyCollection itemProperties )
{
if( itemProperties == null )
return;
foreach( var itemProperty in itemProperties )
{
this.UnregisterItemProperty( itemProperty );
}
CollectionChangedEventManager.RemoveListener( itemProperties, this );
}
private void RegisterItemProperty( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return;
if( !m_listeningToPropertyChanged.Add( itemProperty ) )
return;
PropertyChangedEventManager.AddListener( itemProperty, this, string.Empty );
this.RegisterItemProperties( itemProperty.ItemPropertiesInternal );
}
private void UnregisterItemProperty( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return;
if( !m_listeningToPropertyChanged.Remove( itemProperty ) )
return;
this.UnregisterItemProperties( itemProperty.ItemPropertiesInternal );
PropertyChangedEventManager.RemoveListener( itemProperty, this, string.Empty );
}
private void MapItemProperties()
{
this.MapItemProperties( m_masterItemProperties, m_detailItemProperties );
}
private void MapItemProperties( DataGridItemPropertyCollection masterItemProperties, DataGridItemPropertyCollection detailItemProperties )
{
if( ( masterItemProperties == null ) || ( masterItemProperties.Count <= 0 ) )
return;
foreach( var masterItemProperty in masterItemProperties )
{
this.MapMasterItemProperty( masterItemProperty );
}
}
private void MapItemProperties( DataGridItemPropertyBase masterItemProperty, DataGridItemPropertyBase detailItemProperty )
{
if( ( masterItemProperty == null ) || ( detailItemProperty == null ) )
return;
DataGridItemPropertyBase mappedItemProperty;
if( m_masterToDetail.TryGetValue( masterItemProperty, out mappedItemProperty ) )
{
if( mappedItemProperty == detailItemProperty )
return;
this.UnmapMasterItemProperty( masterItemProperty );
}
this.UnmapDetailItemProperty( detailItemProperty );
m_masterToDetail[ masterItemProperty ] = detailItemProperty;
m_detailToMaster[ detailItemProperty ] = masterItemProperty;
this.OnMappingChanged();
this.MapItemProperties( masterItemProperty.ItemPropertiesInternal, detailItemProperty.ItemPropertiesInternal );
}
private void MapMasterItemProperty( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return;
var collection = itemProperty.ContainingCollection;
if( collection == null )
return;
DataGridItemPropertyCollection mappedItemProperties;
DataGridItemPropertyBase mappedItemProperty;
var owner = collection.Owner;
if( owner == null )
{
Debug.Assert( collection == m_masterItemProperties );
if( collection != m_masterItemProperties )
return;
mappedItemProperties = m_detailItemProperties;
}
else
{
if( !m_masterToDetail.TryGetValue( owner, out mappedItemProperty ) )
return;
mappedItemProperties = mappedItemProperty.ItemPropertiesInternal;
}
if( mappedItemProperties == null )
return;
mappedItemProperty = mappedItemProperties.GetForSynonym( itemProperty.Name );
if( mappedItemProperty != null )
{
this.MapItemProperties( itemProperty, mappedItemProperty );
}
else
{
this.UnmapMasterItemProperty( itemProperty );
}
}
private void MapDetailItemProperty( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return;
var collection = itemProperty.ContainingCollection;
if( collection == null )
return;
DataGridItemPropertyCollection mappedItemProperties;
DataGridItemPropertyBase mappedItemProperty;
var owner = collection.Owner;
if( owner == null )
{
Debug.Assert( collection == m_detailItemProperties );
if( collection != m_detailItemProperties )
return;
mappedItemProperties = m_masterItemProperties;
}
else
{
if( !m_detailToMaster.TryGetValue( owner, out mappedItemProperty ) )
return;
mappedItemProperties = mappedItemProperty.ItemPropertiesInternal;
}
if( mappedItemProperties == null )
return;
mappedItemProperty = ( !string.IsNullOrEmpty( itemProperty.Synonym ) ) ? mappedItemProperties[ itemProperty.Synonym ] : null;
if( mappedItemProperty != null )
{
this.MapItemProperties( mappedItemProperty, itemProperty );
}
else
{
this.UnmapDetailItemProperty( itemProperty );
}
}
private void UnmapItemProperties()
{
if( ( m_masterItemProperties == null ) || ( m_detailItemProperties == null ) )
return;
while( m_masterToDetail.Count > 0 )
{
var entry = m_masterToDetail.First();
this.UnmapItemProperties( entry.Key, entry.Value, false );
}
Debug.Assert( m_masterToDetail.Count == 0 );
Debug.Assert( m_detailToMaster.Count == 0 );
while( m_detailToMaster.Count > 0 )
{
var entry = m_detailToMaster.First();
this.UnmapItemProperties( entry.Value, entry.Key, false );
}
m_masterToDetail.Clear();
m_detailToMaster.Clear();
}
private void UnmapItemProperties( DataGridItemPropertyBase masterItemProperty, DataGridItemPropertyBase detailItemProperty, bool recursive )
{
if( ( masterItemProperty == null ) || ( detailItemProperty == null ) )
return;
DataGridItemPropertyBase mappedItemProperty;
if( !m_masterToDetail.TryGetValue( masterItemProperty, out mappedItemProperty ) || ( mappedItemProperty != detailItemProperty ) )
throw new InvalidOperationException();
if( !m_detailToMaster.TryGetValue( detailItemProperty, out mappedItemProperty ) || ( mappedItemProperty != masterItemProperty ) )
throw new InvalidOperationException();
m_masterToDetail.Remove( masterItemProperty );
m_detailToMaster.Remove( detailItemProperty );
this.OnMappingChanged();
if( recursive )
{
this.UnmapMasterItemProperties( masterItemProperty.ItemPropertiesInternal );
this.UnmapDetailItemProperties( detailItemProperty.ItemPropertiesInternal );
}
}
private void UnmapMasterItemProperties( DataGridItemPropertyCollection itemProperties )
{
if( itemProperties == null )
return;
foreach( var itemProperty in itemProperties )
{
this.UnmapMasterItemProperty( itemProperty );
}
}
private void UnmapDetailItemProperties( DataGridItemPropertyCollection itemProperties )
{
if( itemProperties == null )
return;
foreach( var itemProperty in itemProperties )
{
this.UnmapDetailItemProperty( itemProperty );
}
}
private void UnmapMasterItemProperty( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return;
DataGridItemPropertyBase mappedItemProperty;
if( !m_masterToDetail.TryGetValue( itemProperty, out mappedItemProperty ) )
return;
Debug.Assert( mappedItemProperty != null );
this.UnmapItemProperties( itemProperty, mappedItemProperty, true );
}
private void UnmapDetailItemProperty( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return;
DataGridItemPropertyBase mappedItemProperty;
if( !m_detailToMaster.TryGetValue( itemProperty, out mappedItemProperty ) )
return;
Debug.Assert( mappedItemProperty != null );
this.UnmapItemProperties( mappedItemProperty, itemProperty, true );
}
private void OnItemPropertyCollectionChanged( DataGridItemPropertyCollection collection, NotifyCollectionChangedEventArgs e )
{
var rootCollection = ItemsSourceHelper.GetRootCollection( collection );
if( rootCollection == null )
return;
if( rootCollection == m_masterItemProperties )
{
if( e.Action == NotifyCollectionChangedAction.Reset )
throw new NotSupportedException();
if( e.Action == NotifyCollectionChangedAction.Move )
return;
using( this.DeferMappingChanged() )
{
if( e.OldItems != null )
{
foreach( DataGridItemPropertyBase itemProperty in e.OldItems )
{
this.UnregisterItemProperty( itemProperty );
this.UnmapMasterItemProperty( itemProperty );
}
}
if( e.NewItems != null )
{
foreach( DataGridItemPropertyBase itemProperty in e.NewItems )
{
this.RegisterItemProperty( itemProperty );
this.MapMasterItemProperty( itemProperty );
}
}
}
}
else if( rootCollection == m_detailItemProperties )
{
if( e.Action == NotifyCollectionChangedAction.Reset )
throw new NotSupportedException();
if( e.Action == NotifyCollectionChangedAction.Move )
return;
using( this.DeferMappingChanged() )
{
if( e.OldItems != null )
{
foreach( DataGridItemPropertyBase itemProperty in e.OldItems )
{
this.UnregisterItemProperty( itemProperty );
this.UnmapDetailItemProperty( itemProperty );
}
}
if( e.NewItems != null )
{
foreach( DataGridItemPropertyBase itemProperty in e.NewItems )
{
this.RegisterItemProperty( itemProperty );
this.MapDetailItemProperty( itemProperty );
}
}
}
}
else
{
Debug.Fail( "The collection should have been either for the master or the detail item properties." );
CollectionChangedEventManager.RemoveListener( collection, this );
}
}
private void OnItemPropertyPropertyChanged( DataGridItemPropertyBase itemProperty, PropertyChangedEventArgs e )
{
var rootCollection = ItemsSourceHelper.GetRootCollection( itemProperty );
if( rootCollection == null )
return;
using( this.DeferMappingChanged() )
{
if( string.IsNullOrEmpty( e.PropertyName ) || ( e.PropertyName == DataGridItemPropertyBase.SynonymPropertyName ) )
{
if( rootCollection == m_detailItemProperties )
{
this.MapDetailItemProperty( itemProperty );
}
}
if( string.IsNullOrEmpty( e.PropertyName ) || ( e.PropertyName == DataGridItemPropertyBase.ItemPropertiesInternalPropertyName ) )
{
var itemProperties = itemProperty.ItemPropertiesInternal;
if( itemProperties != null )
{
this.UnregisterItemProperties( itemProperties );
this.RegisterItemProperties( itemProperties );
if( rootCollection == m_masterItemProperties )
{
foreach( var childItemProperty in itemProperties )
{
this.MapMasterItemProperty( childItemProperty );
}
}
else if( rootCollection == m_detailItemProperties )
{
foreach( var childItemProperty in itemProperties )
{
this.MapDetailItemProperty( childItemProperty );
}
}
}
}
}
}
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( managerType == typeof( CollectionChangedEventManager ) )
{
this.OnItemPropertyCollectionChanged( ( DataGridItemPropertyCollection )sender, ( NotifyCollectionChangedEventArgs )e );
}
else if( managerType == typeof( PropertyChangedEventManager ) )
{
this.OnItemPropertyPropertyChanged( ( DataGridItemPropertyBase )sender, ( PropertyChangedEventArgs )e );
}
else
{
return false;
}
return true;
}
#endregion
private readonly Dictionary<DataGridItemPropertyBase, DataGridItemPropertyBase> m_masterToDetail = new Dictionary<DataGridItemPropertyBase, DataGridItemPropertyBase>();
private readonly Dictionary<DataGridItemPropertyBase, DataGridItemPropertyBase> m_detailToMaster = new Dictionary<DataGridItemPropertyBase, DataGridItemPropertyBase>();
private readonly HashSet<DataGridItemPropertyBase> m_listeningToPropertyChanged = new HashSet<DataGridItemPropertyBase>();
private int m_deferRaiseMappingChangedCount;
private bool m_raiseMappingChanged; //false
#region DeferMappingChangedEvent Private Class
private sealed class DeferMappingChangedEvent : DeferredDisposableState
{
internal DeferMappingChangedEvent( DataGridItemPropertyMap target )
{
if( target == null )
throw new ArgumentNullException( "target" );
m_target = target;
}
protected override object SyncRoot
{
get
{
return m_target.m_listeningToPropertyChanged;
}
}
protected override bool IsDeferred
{
get
{
return ( m_target.m_deferRaiseMappingChangedCount != 0 );
}
}
protected override void Increment()
{
m_target.m_deferRaiseMappingChangedCount++;
}
protected override void Decrement()
{
m_target.m_deferRaiseMappingChangedCount--;
}
protected override void OnDeferEnded( bool disposing )
{
if( !disposing )
return;
if( m_target.m_raiseMappingChanged )
{
m_target.OnMappingChanged();
}
}
private readonly DataGridItemPropertyMap m_target;
}
#endregion
}
}

118
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyMapHelper.cs

@ -1,118 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
namespace Xceed.Wpf.DataGrid
{
internal static class DataGridItemPropertyMapHelper
{
internal static bool TryGetMasterColumnName( DataGridItemPropertyMap itemPropertyMap, string detailColumnName, out string masterColumnName )
{
masterColumnName = default( string );
if( itemPropertyMap == null )
return false;
var detailItemProperty = ItemsSourceHelper.GetItemPropertyFromProperty( itemPropertyMap.DetailItemProperties, detailColumnName );
if( detailItemProperty == null )
return false;
DataGridItemPropertyBase masterItemProperty;
if( !itemPropertyMap.TryGetMasterItemProperty( detailItemProperty, out masterItemProperty ) )
return false;
masterColumnName = PropertyRouteParser.Parse( masterItemProperty );
return !string.IsNullOrEmpty( masterColumnName );
}
internal static bool TryGetDetailColumnName( DataGridItemPropertyMap itemPropertyMap, string masterColumnName, out string detailColumnName )
{
detailColumnName = default( string );
if( itemPropertyMap == null )
return false;
var masterItemProperty = ItemsSourceHelper.GetItemPropertyFromProperty( itemPropertyMap.MasterItemProperties, masterColumnName );
if( masterItemProperty == null )
return false;
DataGridItemPropertyBase detailItemProperty;
if( !itemPropertyMap.TryGetDetailItemProperty( masterItemProperty, out detailItemProperty ) )
return false;
detailColumnName = PropertyRouteParser.Parse( detailItemProperty );
return !string.IsNullOrEmpty( detailColumnName );
}
internal static bool TryGetMasterColumn( DataGridContext detailContext, ColumnBase detailColumn, out ColumnBase masterColumn )
{
if( detailContext != null )
{
var masterContext = detailContext.RootDataGridContext;
if( masterContext != null )
return DataGridItemPropertyMapHelper.TryGetMasterColumn( detailContext.ItemPropertyMap, masterContext.Columns, detailColumn, out masterColumn );
}
masterColumn = default( ColumnBase );
return false;
}
internal static bool TryGetDetailColumn( DataGridContext detailContext, ColumnBase masterColumn, out ColumnBase detailColumn )
{
if( detailContext != null )
return DataGridItemPropertyMapHelper.TryGetDetailColumn( detailContext.ItemPropertyMap, detailContext.Columns, masterColumn, out detailColumn );
detailColumn = default( ColumnBase );
return false;
}
internal static bool TryGetMasterColumn( DataGridItemPropertyMap itemPropertyMap, ColumnCollection masterColumns, ColumnBase detailColumn, out ColumnBase masterColumn )
{
masterColumn = default( ColumnBase );
if( ( masterColumns == null ) || ( detailColumn == null ) )
return false;
string masterColumnName;
if( !DataGridItemPropertyMapHelper.TryGetMasterColumnName( itemPropertyMap, detailColumn.FieldName, out masterColumnName ) )
return false;
masterColumn = masterColumns[ masterColumnName ];
return ( masterColumn != null );
}
internal static bool TryGetDetailColumn( DataGridItemPropertyMap itemPropertyMap, ColumnCollection detailColumns, ColumnBase masterColumn, out ColumnBase detailColumn )
{
detailColumn = default( ColumnBase );
if( ( detailColumns == null ) || ( masterColumn == null ) )
return false;
string detailColumnName;
if( !DataGridItemPropertyMapHelper.TryGetDetailColumnName( itemPropertyMap, masterColumn.FieldName, out detailColumnName ) )
return false;
detailColumn = detailColumns[ detailColumnName ];
return ( detailColumn != null );
}
}
}

34
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyQueryValueEvent.cs

@ -1,34 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemPropertyQueryValueEventArgs : EventArgs
{
public DataGridItemPropertyQueryValueEventArgs( object item )
{
this.Item = item;
}
public object Item { get; private set; }
public object Value { get; set; }
}
}

97
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyRoute.cs

@ -1,97 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal sealed class DataGridItemPropertyRoute
{
private DataGridItemPropertyRoute( DataGridItemPropertyBase itemProperty )
: this( itemProperty, null )
{
}
private DataGridItemPropertyRoute( DataGridItemPropertyBase itemProperty, DataGridItemPropertyRoute parent )
{
Debug.Assert( itemProperty != null );
m_itemProperty = itemProperty;
m_parent = parent;
}
#region Current Property
internal DataGridItemPropertyBase Current
{
get
{
return m_itemProperty;
}
}
private readonly DataGridItemPropertyBase m_itemProperty;
#endregion
#region Parent Property
internal DataGridItemPropertyRoute Parent
{
get
{
return m_parent;
}
}
private readonly DataGridItemPropertyRoute m_parent;
#endregion
internal static DataGridItemPropertyRoute Create( DataGridItemPropertyBase itemProperty )
{
if( itemProperty == null )
return null;
var collection = itemProperty.ContainingCollection;
if( collection == null )
return new DataGridItemPropertyRoute( itemProperty );
return new DataGridItemPropertyRoute(
itemProperty,
DataGridItemPropertyRoute.Create( collection.Owner ) );
}
internal static DataGridItemPropertyRoute Combine( DataGridItemPropertyBase itemProperty, DataGridItemPropertyRoute ancestors )
{
if( itemProperty == null )
return ancestors;
if( ancestors == null )
return DataGridItemPropertyRoute.Create( itemProperty );
var collection = itemProperty.ContainingCollection;
if( collection == null )
throw new InvalidOperationException();
if( collection.Owner != ancestors.Current )
throw new InvalidOperationException();
return new DataGridItemPropertyRoute( itemProperty, ancestors );
}
}
}

43
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemRemovedEvent.cs

@ -1,43 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridItemRemovedEventArgs : DataGridItemEventArgs
{
public DataGridItemRemovedEventArgs( DataGridCollectionViewBase collectionView, object item, int index )
: base( collectionView, item )
{
m_index = index;
}
#region Index Property
public int Index
{
get { return m_index; }
}
private int m_index;
#endregion Index Property
}
}

171
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridLINQPageManager.cs

@ -1,171 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridLINQPageManager : DataGridPageManagerBase
{
public DataGridLINQPageManager( DataGridVirtualizingQueryableCollectionView collectionView, object syncRoot, bool supportsPrimaryKeyOptimizations )
: base( collectionView )
{
m_supportsPrimaryKeyOptimizations = supportsPrimaryKeyOptimizations;
m_syncRoot = syncRoot;
}
protected override void DisposeCore()
{
m_syncRoot = null;
base.DisposeCore();
}
protected override int OnQueryItemCountCore( VirtualList virtualList )
{
if( !this.IsConnected )
return 0;
DataGridVirtualizingQueryableCollectionViewGroup collectionViewGroup =
this.GetLinkedCollectionViewGroup( virtualList ) as DataGridVirtualizingQueryableCollectionViewGroup;
Debug.Assert( collectionViewGroup != null );
return collectionViewGroup.QueryItemCount();
}
protected internal override void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
{
base.OnQueryItems( page, queryInfo );
DataGridVirtualizingQueryableCollectionViewGroup collectionViewGroup =
this.GetLinkedCollectionViewGroup( page.ParentVirtualList ) as DataGridVirtualizingQueryableCollectionViewGroup;
IQueryable queryableToUse;
int virtualItemCount = collectionViewGroup.VirtualItemCount;
bool queryableIsReversed;
if( ( !m_supportsPrimaryKeyOptimizations ) || ( queryInfo.StartIndex < ( virtualItemCount / 2 ) ) )
{
queryableIsReversed = false;
queryableToUse = collectionViewGroup.Queryable.Slice( queryInfo.StartIndex, queryInfo.RequestedItemCount );
}
else
{
queryableIsReversed = true;
int reversedStartIndex = virtualItemCount - ( queryInfo.StartIndex + queryInfo.RequestedItemCount );
queryableToUse = collectionViewGroup.ReversedQueryable.Slice( reversedStartIndex, queryInfo.RequestedItemCount );
}
System.Threading.ThreadPool.QueueUserWorkItem( new System.Threading.WaitCallback( this.AsyncGatherItems ), new object[] { queryInfo, queryableToUse, queryableIsReversed } );
}
protected internal override void OnQueryItemsCompleted( VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems )
{
DataGridVirtualizingQueryableCollectionView collectionView = this.CollectionView as DataGridVirtualizingQueryableCollectionView;
// The VirtualPageManager was Disposed
if( collectionView == null )
return;
using( collectionView.DeferRefresh() )
{
base.OnQueryItemsCompleted( page, queryInfo, fetchedItems );
}
}
private void AsyncGatherItems( object workItem )
{
object[] parameters = ( object[] )workItem;
AsyncQueryInfo queryInfo = parameters[ 0 ] as AsyncQueryInfo;
if( queryInfo.ShouldAbort )
return;
IQueryable queryable = ( IQueryable )parameters[ 1 ];
int requestedItemCount = queryInfo.RequestedItemCount;
object[] items = new object[ requestedItemCount ];
System.Collections.IEnumerator enumerator;
lock( m_syncRoot )
{
// We reverify here since a reset could have been issued while we were waiting on the lock statement.
if( ( queryInfo.ShouldAbort ) || ( !this.IsConnected ) || ( this.IsDisposed ) )
return;
try
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Beginning Provider Execute for page at start index: " + queryInfo.StartIndex.ToString() );
enumerator = queryable.GetEnumerator();
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Ended Provider Execute for page at start index: " + queryInfo.StartIndex.ToString() );
int i = 0;
while( enumerator.MoveNext() && ( i < requestedItemCount ) )
{
object current = enumerator.Current;
if( current != null )
{
items[ i ] = enumerator.Current;
i++;
}
}
}
catch( Exception exception )
{
// TimeOut exeception or other.
queryInfo.AbortQuery();
queryInfo.Error = exception.Message;
return;
}
}
items = items.Where( item => item != null ).ToArray();
try
{
if( items.Count() != requestedItemCount )
throw new InvalidOperationException( "The number of non-null items returned by the source must be equal to the provided item count." );
}
catch
{
//go silently here, in case the next sequance give a valid result. At the same time, if it does not, the dev has information when debugging.
}
bool queryableWasReversed = ( bool )parameters[ 2 ];
if( queryableWasReversed )
Array.Reverse( items );
queryInfo.EndQuery( items );
}
private object m_syncRoot;
private bool m_supportsPrimaryKeyOptimizations;
}
}

103
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridPageManager.cs

@ -1,103 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridPageManager : DataGridPageManagerBase
{
#region CONSTRUCTORS
public DataGridPageManager( DataGridVirtualizingCollectionView collectionView )
: base( collectionView )
{
}
#endregion CONSTRUCTORS
#region DATA VIRTUALIZATION
protected override int OnQueryItemCountCore( VirtualList virtualList )
{
if( !this.IsConnected )
return 0;
DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;
// The VirtualPageManager was Disposed
if( collectionView == null )
return 0;
DataGridVirtualizingCollectionViewGroup collectionViewGroup = this.GetLinkedCollectionViewGroup( virtualList ) as DataGridVirtualizingCollectionViewGroup;
Debug.Assert( ( collectionViewGroup != null ) && ( collectionView != null ) );
return collectionView.OnQueryItemCount( collectionViewGroup );
}
protected internal override void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
{
base.OnQueryItems( page, queryInfo );
DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;
// The VirtualPageManager was Disposed
if( collectionView == null )
return;
DataGridVirtualizingCollectionViewGroup collectionViewGroup = this.GetLinkedCollectionViewGroup( page.ParentVirtualList ) as DataGridVirtualizingCollectionViewGroup;
Debug.Assert( ( collectionViewGroup != null ) && ( collectionView != null ) );
collectionView.OnQueryItems( queryInfo, collectionViewGroup );
}
protected internal override void OnAbortQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
{
DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;
// The VirtualPageManager was Disposed
if( collectionView == null )
return;
DataGridVirtualizingCollectionViewGroup collectionViewGroup = this.GetLinkedCollectionViewGroup( page.ParentVirtualList ) as DataGridVirtualizingCollectionViewGroup;
collectionView.OnAbortQueryItems( queryInfo, collectionViewGroup );
base.OnAbortQueryItems( page, queryInfo );
}
protected internal override void OnQueryItemsCompleted( VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems )
{
DataGridVirtualizingCollectionView collectionView = this.CollectionView as DataGridVirtualizingCollectionView;
// The VirtualPageManager was Disposed
if( collectionView == null )
return;
using( collectionView.DeferRefresh() )
{
base.OnQueryItemsCompleted( page, queryInfo, fetchedItems );
}
}
#endregion DATA VIRTUALIZATION
}
}

584
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridPageManagerBase.cs

@ -1,584 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections;
using System.Windows.Threading;
using System.Collections.Specialized;
namespace Xceed.Wpf.DataGrid
{
internal abstract class DataGridPageManagerBase : VirtualPageManager, IEnumerable<object>, IEnumerable
{
#region STATIC MEMBERS
private static AsyncQueryInfoWeakComparer QueryInfoWeakComparer = new AsyncQueryInfoWeakComparer();
#endregion STATIC MEMBERS
public DataGridPageManagerBase( DataGridVirtualizingCollectionViewBase collectionView )
: base( collectionView.Dispatcher, collectionView.PageSize, collectionView.MaxRealizedItemCount, collectionView.PreemptivePageQueryRatio )
{
m_collectionView = collectionView;
m_virtualListVSCollectionViewGroupDictionary = new Dictionary<VirtualList, DataGridVirtualizingCollectionViewGroupBase>();
}
#region CollectionView Property
public DataGridVirtualizingCollectionViewBase CollectionView
{
get
{
return m_collectionView;
}
}
#endregion CollectionView Property
#region PUBLIC METHODS
public DataGridVirtualizingCollectionViewGroupBase GetLinkedCollectionViewGroup( VirtualList virtualItemList )
{
DataGridVirtualizingCollectionViewGroupBase collectionViewGroup;
m_virtualListVSCollectionViewGroupDictionary.TryGetValue( virtualItemList, out collectionViewGroup );
return collectionViewGroup;
}
public int GetGlobalIndexOf( object item )
{
ReadOnlyCollection<VirtualList> virtualItemLists = this.ManagedLists;
int virtualItemListsCount = virtualItemLists.Count;
for( int i = 0; i < virtualItemListsCount; i++ )
{
VirtualList localList = virtualItemLists[ i ];
int localIndex = localList.IndexOf( item );
if( localIndex >= 0 )
{
Debug.Assert( m_virtualListVSCollectionViewGroupDictionary.ContainsKey( localList ) );
DataGridVirtualizingCollectionViewGroupBase dgvcvg = m_virtualListVSCollectionViewGroupDictionary[ localList ];
return localIndex + dgvcvg.StartGlobalIndex;
}
}
return -1;
}
#endregion PUBLIC METHODS
#region PROTECTED METHODS
protected internal override void OnBuiltInAbort( VirtualPage page, AsyncQueryInfo queryInfo )
{
// When a built-in abort occurs, we ensure to remove
// any AsyncQueryInfo from references since the ConnectionState
// use this array to update its actual state
m_asyncQueryInfosInProgress.Remove( queryInfo );
// In case the page query was aborted when
// VirtualPageManager.CleanUpUnused is called
if( page.RemoveAfterOperation )
this.RemovePage( page );
this.UpdateConnectionState();
}
protected internal override void OnQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
{
// The VirtualPageManager is not connected to the CollectionView anymore,
// do NOT query items since it will be done by the new VirtualPageManager
// assigned to the same CollectionView
if( !this.IsConnected )
return;
Debug.Assert( !m_asyncQueryInfosInProgress.Contains( queryInfo ) );
m_asyncQueryInfosInProgress.Add( queryInfo );
if( m_asyncQueryInfosInError != null )
{
LinkedListNode<AsyncQueryInfo> queryInfoInErrorNode = m_asyncQueryInfosInError.First;
while( queryInfoInErrorNode != null )
{
if( DataGridPageManagerBase.QueryInfoWeakComparer.Equals( queryInfo, queryInfoInErrorNode.Value ) )
{
m_asyncQueryInfosInError.Remove( queryInfoInErrorNode );
break;
}
queryInfoInErrorNode = queryInfoInErrorNode.Next;
}
if( m_asyncQueryInfosInError.Count == 0 )
m_asyncQueryInfosInError = null;
}
this.UpdateConnectionState();
}
protected internal override void OnQueryItemsCompleted( VirtualPage page, AsyncQueryInfo queryInfo, object[] fetchedItems )
{
base.OnQueryItemsCompleted( page, queryInfo, fetchedItems );
Debug.Assert( m_asyncQueryInfosInProgress.Contains( queryInfo ) );
m_asyncQueryInfosInProgress.Remove( queryInfo );
this.UpdateConnectionState();
}
protected internal override void OnAbortQueryItems( VirtualPage page, AsyncQueryInfo queryInfo )
{
base.OnAbortQueryItems( page, queryInfo );
// It is possible that the queryInfo was removed previously
m_asyncQueryInfosInProgress.Remove( queryInfo );
// In case the page query was aborted when
// VirtualPageManager.CleanUpUnused is called
if( page.RemoveAfterOperation )
this.RemovePage( page );
this.UpdateConnectionState();
}
protected internal override void OnQueryErrorChanged( VirtualPage page, AsyncQueryInfo queryInfo )
{
base.OnQueryErrorChanged( page, queryInfo );
// It is possible that m_asyncQueryInfosInProgress does not contain the queryInfo when
// the query was aborted but the user did not stop the query and later on set the queryInfo error
// event if the queryInfo ShouldAbort is set to True.
Debug.Assert( ( m_asyncQueryInfosInProgress.Contains( queryInfo ) ) || ( queryInfo.ShouldAbort ) );
object error = queryInfo.Error;
if( error == null )
{
// Even if the queryInfo's ShouldAbort property is set to True, clean-up the error.
Debug.Assert( ( m_asyncQueryInfosInError != null ) && ( m_asyncQueryInfosInError.Contains( queryInfo ) ) );
m_asyncQueryInfosInError.Remove( queryInfo );
if( m_asyncQueryInfosInError.Count == 0 )
m_asyncQueryInfosInError = null;
}
else if( !queryInfo.ShouldAbort )
{
// Only add errors if the queryInfo's ShouldAbort property is set to False.
if( m_asyncQueryInfosInError == null )
m_asyncQueryInfosInError = new LinkedList<AsyncQueryInfo>();
if( m_asyncQueryInfosInError.Contains( queryInfo ) )
m_asyncQueryInfosInError.Remove( queryInfo );
m_asyncQueryInfosInError.AddFirst( queryInfo );
}
this.UpdateConnectionState();
}
protected override void OnVirtualPageManagerRestarting()
{
base.OnVirtualPageManagerRestarting();
// Keep a reference on the old CollectionViewGroupRoot of the
// parent CollectionView to be able to clear all references
// of this group after the VirtualPageManager is disposed
m_managerCollectionViewGroupRoot = m_collectionView.RootGroup;
}
protected override void OnVirtualPageManagerRestarted( bool shouldRefresh )
{
base.OnVirtualPageManagerRestarted( shouldRefresh );
// No need for a refresh since a new VirtualPageManager will
// be created and force QueryItemsCount and QueryItems using
// the same CollectionView
this.TryDispose();
}
protected internal override void OnCommitItems( VirtualPage page, AsyncCommitInfo commitInfo )
{
base.OnCommitItems( page, commitInfo );
Debug.Assert( !m_asyncCommitInfosInProgress.Contains( commitInfo ) );
m_asyncCommitInfosInProgress.Add( commitInfo );
this.UpdateConnectionState();
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "OnCommitItems for page " + page.ToString() );
m_collectionView.Dispatcher.BeginInvoke(
new Action<VirtualPage, AsyncCommitInfo>( this.RaiseCollectionViewOnCommitItems ),
DispatcherPriority.Background,
page,
commitInfo );
}
protected internal override void OnCommitItemsCompleted( VirtualPage page, AsyncCommitInfo commitInfo )
{
Debug.Assert( m_asyncCommitInfosInProgress.Contains( commitInfo ) );
m_asyncCommitInfosInProgress.Remove( commitInfo );
this.UpdateConnectionState();
base.OnCommitItemsCompleted( page, commitInfo );
// In case the page query was aborted when
// VirtualPageManager.CleanUpUnused is called
if( page.RemoveAfterOperation )
this.RemovePage( page );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "OnCommitItemsCompleted for page " + page.ToString() );
}
protected internal override void OnCommitErrorChanged( VirtualPage page, AsyncCommitInfo commitInfo )
{
base.OnCommitErrorChanged( page, commitInfo );
Debug.Assert( m_asyncCommitInfosInProgress.Contains( commitInfo ) );
object error = commitInfo.Error;
if( error == null )
{
Debug.Assert( ( m_asyncCommitInfosInError != null ) && ( m_asyncCommitInfosInError.Contains( commitInfo ) ) );
m_asyncCommitInfosInError.Remove( commitInfo );
if( m_asyncCommitInfosInError.Count == 0 )
m_asyncCommitInfosInError = null;
}
else
{
if( m_asyncCommitInfosInError == null )
m_asyncCommitInfosInError = new LinkedList<AsyncCommitInfo>();
if( m_asyncCommitInfosInError.Contains( commitInfo ) )
m_asyncCommitInfosInError.Remove( commitInfo );
m_asyncCommitInfosInError.AddFirst( commitInfo );
}
this.UpdateConnectionState();
}
protected void UnlinkVirtualListAndCollectionViewGroup( VirtualList virtualList )
{
DataGridVirtualizingCollectionViewGroupBase collectionViewGroup = null;
if( m_virtualListVSCollectionViewGroupDictionary.TryGetValue( virtualList, out collectionViewGroup ) )
{
CollectionChangedEventManager.RemoveListener( virtualList, collectionViewGroup );
m_virtualListVSCollectionViewGroupDictionary.Remove( virtualList );
}
}
protected override void DisposeCore()
{
// Remove every CollectionChanged WeakEventListener from the
// inner DataGridVirtualizingCollectionViewGroupBase
// and clear the references to them
Debug.Assert( m_virtualListVSCollectionViewGroupDictionary.Count == 0 );
// Dispose the RootGroup for which this manager
// was created
if( m_managerCollectionViewGroupRoot != null )
{
m_managerCollectionViewGroupRoot.Dispose();
m_managerCollectionViewGroupRoot = null;
}
// Force a PropertyChanged on the CollectionView
// for properties ConnectionState and Error to force
// bound countrol to update correctly using the values
// affected on the CollectionView by the new
// VirtualPageManager
if( m_collectionView != null )
{
m_collectionView.RefreshConnectionStateAndError();
m_collectionView = null;
}
base.DisposeCore();
}
protected internal override int OnQueryItemCount( VirtualList virtualList )
{
try
{
return base.OnQueryItemCount( virtualList );
}
finally
{
this.UpdateConnectionState();
}
}
#endregion PROTECTED METHODS
#region PRIVATE METHODS
private void TryDispose()
{
if( ( m_asyncCommitInfosInProgress.Count == 0 )
&& ( m_asyncCommitInfosInError == null )
&& ( m_asyncQueryInfosInError == null )
&& ( m_asyncQueryInfosInProgress.Count == 0 ) )
{
// At this point, all data was correctly committed.
// This manager is no more required, we can dispose
// it. This will force a dispose of all VirtualList,
// their inner VirtualListTableOfContent and Pages.
this.Dispose();
}
}
private void UpdateConnectionState()
{
// Never update the ConnectionState when disconnected
// from the CollectionView or Disposed since another
// VirtualPageManager will take care or updating it
if( !this.IsConnected || this.IsDisposed )
return;
DataGridConnectionState state = DataGridConnectionState.Idle;
object error = null;
if( m_asyncCommitInfosInError != null )
{
state = DataGridConnectionState.Error;
Debug.Assert( m_asyncCommitInfosInError.Count > 0 );
error = m_asyncCommitInfosInError.First.Value.Error;
}
else if( m_asyncQueryInfosInError != null )
{
state = DataGridConnectionState.Error;
Debug.Assert( m_asyncQueryInfosInError.Count > 0 );
error = m_asyncQueryInfosInError.First.Value.Error;
}
else if( m_asyncCommitInfosInProgress.Count > 0 )
{
state = DataGridConnectionState.Committing;
}
else if( m_asyncQueryInfosInProgress.Count > 0 )
{
state = DataGridConnectionState.Loading;
}
m_collectionView.UpdateConnectionState( state, error );
}
private void RaiseCollectionViewOnCommitItems( VirtualPage dispatchedPage, AsyncCommitInfo dispatchedCommitInfo )
{
DataGridVirtualizingCollectionViewBase collectionView = this.CollectionView as DataGridVirtualizingCollectionViewBase;
DataGridVirtualizingCollectionViewGroupBase collectionViewGroup =
this.GetLinkedCollectionViewGroup( dispatchedPage.ParentVirtualList ) as DataGridVirtualizingCollectionViewGroupBase;
Debug.Assert( ( collectionViewGroup != null ) && ( collectionView != null ) );
collectionView.OnCommitItems( dispatchedCommitInfo );
}
#endregion
#region INTERNAL METHODS
internal void LinkVirtualListAndCollectionViewGroup( VirtualList virtualItemList, DataGridVirtualizingCollectionViewGroupBase collectionViewGroup )
{
Debug.Assert( !m_virtualListVSCollectionViewGroupDictionary.ContainsKey( virtualItemList ) );
Debug.Assert( !m_virtualListVSCollectionViewGroupDictionary.ContainsValue( collectionViewGroup ) );
m_virtualListVSCollectionViewGroupDictionary.Add( virtualItemList, collectionViewGroup );
CollectionChangedEventManager.AddListener( virtualItemList, collectionViewGroup );
}
internal override void OnVirtualListRestarted( VirtualList virtualList )
{
this.UnlinkVirtualListAndCollectionViewGroup( virtualList );
base.OnVirtualListRestarted( virtualList );
}
#endregion INTERNAL METHODS
#region PRIVATE FIELDS
private DataGridVirtualizingCollectionViewGroupBase m_managerCollectionViewGroupRoot;
private DataGridVirtualizingCollectionViewBase m_collectionView;
private Dictionary<VirtualList, DataGridVirtualizingCollectionViewGroupBase> m_virtualListVSCollectionViewGroupDictionary;
private HashSet<AsyncQueryInfo> m_asyncQueryInfosInProgress = new HashSet<AsyncQueryInfo>();
private HashSet<AsyncCommitInfo> m_asyncCommitInfosInProgress = new HashSet<AsyncCommitInfo>();
private LinkedList<AsyncQueryInfo> m_asyncQueryInfosInError;
private LinkedList<AsyncCommitInfo> m_asyncCommitInfosInError;
#endregion PRIVATE FIELDS
#region IEnumerable<object> Members
public IEnumerator<object> GetEnumerator()
{
return new DataGridPageManagerEnumerator( this );
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return null;
}
#endregion
#region PRIVATE NESTED CLASSES
private class DataGridPageManagerEnumerator : IEnumerator<object>, IEnumerator
{
public DataGridPageManagerEnumerator( DataGridPageManagerBase dataGridPageManagerBase )
{
if( dataGridPageManagerBase == null )
throw new ArgumentNullException( "dataGridPageManagerBase" );
m_dataGridPageManagerBase = dataGridPageManagerBase;
VirtualList[] orderedVirtualLists =
m_dataGridPageManagerBase.m_virtualListVSCollectionViewGroupDictionary.Keys.OrderBy(
virtualList => m_dataGridPageManagerBase.m_virtualListVSCollectionViewGroupDictionary[ virtualList ].StartGlobalIndex ).ToArray();
m_orderedVirtualListEnumerators = new VirtualListEnumerator[ orderedVirtualLists.Length ];
for( int i = 0; i < orderedVirtualLists.Length; i++ )
{
m_orderedVirtualListEnumerators[ i ] = ( VirtualListEnumerator )( ( IEnumerable )orderedVirtualLists[ i ] ).GetEnumerator();
}
}
#region IEnumerator<object> Members
public object Current
{
get
{
return m_currentItem;
}
}
#endregion IEnumerator<object> Members
#region IDisposable Members
public void Dispose()
{
foreach( VirtualListEnumerator enumerator in m_orderedVirtualListEnumerators )
{
enumerator.Dispose();
}
m_orderedVirtualListEnumerators = null;
m_dataGridPageManagerBase = null;
m_currentItem = null;
}
#endregion
#region IEnumerator Members
public bool MoveNext()
{
// No need to check the VirtualPageManager's version. The sub VirtualLists' Enumerator will take care of it.
while( m_currentEnumeratorIndex < m_orderedVirtualListEnumerators.Length )
{
VirtualListEnumerator enumerator = m_orderedVirtualListEnumerators[ m_currentEnumeratorIndex ];
enumerator.MoveNext();
if( !enumerator.AfterEnd )
{
m_currentItem = enumerator.Current;
return true;
}
else
{
// Reached the end of this enumerator. Let's increment the currentEnumeratorIndex.
m_currentEnumeratorIndex++;
}
}
m_currentItem = null;
return false;
}
public void Reset()
{
m_currentEnumeratorIndex = 0;
m_currentItem = null;
}
object IEnumerator.Current
{
get
{
return this.Current;
}
}
bool IEnumerator.MoveNext()
{
return this.MoveNext();
}
void IEnumerator.Reset()
{
this.Reset();
}
#endregion IEnumerator Members
#region PRIVATE FIELDS
private DataGridPageManagerBase m_dataGridPageManagerBase;
private VirtualListEnumerator[] m_orderedVirtualListEnumerators;
private object m_currentItem;
private int m_currentEnumeratorIndex;
#endregion PRIVATE FIELDS
}
#endregion PRIVATE NESTED CLASSES
}
}

43
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridRemovingItemEvent.cs

@ -1,43 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class DataGridRemovingItemEventArgs : DataGridItemCancelEventArgs
{
public DataGridRemovingItemEventArgs( DataGridCollectionViewBase collectionView, object item, int index, bool cancel)
: base( collectionView, item, cancel )
{
m_index = index;
}
#region Index Property
public int Index
{
get { return m_index; }
}
private int m_index;
#endregion Index Property
}
}

130
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridSortDescriptionCollection.cs

@ -1,130 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridSortDescriptionCollection : SortDescriptionCollection
{
#region CONSTRUCTORS
public DataGridSortDescriptionCollection()
{
}
#endregion CONSTRUCTORS
#region IsResortDefered PROPERTY
public bool IsResortDefered
{
get
{
return ( m_deferResortCount > 0 );
}
}
#endregion IsResortDefered PROPERTY
#region SyncContext PROPERTY
public SortDescriptionsSyncContext SyncContext
{
get
{
return m_syncContext;
}
}
#endregion SyncContext PROPERTY
#region PUBLIC METHODS
public IDisposable DeferResort()
{
return new DeferResortDisposable( this );
}
public void AddResortNotification( IDisposable notificationObject )
{
Debug.Assert( m_deferResortCount > 0 );
lock( m_notificationList )
{
m_notificationList.Enqueue( notificationObject );
}
}
#endregion PUBLIC METHODS
#region PRIVATE FIELDS
private SortDescriptionsSyncContext m_syncContext = new SortDescriptionsSyncContext();
private int m_deferResortCount; // = 0
private Queue<IDisposable> m_notificationList = new Queue<IDisposable>();
#endregion PRIVATE FIELDS
#region NESTED CLASSES
private sealed class DeferResortDisposable : IDisposable
{
public DeferResortDisposable( DataGridSortDescriptionCollection parentCollection )
{
if( parentCollection == null )
throw new ArgumentNullException( "parentCollection" );
m_parentCollection = parentCollection;
m_parentCollection.m_deferResortCount++;
}
#region IDisposable Members
public void Dispose()
{
Debug.Assert( m_parentCollection.m_deferResortCount > 0 );
lock( m_parentCollection.m_notificationList )
{
m_parentCollection.m_deferResortCount--;
if( m_parentCollection.m_deferResortCount == 0 )
{
while( m_parentCollection.m_notificationList.Count > 0 )
{
IDisposable notificationObject = m_parentCollection.m_notificationList.Dequeue();
notificationObject.Dispose();
notificationObject = null;
}
}
}
m_parentCollection = null;
}
#endregion
private DataGridSortDescriptionCollection m_parentCollection; // = null
}
#endregion NESTED CLASSES
}
}

126
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridUnboundItemProperty.cs

@ -1,126 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.ComponentModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
[DebuggerDisplay( "Name = {Name}" )]
public class DataGridUnboundItemProperty : DataGridItemPropertyBase
{
public DataGridUnboundItemProperty()
{
}
public DataGridUnboundItemProperty( string name, Type dataType )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "The name must not be null (Nothing in Visual Basic) or empty.", "name" );
if( dataType == null )
throw new ArgumentNullException( "dataType" );
this.Initialize( name, null, dataType, null, null, null, null );
}
public DataGridUnboundItemProperty( string name, Type dataType, bool isReadOnly )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "The name must not be null (Nothing in Visual Basic) or empty.", "name" );
if( dataType == null )
throw new ArgumentNullException( "dataType" );
this.Initialize( name, null, dataType, isReadOnly, null, null, null );
}
public DataGridUnboundItemProperty( string name, Type dataType, bool isReadOnly, bool overrideReadOnlyForInsertion )
{
if( string.IsNullOrEmpty( name ) )
throw new ArgumentException( "The name must not be null (Nothing in Visual Basic) or empty.", "name" );
if( dataType == null )
throw new ArgumentNullException( "dataType" );
this.Initialize( name, null, dataType, isReadOnly, overrideReadOnlyForInsertion, null, null );
}
[Browsable( false )]
[EditorBrowsable( EditorBrowsableState.Never )]
[Obsolete( "This constructor is obsolete and should no longer be used.", true )]
protected DataGridUnboundItemProperty( DataGridUnboundItemProperty template )
{
throw new NotSupportedException();
}
public event EventHandler<DataGridItemPropertyQueryValueEventArgs> QueryValue;
public event EventHandler<DataGridItemPropertyCommittingValueEventArgs> CommittingValue;
protected override object GetValueCore( object component )
{
var handler = this.QueryValue;
if( handler == null )
return null;
var e = new DataGridItemPropertyQueryValueEventArgs( component );
handler.Invoke( this, e );
return e.Value;
}
protected override void SetValueCore( object component, object value )
{
var handler = this.CommittingValue;
if( handler != null )
{
handler.Invoke( this, new DataGridItemPropertyCommittingValueEventArgs( component, value ) );
}
base.SetValueCore( component, value );
}
internal void Refresh( object component )
{
var propertyDescriptor = this.GetPropertyDescriptorForBinding();
if( propertyDescriptor == null )
return;
propertyDescriptor.RaiseValueChanged( component );
}
internal override void SetUnspecifiedPropertiesValues(
PropertyDescription description,
Type itemType,
bool defaultItemPropertiesCreated )
{
if( this.DataType == null )
throw new InvalidOperationException( "An attempt was made to add an item without specifying its data type." );
if( string.IsNullOrEmpty( this.Title ) )
{
this.Title = this.Name;
}
if( !this.OverrideReadOnlyForInsertion.HasValue )
{
this.OverrideReadOnlyForInsertion = false;
}
}
}
}

155
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionView.cs

@ -1,155 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Xceed.Utils.Collections;
using System.Data;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
public sealed class DataGridVirtualizingCollectionView : DataGridVirtualizingCollectionViewBase
{
#region CONSTRUCTORS
public DataGridVirtualizingCollectionView()
: this( null, typeof( object ), true, DataGridVirtualizingCollectionViewBase.DefaultPageSize, DataGridVirtualizingCollectionViewBase.DefaultMaxRealizedItemCount )
{
}
public DataGridVirtualizingCollectionView( Type itemType )
: this( null, itemType, true, DataGridVirtualizingCollectionViewBase.DefaultPageSize, DataGridVirtualizingCollectionViewBase.DefaultMaxRealizedItemCount )
{
}
public DataGridVirtualizingCollectionView( Type itemType, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount )
: this( null, itemType, autoCreateItemProperties, pageSize, maxRealizedItemCount )
{
}
public DataGridVirtualizingCollectionView( DataTable sourceSchema )
: this( sourceSchema, typeof( object ), true, DataGridVirtualizingCollectionViewBase.DefaultPageSize, DataGridVirtualizingCollectionViewBase.DefaultMaxRealizedItemCount )
{
}
public DataGridVirtualizingCollectionView( DataTable sourceSchema, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount )
: this( sourceSchema, typeof( object ), autoCreateItemProperties, pageSize, maxRealizedItemCount )
{
}
private DataGridVirtualizingCollectionView( DataTable sourceSchema, Type itemType, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount )
: base( sourceSchema, itemType, autoCreateItemProperties, pageSize, maxRealizedItemCount )
{
}
#endregion CONSTRUCTORS
#region DATA VIRTUALIZATION
public event EventHandler<QueryItemCountEventArgs> QueryItemCount;
internal int OnQueryItemCount( DataGridVirtualizingCollectionViewGroup collectionViewGroup )
{
QueryItemCountEventArgs e = new QueryItemCountEventArgs( this, collectionViewGroup );
if( this.QueryItemCount != null )
this.QueryItemCount( this, e );
DataGridVirtualizingCollectionViewSource source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSource;
if( source != null )
source.OnQueryItemCount( e );
return e.Count;
}
public event EventHandler<QueryGroupsEventArgs> QueryGroups;
internal List<GroupNameCountPair> OnQueryGroups( DataGridVirtualizingCollectionViewGroup parentGroup )
{
ObservableCollection<GroupDescription> groupDescriptions = this.GroupDescriptions;
int nextLevel = parentGroup.Level + 1;
Debug.Assert( ( groupDescriptions != null ) && ( groupDescriptions.Count > nextLevel ) );
QueryGroupsEventArgs e = new QueryGroupsEventArgs( this, parentGroup, groupDescriptions[ nextLevel ] );
if( this.QueryGroups != null )
this.QueryGroups( this, e );
DataGridVirtualizingCollectionViewSource source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSource;
if( source != null )
source.OnQueryGroups( e );
return e.ChildGroupNameCountPairs;
}
public event EventHandler<QueryItemsEventArgs> AbortQueryItems;
internal void OnAbortQueryItems( AsyncQueryInfo asyncQueryInfo, DataGridVirtualizingCollectionViewGroup collectionViewGroup )
{
QueryItemsEventArgs e = new QueryItemsEventArgs( this, collectionViewGroup, asyncQueryInfo );
if( this.AbortQueryItems != null )
this.AbortQueryItems( this, e );
DataGridVirtualizingCollectionViewSource source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSource;
if( source != null )
source.OnAbortQueryItems( e );
}
public event EventHandler<QueryItemsEventArgs> QueryItems;
internal void OnQueryItems( AsyncQueryInfo asyncQueryInfo, DataGridVirtualizingCollectionViewGroup collectionViewGroup )
{
QueryItemsEventArgs e = new QueryItemsEventArgs( this, collectionViewGroup, asyncQueryInfo );
if( this.QueryItems != null )
this.QueryItems( this, e );
DataGridVirtualizingCollectionViewSource source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSource;
if( source != null )
source.OnQueryItems( e );
}
#endregion DATA VIRTUALIZATION
internal override IEnumerator GetVirtualEnumerator()
{
return ( ( DataGridVirtualizingCollectionViewGroupRoot )this.RootGroup ).GetVirtualPageManager().GetEnumerator();
}
internal override DataGridVirtualizingCollectionViewGroupBase CreateNewRootGroup()
{
bool rootIsBottomLevel = ( this.GroupDescriptions == null ) ? true : ( this.GroupDescriptions.Count == 0 );
return new DataGridVirtualizingCollectionViewGroupRoot( this, rootIsBottomLevel );
}
}
}

977
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewBase.cs

@ -1,977 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
public abstract class DataGridVirtualizingCollectionViewBase : DataGridCollectionViewBase
{
#region STATIC MEMBERS
internal const int DefaultMaxRealizedItemCount = 1000;
internal const int DefaultPageSize = 200;
internal const double DefaultPreemptivePageQueryRatio = 0.25;
#endregion STATIC MEMBERS
#region CONSTRUCTORS
internal DataGridVirtualizingCollectionViewBase( object sourceModel, Type itemType, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount )
: base( sourceModel, null, itemType, autoCreateItemProperties, false, false )
{
if( itemType == null )
{
itemType = typeof( object );
}
if( pageSize < 1 )
throw new ArgumentOutOfRangeException( "pageSize", pageSize, "pageSize must be greater than zero." );
if( maxRealizedItemCount < 1 )
throw new ArgumentOutOfRangeException( "maxRealizedItemCount", maxRealizedItemCount, "maxRealizedItemCount must be greater than zero." );
if( maxRealizedItemCount < pageSize )
{
maxRealizedItemCount = pageSize;
}
m_pageSize = pageSize;
m_maxRealizedItemCount = maxRealizedItemCount;
m_preemptivePageQueryRatio = DataGridVirtualizingCollectionViewBase.DefaultPreemptivePageQueryRatio;
}
internal override DataGridCollectionViewBase CreateDetailDataGridCollectionViewBase(
IEnumerable detailDataSource,
DataGridDetailDescription parentDetailDescription,
DataGridCollectionViewBase parentDataGridCollectionViewBase )
{
throw new NotImplementedException();
}
#endregion
#region CollectionView Members
public override bool CanGroup
{
get
{
return true;
}
}
public override bool CanFilter
{
get
{
return false;
}
}
public override IEnumerable SourceCollection
{
get
{
// VirtualizingDataGridCollectionView does not have a source.
return null;
}
}
public override bool Contains( object item )
{
if( item == null )
return false;
return ( this.IndexOf( item ) != -1 );
}
public override bool IsEmpty
{
get
{
return ( this.Count == 0 );
}
}
public override int IndexOf( object item )
{
this.EnsureThreadAndCollectionLoaded();
return this.RootGroup.GetGlobalIndexOf( item );
}
public override object GetItemAt( int index )
{
this.EnsureThreadAndCollectionLoaded();
if( index < 0 )
return null;
return this.RootGroup.GetItemAtGlobalIndex( index );
}
#endregion CollectionView Members
#region Currency management
public override object CurrentItem
{
get
{
if( ( !this.Loaded ) || ( this.IsCurrentBeforeFirst ) || ( this.IsCurrentAfterLast ) )
return null;
return base.CurrentItem;
}
}
public override bool MoveCurrentToPosition( int position )
{
if( position == this.CurrentPosition )
return ( this.CurrentItem != null );
this.EnsureThreadAndCollectionLoaded();
return this.SetCurrentItem( position, true );
}
private bool SetCurrentItem( int newCurrentPosition, bool isCancelable )
{
int count = this.Count;
if( ( newCurrentPosition < -1 ) || ( newCurrentPosition > count ) )
throw new ArgumentOutOfRangeException( "newCurrentPosition", "The current position must be greater than -1 and less than Count." );
object newCurrentItem = null;
if( ( newCurrentPosition >= 0 ) && ( newCurrentPosition < count ) )
newCurrentItem = this.GetItemAt( newCurrentPosition );
return this.SetCurrentItem( newCurrentPosition, newCurrentItem, isCancelable, false );
}
private bool SetCurrentItem( int newCurrentPosition, object newCurrentItem, bool isCancelable, bool beforeDeleteOperation )
{
object oldCurrentItem = this.CurrentItem;
int oldCurrentPosition = this.CurrentPosition;
bool oldIsCurrentBeforeFirst = this.IsCurrentBeforeFirst;
bool oldIsCurrentAfterLast = this.IsCurrentAfterLast;
if( ( !object.Equals( oldCurrentItem, newCurrentItem ) ) || ( oldCurrentPosition != newCurrentPosition ) )
{
// We raise the changing event even if we are in DeferCurrencyEvent
CurrentChangingEventArgs currentChangingEventArgs = new CurrentChangingEventArgs( isCancelable );
this.OnCurrentChanging( currentChangingEventArgs );
if( ( !currentChangingEventArgs.Cancel ) || ( !currentChangingEventArgs.IsCancelable ) )
{
int count = this.Count;
if( beforeDeleteOperation )
{
Debug.Assert( count > 0 );
count--;
}
bool isCurrentBeforeFirst;
bool isCurrentAfterLast;
if( count == 0 )
{
isCurrentBeforeFirst = true;
isCurrentAfterLast = true;
}
else
{
isCurrentBeforeFirst = newCurrentPosition < 0;
isCurrentAfterLast = newCurrentPosition >= count;
}
#if DEBUG
if( newCurrentItem == null )
Debug.Assert( ( newCurrentPosition == -1 ) || ( newCurrentPosition >= ( count - 1 ) ) );
#endif
this.SetCurrentItemAndPositionCore(
newCurrentItem, newCurrentPosition, isCurrentBeforeFirst, isCurrentAfterLast );
if( !this.IsCurrencyDeferred )
{
if( !object.Equals( oldCurrentItem, newCurrentItem ) )
this.OnPropertyChanged( new PropertyChangedEventArgs( "CurrentItem" ) );
if( oldCurrentPosition != this.CurrentPosition )
this.OnPropertyChanged( new PropertyChangedEventArgs( "CurrentPosition" ) );
if( oldIsCurrentBeforeFirst != this.IsCurrentBeforeFirst )
this.OnPropertyChanged( new PropertyChangedEventArgs( "IsCurrentBeforeFirst" ) );
if( oldIsCurrentAfterLast != this.IsCurrentAfterLast )
this.OnPropertyChanged( new PropertyChangedEventArgs( "IsCurrentAfterLast" ) );
this.OnCurrentChanged();
}
}
}
return ( newCurrentItem != null );
}
private void SaveCurrentBeforeReset( out int oldCurrentPosition )
{
Debug.Assert( this.Loaded );
if( this.IsCurrentAfterLast )
{
oldCurrentPosition = int.MaxValue;
}
else
{
oldCurrentPosition = this.CurrentPosition;
}
}
private void AdjustCurrencyAfterReset( int oldCurrentPosition )
{
if( oldCurrentPosition < 0 )
{
this.SetCurrentItem( -1, null, false, false );
return;
}
int count = this.Count;
if( oldCurrentPosition == int.MaxValue )
{
this.SetCurrentItem( count, null, false, false );
return;
}
if( oldCurrentPosition >= count )
{
this.SetCurrentItem( count - 1, false );
return;
}
this.SetCurrentItem( oldCurrentPosition, false );
}
#endregion Currency management
#region IEnumerable Members
protected override IEnumerator GetEnumerator()
{
this.EnsureThreadAndCollectionLoaded();
return this.GetVirtualEnumerator();
}
internal abstract IEnumerator GetVirtualEnumerator();
#endregion
#region Count Property
public override int Count
{
get
{
this.EnsureThreadAndCollectionLoaded();
int count = this.RootGroup.VirtualItemCount;
if( count > 0 )
return count;
return 0;
}
}
#endregion Count Property
#region DistinctValues Management
private void ResetDistinctValues()
{
}
#endregion
#region PageSize Property
public int PageSize
{
get
{
return m_pageSize;
}
set
{
if( m_pageSize != value )
{
m_pageSize = value;
// Cannot modify this PageManager property. Must Refresh which will recreate the CollectionViewGroupRoot
// and the DataGridVirtualPageManagerBase taking the new pageSize into account.
this.Refresh();
this.OnPropertyChanged( new PropertyChangedEventArgs( "PageSize" ) );
}
}
}
#endregion PageSize Property
#region MaxRealizedItemCount Property
public int MaxRealizedItemCount
{
get
{
return m_maxRealizedItemCount;
}
set
{
if( m_maxRealizedItemCount != value )
{
m_maxRealizedItemCount = value;
if( value < this.PageSize )
{
value = this.PageSize;
}
// Cannot modify this PageManager property. Must Refresh which will recreate the CollectionViewGroupRoot
// and the DataGridVirtualPageManagerBase taking the new pageSize into account.
this.Refresh();
this.OnPropertyChanged( new PropertyChangedEventArgs( "MaxRealizedItemCount" ) );
}
}
}
#endregion MaxRealizedItemCount Property
#region PreemptivePageQueryRatio Property
public double PreemptivePageQueryRatio
{
get
{
return m_preemptivePageQueryRatio;
}
set
{
if( m_preemptivePageQueryRatio != value )
{
m_preemptivePageQueryRatio = value;
// Cannot modify this PageManager property. Must Refresh which will recreate the CollectionViewGroupRoot
// and the DataGridVirtualPageManagerBase taking the new pageSize into account.
this.Refresh();
this.OnPropertyChanged( new PropertyChangedEventArgs( "PreemptivePageQueryRatio" ) );
}
}
}
#endregion PreemptivePageQueryRatio Property
#region CommitMode Property
public CommitMode CommitMode
{
get
{
return m_commitMode;
}
set
{
if( m_commitMode != value )
{
m_commitMode = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "CommitMode" ) );
}
}
}
#endregion CommitMode Property
#region DATA VIRTUALIZATION
public void CommitAll()
{
this.RootGroup.GetVirtualPageManager().CommitAll();
}
public event EventHandler<CommitItemsEventArgs> CommitItems;
internal void OnCommitItems( AsyncCommitInfo asyncCommitInfo )
{
CommitItemsEventArgs e = new CommitItemsEventArgs( this, asyncCommitInfo );
if( this.CommitItems != null )
this.CommitItems( this, e );
DataGridVirtualizingCollectionViewSourceBase source = this.ParentCollectionViewSourceBase as DataGridVirtualizingCollectionViewSourceBase;
if( source != null )
source.OnCommitItems( e );
}
public DataGridConnectionState ConnectionState
{
get
{
return m_connectionState;
}
private set
{
if( m_connectionState != value )
{
m_connectionState = value;
this.RefreshConnectionState();
}
}
}
private void RefreshConnectionState()
{
this.OnPropertyChanged( new PropertyChangedEventArgs( "ConnectionState" ) );
this.OnConnectionStateChanged();
}
public object ConnectionError
{
get
{
return m_connectionError;
}
private set
{
if( m_connectionError != value )
{
m_connectionError = value;
this.RefreshConnectionError();
}
}
}
private void RefreshConnectionError()
{
this.OnPropertyChanged( new PropertyChangedEventArgs( "ConnectionError" ) );
this.OnConnectionErrorChanged();
}
internal void RefreshConnectionStateAndError()
{
this.RefreshConnectionState();
this.RefreshConnectionError();
}
internal void UpdateConnectionState( DataGridConnectionState connectionState, object error )
{
this.ConnectionState = connectionState;
this.ConnectionError = error;
}
#endregion DATA VIRTUALIZATION
#region PUBLIC METHODS
public override void CommitNew()
{
// We are not calling base since the intended behavior is quite different with Virtualizing collection views.
object currentAddItem = this.CurrentAddItem;
if( currentAddItem == null )
return;
DataGridCommittingNewItemEventArgs committingNewItemEventArgs = new DataGridCommittingNewItemEventArgs( this, currentAddItem, false );
this.RootDataGridCollectionViewBase.OnCommittingNewItem( committingNewItemEventArgs );
if( committingNewItemEventArgs.Cancel )
throw new DataGridException( "CommitNew was canceled." );
if( !committingNewItemEventArgs.Handled )
throw new InvalidOperationException( "When manually handling the item-insertion process the CreatingNewItem, CommittingNewItem, and CancelingNewItem events must all be handled." );
// Contrarily to the data bound collection views, we do not care about the new index or new count since we will enqueue a Refresh operation.
this.SetCurrentAddNew( null, -1 );
this.ExecuteOrQueueSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ) );
}
public override bool MoveCurrentTo( object item )
{
m_canSynchronizeSelectionWithCurrent = true;
bool ret = base.MoveCurrentTo( item );
m_canSynchronizeSelectionWithCurrent = false;
return ret;
}
public override bool MoveCurrentToFirst()
{
m_canSynchronizeSelectionWithCurrent = true;
bool ret = base.MoveCurrentToFirst();
m_canSynchronizeSelectionWithCurrent = false;
return ret;
}
public override bool MoveCurrentToLast()
{
m_canSynchronizeSelectionWithCurrent = true;
bool ret = base.MoveCurrentToLast();
m_canSynchronizeSelectionWithCurrent = false;
return ret;
}
public override bool MoveCurrentToNext()
{
m_canSynchronizeSelectionWithCurrent = true;
bool ret = base.MoveCurrentToNext();
m_canSynchronizeSelectionWithCurrent = false;
return ret;
}
public override bool MoveCurrentToPrevious()
{
m_canSynchronizeSelectionWithCurrent = true;
bool ret = base.MoveCurrentToPrevious();
m_canSynchronizeSelectionWithCurrent = false;
return ret;
}
#endregion PUBLIC METHODS
internal override void SetCurrentItemAndPositionCore( object currentItem, int currentPosition, bool isCurrentBeforeFirst, bool isCurrentAfterLast )
{
this.UpdateDataVirtualizationLockForCurrentPosition( false );
base.SetCurrentItemAndPositionCore( currentItem, currentPosition, isCurrentBeforeFirst, isCurrentAfterLast );
this.UpdateDataVirtualizationLockForCurrentPosition( true );
}
private void UpdateDataVirtualizationLockForCurrentPosition( bool applyLock )
{
if( base.RootGroup == null )
return;
if( !this.IsCurrentAfterLast && !this.IsCurrentBeforeFirst )
{
int currentPosition = this.CurrentPosition;
Debug.Assert( currentPosition > -1 );
if( applyLock )
{
this.RootGroup.LockGlobalIndex( currentPosition );
}
else
{
this.RootGroup.UnlockGlobalIndex( currentPosition );
}
}
}
#region DEFERRED OPERATIONS HANDLING
internal override void ExecuteSourceItemOperation( DeferredOperation deferredOperation, out bool refreshForced )
{
refreshForced = false;
switch( deferredOperation.Action )
{
case DeferredOperation.DeferredOperationAction.Add:
case DeferredOperation.DeferredOperationAction.Move:
case DeferredOperation.DeferredOperationAction.RefreshDistincValues:
{
Debug.Assert( false );
break;
}
case DeferredOperation.DeferredOperationAction.Refresh:
case DeferredOperation.DeferredOperationAction.Remove:
case DeferredOperation.DeferredOperationAction.Resort:
case DeferredOperation.DeferredOperationAction.Regroup:
{
this.ForceRefresh( true, false, true );
break;
}
case DeferredOperation.DeferredOperationAction.Replace:
{
this.ReplaceSourceItem( deferredOperation.OldStartingIndex, deferredOperation.OldItems,
deferredOperation.NewStartingIndex, deferredOperation.NewItems );
break;
}
default:
{
base.ExecuteSourceItemOperation( deferredOperation, out refreshForced );
break;
}
}
}
private void ReplaceSourceItem( int oldStartIndex, IList oldItems, int newStartIndex, IList newItems )
{
Debug.Assert( oldStartIndex == newStartIndex );
Debug.Assert( oldItems.Count == newItems.Count );
if( ( oldStartIndex == -1 ) || ( newStartIndex == -1 ) )
{
this.ForceRefresh( true, !this.Loaded, true );
return;
}
int newItemCount = newItems.Count;
int oldItemCount = oldItems.Count;
int extraOldItemCount = oldItemCount - newItemCount;
int currentPosition = this.CurrentPosition;
int count = Math.Min( newItemCount, oldItemCount );
for( int i = 0; i < count; i++ )
{
object oldItem = oldItems[ i ];
object newItem = newItems[ i ];
if( ( oldStartIndex == newStartIndex ) && ( object.Equals( oldItem, newItem ) ) )
{
if( this.CurrentEditItem != oldItem )
{
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace,
new object[] { newItem },
new object[] { oldItem },
oldStartIndex + i ) );
}
}
else
{
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Replace,
new object[] { newItem },
new object[] { oldItem },
oldStartIndex + i ) );
if( currentPosition == newStartIndex + i )
this.SetCurrentItem( currentPosition, newItem, false, false );
}
}
}
#endregion DEFERRED OPERATIONS HANDLING
#region INTERNAL PROPERTIES
internal new DataGridVirtualizingCollectionViewGroupBase RootGroup
{
get
{
if( base.RootGroup == null )
base.RootGroup = this.CreateNewRootGroup();
return base.RootGroup as DataGridVirtualizingCollectionViewGroupBase;
}
set
{
base.RootGroup = value;
}
}
internal override int SourceItemCount
{
get
{
return this.Count;
}
}
internal bool CanSynchronizeSelectionWithCurrent
{
get
{
return m_canSynchronizeSelectionWithCurrent;
}
}
#endregion INTERNAL PROPERTIES
#region INTERNAL METHODS
internal abstract DataGridVirtualizingCollectionViewGroupBase CreateNewRootGroup();
internal override void OnBeginningEdit( DataGridItemCancelEventArgs e )
{
object item = e.Item;
// We throw instead of setting e.Cancel to True because we do not want to give the developer the chance to set it back to False.
if( item is EmptyDataItem )
throw new DataGridException( "Cannot begin edit on an empty data item or on an item that has a pending commit async operation." );
DataGridPageManagerBase pageManager = this.RootGroup.GetVirtualPageManager();
if( pageManager.IsAsyncCommitQueuedForItem( item ) )
throw new DataGridException( "Cannot begin edit on an empty data item or on an item that has a pending commit async operation." );
base.OnBeginningEdit( e );
}
internal override void OnEditBegun( DataGridItemEventArgs e )
{
var item = e.Item;
var pageManager = this.RootGroup.GetVirtualPageManager();
if( !pageManager.IsItemDirty( item ) )
{
// First time we enter edit on this item.
var itemProperties = this.ItemProperties;
var count = itemProperties.Count;
var propertyNames = new string[ count ];
var cachedValues = new object[ count ];
for( int i = 0; i < count; i++ )
{
var itemProperty = itemProperties[ i ];
propertyNames[ i ] = PropertyRouteParser.Parse( itemProperty );
cachedValues[ i ] = ItemsSourceHelper.GetValueFromItemProperty( itemProperty, item );
}
// Cache the values of the never edited before row. This will help the developer find the corresponding row
// in the source when times comes to commit the changes to the data source.
pageManager.SetCachedValuesForItem( item, propertyNames, cachedValues );
}
base.OnEditBegun( e );
}
internal override void OnEditCommitted( DataGridItemEventArgs e )
{
var item = e.Item;
var pageManager = this.RootGroup.GetVirtualPageManager();
// Compare cached values with current values. If they are the same, we can clear the old values which in turn will
// make the item non dirty.
var clearIsDirty = true;
var cachedValues = pageManager.GetCachedValuesForItem( item );
Debug.Assert( cachedValues != null );
var itemProperties = this.ItemProperties;
foreach( var itemProperty in itemProperties )
{
var currentValue = ItemsSourceHelper.GetValueFromItemProperty( itemProperty, item );
if( !( object.Equals( currentValue, cachedValues[ itemProperty.Name ] ) ) )
{
clearIsDirty = false;
break;
}
}
if( clearIsDirty )
{
// No modification was detected.
pageManager.ClearCachedValuesForItem( item );
}
else if( m_commitMode == CommitMode.EditCommitted )
{
pageManager.CommitAll();
}
base.OnEditCommitted( e );
}
internal override void OnEditCanceled( DataGridItemEventArgs e )
{
var item = e.Item;
var pageManager = this.RootGroup.GetVirtualPageManager();
// Compare cached values with current values. If they are the same, we can clear the old values which in turn will
// make the item non dirty.
var clearIsDirty = true;
var cachedValues = pageManager.GetCachedValuesForItem( item );
Debug.Assert( cachedValues != null );
var itemProperties = this.ItemProperties;
foreach( var itemProperty in itemProperties )
{
var currentValue = ItemsSourceHelper.GetValueFromItemProperty( itemProperty, item );
if( !( object.Equals( currentValue, cachedValues[ PropertyRouteParser.Parse( itemProperty ) ] ) ) )
{
clearIsDirty = false;
break;
}
}
if( clearIsDirty )
{
pageManager.ClearCachedValuesForItem( item );
}
base.OnEditCanceled( e );
}
#endregion INTERNAL METHODS
#region INTERNAL EVENTS
internal event EventHandler ConnectionStateChanged;
internal void OnConnectionStateChanged()
{
if( this.ConnectionStateChanged != null )
this.ConnectionStateChanged( this, EventArgs.Empty );
}
internal event EventHandler ConnectionErrorChanged;
internal void OnConnectionErrorChanged()
{
if( this.ConnectionErrorChanged != null )
this.ConnectionErrorChanged( this, EventArgs.Empty );
}
#endregion INTERNAL EVENTS
#region PRIVATE FIELDS
private CommitMode m_commitMode;
private int m_pageSize;
private double m_preemptivePageQueryRatio;
private int m_maxRealizedItemCount;
private object m_connectionError;
private DataGridConnectionState m_connectionState;
private bool m_canSynchronizeSelectionWithCurrent;
#endregion PRIVATE FIELDS
#region DataGridCollectionViewBase Implementation
internal override void EnsurePosition( int globalSortedIndex )
{
}
internal override void ForceRefresh( bool sendResetNotification, bool initialLoad, bool setCurrentToFirstOnInitialLoad )
{
if( this.Refreshing )
throw new InvalidOperationException( "An attempt was made to refresh the DataGridVirtualizingCollectionView while it is already in the process of refreshing." );
if( this.IsRefreshingDistinctValues )
throw new InvalidOperationException( "An attempt was made to refresh the DataGridVirtualizingCollectionView while it is already in the process of refreshing distinct values." );
this.SetCurrentEditItem( null );
int oldCurrentPosition = -1;
if( !initialLoad )
this.SaveCurrentBeforeReset( out oldCurrentPosition );
using( this.DeferCurrencyEvent() )
{
this.Refreshing = true;
try
{
lock( this.SyncRoot )
{
lock( this.DeferredOperationManager )
{
this.DeferredOperationManager.ClearDeferredOperations();
// We explicitly go through base so we do not end-up creating a RootGroup if there is none existing at the moment.
DataGridVirtualizingCollectionViewGroupBase rootGroup = base.RootGroup as DataGridVirtualizingCollectionViewGroupBase;
if( rootGroup != null )
{
DataGridPageManagerBase pageManager = rootGroup.GetVirtualPageManager();
// The pageManager can be null when no queryable source was set yet.
if( pageManager != null )
{
// Disconnect the PageManager so that subsequent Items/Count interrogations are not processed.
pageManager.Disconnect();
// Restart all virtual lists. The DataGridPageManagerBase will make a call to ForceRefresh once everything has been restarted if
// commit operations had to be made.
pageManager.Restart();
}
}
// Ensure to clear the DistinctValues cache when refreshing
// since the source could have changed
this.ResetDistinctValues();
base.RootGroup = this.CreateNewRootGroup();
// We set the current item to -1 to prevent the developper to get an invalid position.
// We will replace the current item to the correct one later.
this.SetCurrentItem( -1, null, false, false );
}
}
}
finally
{
this.Refreshing = false;
}
if( initialLoad )
{
this.Loaded = true;
}
else
{
this.AdjustCurrencyAfterReset( oldCurrentPosition );
}
if( sendResetNotification )
{
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
this.OnPropertyChanged( new PropertyChangedEventArgs( "Groups" ) );
}
}
#endregion DataGridCollectionViewBase Implementation
}
}

53
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewDataProvider.cs

@ -1,53 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridVirtualizingCollectionViewDataProvider : DataGridCollectionViewBaseDataProvider
{
#region CONSTRUCTORS
public DataGridVirtualizingCollectionViewDataProvider( DataGridVirtualizingCollectionViewSource parentSource )
: base( parentSource )
{
}
#endregion CONSTRUCTORS
#region INTERNAL METHODS
internal override DataGridCollectionViewBase EnsureDataGridCollectionViewBaseCore()
{
DataGridVirtualizingCollectionViewSource parentSource = this.ParentSource as DataGridVirtualizingCollectionViewSource;
if( !parentSource.IsInitialized )
return null;
return new DataGridVirtualizingCollectionView(
parentSource.ItemType,
parentSource.AutoCreateItemProperties,
parentSource.PageSize,
parentSource.MaxRealizedItemCount );
}
#endregion INTERNAL METHODS
}
}

112
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewGroup.cs

@ -1,112 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridVirtualizingCollectionViewGroup : DataGridVirtualizingCollectionViewGroupBase, IWeakEventListener
{
private static List<DataGridGroupInfo> EmptyDataGridInfoList = new List<DataGridGroupInfo>( 0 );
internal DataGridVirtualizingCollectionViewGroup( object name, int initialItemsCount, int startGlobalIndex, DataGridVirtualizingCollectionViewGroup parent, int level, bool isBottomLevel )
: base( name, initialItemsCount, startGlobalIndex, parent, level, isBottomLevel )
{
}
#region GroupPath Property
internal List<DataGridGroupInfo> GroupPath
{
get
{
if( m_groupPath == null )
{
m_groupPath = this.BuildGroupPath();
}
return m_groupPath;
}
}
#endregion
internal override int QueryItemCount()
{
DataGridVirtualizingCollectionView collectionView = this.GetCollectionView() as DataGridVirtualizingCollectionView;
return collectionView.OnQueryItemCount( this );
}
internal override ObservableCollection<object> QuerySubCollectionViewGroupList( GroupDescription subGroupBy, int nextLevel, bool nextLevelIsBottom )
{
DataGridVirtualizingCollectionView collectionView = this.GetCollectionView() as DataGridVirtualizingCollectionView;
Debug.Assert( collectionView != null );
List<GroupNameCountPair> subGroupInfos = collectionView.OnQueryGroups( this );
int subGroupCount = subGroupInfos.Count;
// Create the collection of sub CollectionViewGroups
ObservableCollection<object> subCollectionViewGroupList = new ObservableCollection<object>();
int runningCount = this.StartGlobalIndex;
for( int i = 0; i < subGroupCount; i++ )
{
object subGroupName = subGroupInfos[ i ].Name;
int subGroupItemCount = subGroupInfos[ i ].ItemCount;
subCollectionViewGroupList.Add( new DataGridVirtualizingCollectionViewGroup( subGroupName, subGroupItemCount, runningCount, this, nextLevel, nextLevelIsBottom ) );
runningCount += subGroupItemCount;
}
return subCollectionViewGroupList;
}
private List<DataGridGroupInfo> BuildGroupPath()
{
DataGridVirtualizingCollectionViewGroup parent = this.Parent as DataGridVirtualizingCollectionViewGroup;
if( parent == null )
return new List<DataGridGroupInfo>();
DataGridVirtualizingCollectionViewBase collectionView = this.GetCollectionView();
ObservableCollection<GroupDescription> groupDescriptions = collectionView.GroupDescriptions;
int level = this.Level;
Debug.Assert( this.Level != -1, "A DataGridCollectionViewGroupRoot should have returned a new List since its parent should have been null." );
List<DataGridGroupInfo> groupPath = new List<DataGridGroupInfo>( parent.GroupPath );
Debug.Assert( groupDescriptions.Count > level );
if( groupDescriptions.Count > level )
{
groupPath.Add( new DataGridGroupInfo( groupDescriptions[ level ], this ) );
}
return groupPath;
}
private List<DataGridGroupInfo> m_groupPath;
}
}

469
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewGroupBase.cs

@ -1,469 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
internal abstract class DataGridVirtualizingCollectionViewGroupBase : CollectionViewGroup, IWeakEventListener, IDisposable
{
internal DataGridVirtualizingCollectionViewGroupBase(
object name,
int initialItemsCount,
int startGlobalIndex,
DataGridVirtualizingCollectionViewGroupBase parent,
int level,
bool isBottomLevel )
: base( name )
{
m_parent = parent;
m_level = level;
m_isBottomLevel = isBottomLevel;
m_virtualItemCount = initialItemsCount;
m_startGlobalIndex = startGlobalIndex;
}
#region ItemCount (Obselete) Property
[Obsolete( "The ItemCount property is obsolete and has been replaced by the VirtualItemCount property. When referencing through a CollectionViewGroup, the CollectionViewGroupExtensions.GetItemCount extension method can be used.", true )]
public new int ItemCount
{
get
{
return this.VirtualItemCount;
}
}
#endregion
#region Items (Obselete) Property
[Obsolete( "The Items property is obsolete and has been replaced by the VirtualItems property. When referencing through a CollectionViewGroup, the CollectionViewGroupExtensions.GetItems extension method can be used.", true )]
public new ReadOnlyObservableCollection<object> Items
{
get
{
return base.Items;
}
}
#endregion
#region VirtualItemCount Property
public int VirtualItemCount
{
get
{
if( this.GetVirtualPageManager() == null )
return 0;
if( m_virtualItemCount == -1 )
{
if( m_isBottomLevel )
{
this.EnsureProtectedVirtualItems();
m_virtualItemCount = m_protectedVirtualItems.Count;
}
else
{
m_virtualItemCount = this.QueryItemCount();
}
}
return m_virtualItemCount;
}
}
#endregion
#region VirtualItems Property
public IList<object> VirtualItems
{
get
{
if( m_virtualItems == null )
{
this.EnsureProtectedVirtualItems();
ObservableCollection<object> observableProtectedItems = m_protectedVirtualItems as ObservableCollection<object>;
if( observableProtectedItems != null )
{
Debug.Assert( !m_isBottomLevel );
m_virtualItems = new ReadOnlyObservableCollection<object>( observableProtectedItems );
}
else
{
Debug.Assert( m_isBottomLevel );
m_virtualItems = m_protectedVirtualItems;
}
}
return m_virtualItems;
}
}
#endregion
#region IsBottomLevel Property
public override bool IsBottomLevel
{
get
{
return m_isBottomLevel;
}
}
#endregion
#region Parent Property
internal DataGridVirtualizingCollectionViewGroupBase Parent
{
get
{
return m_parent;
}
}
#endregion
#region Level Property
internal int Level
{
get
{
return m_level;
}
}
#endregion
#region StartGlobalIndex Property
internal int StartGlobalIndex
{
get
{
return m_startGlobalIndex;
}
}
#endregion
protected virtual DataGridVirtualizingCollectionViewBase GetCollectionView()
{
if( m_parent != null )
return m_parent.GetCollectionView();
return null;
}
internal abstract int QueryItemCount();
internal abstract ObservableCollection<object> QuerySubCollectionViewGroupList( GroupDescription subGroupBy, int nextLevel, bool nextLevelIsBottom );
internal virtual GroupDescription GetSubGroupBy()
{
CollectionView collectionView = this.GetCollectionView();
ObservableCollection<GroupDescription> groupDescriptions = collectionView.GroupDescriptions;
int groupDescriptionsCount = ( groupDescriptions == null ) ? 0 : groupDescriptions.Count;
if( groupDescriptionsCount == 0 )
return null;
DataGridVirtualizingCollectionViewGroupBase parentCollectionViewGroup = this.Parent;
int level = 0;
while( parentCollectionViewGroup != null )
{
level++;
parentCollectionViewGroup = parentCollectionViewGroup.Parent;
}
Debug.Assert( groupDescriptionsCount >= level );
return groupDescriptions[ level ];
}
internal virtual void OnProtectedVirtualItemsCreated( IList<object> protectedVirtualItems )
{
}
internal virtual void DisposeCore()
{
m_protectedVirtualItems = new List<object>();
m_virtualItems = m_protectedVirtualItems;
m_parent = null;
}
internal virtual int GetGlobalIndexOf( object item )
{
return m_parent.GetGlobalIndexOf( item );
}
internal virtual DataGridPageManagerBase GetVirtualPageManager()
{
return m_parent.GetVirtualPageManager();
}
internal object GetItemAtGlobalIndex( int globalIndex )
{
Func<int, DataGridVirtualizingCollectionViewGroupBase, object> getItemFunction = ( localIndex, cvg ) =>
{
return cvg.m_protectedVirtualItems[ localIndex ];
};
return this.OperateOnGlobalIndex( globalIndex, getItemFunction );
}
internal void LockGlobalIndex( int globalIndex )
{
Func<int, DataGridVirtualizingCollectionViewGroupBase, object> lockingAction = ( localIndex, cvg ) =>
{
VirtualList virtualItemList = cvg.VirtualItems as VirtualList;
if( virtualItemList != null )
{
virtualItemList.LockPageForLocalIndex( localIndex );
}
return null;
};
this.OperateOnGlobalIndex( globalIndex, lockingAction );
}
internal void UnlockGlobalIndex( int globalIndex )
{
var collectionView = this.GetCollectionView();
if( collectionView != null )
{
var rootGroup = collectionView.RootGroup;
// This can happen when refreshing a CollectionView and the record count has changed in such a way that the global index to unlock is out of range of the new count.
if( ( rootGroup != null ) && ( ( globalIndex >= rootGroup.m_virtualItemCount ) ) )
return;
}
Func<int, DataGridVirtualizingCollectionViewGroupBase, object> unlockingAction = ( localIndex, cvg ) =>
{
VirtualList virtualItemList = cvg.VirtualItems as VirtualList;
if( virtualItemList != null )
{
virtualItemList.UnlockPageForLocalIndex( localIndex );
}
return null;
};
this.OperateOnGlobalIndex( globalIndex, unlockingAction );
}
private void EnsureProtectedVirtualItems()
{
if( m_protectedVirtualItems != null )
return;
DataGridVirtualizingCollectionViewBase collectionView = this.GetCollectionView();
Debug.Assert( collectionView != null );
if( m_isBottomLevel )
{
m_protectedVirtualItems = this.CreateNewVirtualList();
}
else
{
ObservableCollection<GroupDescription> groupDescriptions = collectionView.GroupDescriptions;
int groupDescriptionCount = ( groupDescriptions == null ) ? 0 : groupDescriptions.Count;
int nextLevel = m_level + 1;
if( nextLevel > ( groupDescriptionCount - 1 ) )
throw new DataGridInternalException( "At attempt was made to retrieve child groups for a non-existing group description." );
GroupDescription subGroupBy = groupDescriptions[ nextLevel ];
if( subGroupBy == null )
throw new InvalidOperationException( "TODDOOC: " );
bool nextLevelIsBottom = ( nextLevel == ( groupDescriptionCount - 1 ) );
m_protectedVirtualItems = this.QuerySubCollectionViewGroupList( subGroupBy, nextLevel, nextLevelIsBottom );
}
}
private VirtualList CreateNewVirtualList()
{
Debug.Assert( m_isBottomLevel );
DataGridVirtualizingCollectionViewBase collectionView = this.GetCollectionView();
DataGridPageManagerBase virtualPageManagerBase = collectionView.RootGroup.GetVirtualPageManager();
VirtualList virtualItemList = new VirtualList( virtualPageManagerBase, m_virtualItemCount );
virtualPageManagerBase.LinkVirtualListAndCollectionViewGroup( virtualItemList, this );
return virtualItemList;
}
private int GetSubLevelCount()
{
CollectionView collectionView = this.GetCollectionView();
ObservableCollection<GroupDescription> groupDescriptions = collectionView.GroupDescriptions;
int groupDescriptionsCount = ( groupDescriptions == null ) ? 0 : groupDescriptions.Count;
DataGridVirtualizingCollectionViewGroupBase parentCollectionViewGroup = this.Parent;
int level = 0;
while( parentCollectionViewGroup != null )
{
level++;
parentCollectionViewGroup = parentCollectionViewGroup.Parent;
}
Debug.Assert( groupDescriptionsCount >= level );
return ( groupDescriptionsCount - level );
}
private object OperateOnGlobalIndex( int index, Func<int, DataGridVirtualizingCollectionViewGroupBase, object> function )
{
this.EnsureProtectedVirtualItems();
if( this.IsBottomLevel )
{
return function( index, this );
}
else
{
// The Count property of the virtualItems collection will return the sub-group count since this is not the bottom level.
int count = m_protectedVirtualItems.Count;
for( int i = 0; i < count; i++ )
{
DataGridVirtualizingCollectionViewGroupBase subGroup = m_protectedVirtualItems[ i ] as DataGridVirtualizingCollectionViewGroupBase;
if( subGroup == null )
throw new InvalidOperationException( "Sub-group cannot be null (Nothing in Visual Basic)." );
// VirtualItemCount will return the sum of data items contained in this group and its possible subgroups.
int subGroupItemCount = subGroup.VirtualItemCount;
if( index < subGroupItemCount )
return subGroup.OperateOnGlobalIndex( index, function );
index -= subGroupItemCount;
}
}
throw new ArgumentOutOfRangeException( "index" );
}
private void OnVirtualItemListCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
DataGridVirtualizingCollectionViewBase collectionView = this.GetCollectionView();
lock( collectionView.DeferredOperationManager )
{
DeferredOperation deferredOperation = null;
switch( e.Action )
{
case NotifyCollectionChangedAction.Replace:
{
deferredOperation = new DeferredOperation( DeferredOperation.DeferredOperationAction.Replace, -1, e.NewStartingIndex + m_startGlobalIndex,
e.NewItems, e.OldStartingIndex + m_startGlobalIndex, e.OldItems );
break;
}
case NotifyCollectionChangedAction.Reset:
{
deferredOperation = new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null );
break;
}
default:
throw new NotSupportedException( e.Action.ToString() + " is not a supported action." );
}
if( deferredOperation != null )
{
collectionView.ExecuteOrQueueSourceItemOperation( deferredOperation );
}
}
}
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
return this.OnReceiveWeakEvent( managerType, sender, e );
}
protected virtual bool OnReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( managerType == typeof( CollectionChangedEventManager ) )
{
this.OnVirtualItemListCollectionChanged( sender, ( NotifyCollectionChangedEventArgs )e );
return true;
}
return false;
}
#endregion IWeakEventListener Members
#region IDisposable Members
public void Dispose()
{
this.DisposeCore();
}
#endregion
private bool m_isBottomLevel;
private int m_level;
private int m_startGlobalIndex;
private int m_virtualItemCount;
private IList<object> m_protectedVirtualItems;
private IList<object> m_virtualItems;
private DataGridVirtualizingCollectionViewGroupBase m_parent;
}
}

54
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewGroupRoot.cs

@ -1,54 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
namespace Xceed.Wpf.DataGrid
{
internal class DataGridVirtualizingCollectionViewGroupRoot : DataGridVirtualizingCollectionViewGroup
{
internal DataGridVirtualizingCollectionViewGroupRoot( DataGridVirtualizingCollectionView collectionView, bool isBottomLevel )
: base( null, -1, 0, null, -1, isBottomLevel )
{
m_parentCollectionView = collectionView;
m_virtualPageManager = new DataGridPageManager( collectionView );
}
protected override DataGridVirtualizingCollectionViewBase GetCollectionView()
{
return m_parentCollectionView;
}
internal override int GetGlobalIndexOf( object item )
{
return m_virtualPageManager.GetGlobalIndexOf( item );
}
internal override DataGridPageManagerBase GetVirtualPageManager()
{
return m_virtualPageManager;
}
internal override void DisposeCore()
{
m_parentCollectionView = null;
m_virtualPageManager = null;
base.DisposeCore();
}
private DataGridVirtualizingCollectionView m_parentCollectionView;
private DataGridPageManager m_virtualPageManager;
}
}

87
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewSource.cs

@ -1,87 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
public class DataGridVirtualizingCollectionViewSource : DataGridVirtualizingCollectionViewSourceBase
{
#region CONSTRUCTORS
static DataGridVirtualizingCollectionViewSource()
{
CollectionViewSource.CollectionViewTypeProperty.OverrideMetadata(
typeof( DataGridVirtualizingCollectionViewSource ),
new FrameworkPropertyMetadata( typeof( DataGridVirtualizingCollectionView ) ) );
}
public DataGridVirtualizingCollectionViewSource()
: base()
{
}
#endregion CONSTRUCTORS
#region DATA VIRTUALIZATION EVENTS
public event EventHandler<QueryItemCountEventArgs> QueryItemCount;
internal void OnQueryItemCount( QueryItemCountEventArgs e )
{
if( this.QueryItemCount != null )
this.QueryItemCount( this, e );
}
public event EventHandler<QueryGroupsEventArgs> QueryGroups;
internal void OnQueryGroups( QueryGroupsEventArgs e )
{
if( this.QueryGroups != null )
this.QueryGroups( this, e );
}
public event EventHandler<QueryItemsEventArgs> AbortQueryItems;
internal void OnAbortQueryItems( QueryItemsEventArgs e )
{
if( this.AbortQueryItems != null )
this.AbortQueryItems( this, e );
}
public event EventHandler<QueryItemsEventArgs> QueryItems;
internal void OnQueryItems( QueryItemsEventArgs e )
{
if( this.QueryItems != null )
this.QueryItems( this, e );
}
#endregion DATA VIRTUALIZATION EVENTS
internal override DataGridCollectionViewBaseDataProvider CreateDataProvider()
{
return new DataGridVirtualizingCollectionViewDataProvider( this );
}
}
}

164
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewSourceBase.cs

@ -1,164 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
public abstract class DataGridVirtualizingCollectionViewSourceBase : DataGridCollectionViewSourceBase
{
public DataGridVirtualizingCollectionViewSourceBase()
{
this.Source = null;
m_isInitialized = true;
this.DataSourceProvider.DelayRefresh( this.Dispatcher, System.Windows.Threading.DispatcherPriority.DataBind );
}
#region PageSize Property
public static readonly DependencyProperty PageSizeProperty = DependencyProperty.Register(
"PageSize", typeof( int ), typeof( DataGridVirtualizingCollectionViewSourceBase ),
new UIPropertyMetadata( DataGridVirtualizingCollectionViewBase.DefaultPageSize ) );
public int PageSize
{
get
{
return ( int )this.GetValue( DataGridVirtualizingCollectionViewSourceBase.PageSizeProperty );
}
set
{
this.SetValue( DataGridVirtualizingCollectionViewSourceBase.PageSizeProperty, value );
if( this.DataSourceProvider != null )
this.DataSourceProvider.DelayRefresh( this.Dispatcher, System.Windows.Threading.DispatcherPriority.DataBind );
}
}
#endregion PageSize Property
#region MaxRealizedItemCount
public static readonly DependencyProperty MaxRealizedItemCountProperty = DependencyProperty.Register(
"MaxRealizedItemCount", typeof( int ), typeof( DataGridVirtualizingCollectionViewSourceBase ),
new UIPropertyMetadata( DataGridVirtualizingCollectionViewBase.DefaultMaxRealizedItemCount ) );
public int MaxRealizedItemCount
{
get
{
return ( int )GetValue( DataGridVirtualizingCollectionViewSourceBase.MaxRealizedItemCountProperty );
}
set
{
this.SetValue( DataGridVirtualizingCollectionViewSourceBase.MaxRealizedItemCountProperty, value );
if( this.DataSourceProvider != null )
this.DataSourceProvider.DelayRefresh( this.Dispatcher, System.Windows.Threading.DispatcherPriority.DataBind );
}
}
#endregion MaxRealizedItemCount
#region PreemptivePageQueryRatio
public static readonly DependencyProperty PreemptivePageQueryRatioProperty = DependencyProperty.Register(
"PreemptivePageQueryRatio", typeof( double ), typeof( DataGridVirtualizingCollectionViewSourceBase ),
new UIPropertyMetadata( DataGridVirtualizingCollectionViewBase.DefaultPreemptivePageQueryRatio,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceBaseDependencyPropertyChanged ) ) );
public double PreemptivePageQueryRatio
{
get
{
return ( double )GetValue( DataGridVirtualizingCollectionViewSourceBase.PreemptivePageQueryRatioProperty );
}
set
{
this.SetValue( DataGridVirtualizingCollectionViewSourceBase.PreemptivePageQueryRatioProperty, value );
}
}
#endregion PreemptivePageQueryRatio
#region CommitMode
public static readonly DependencyProperty CommitModeProperty = DependencyProperty.Register(
"CommitMode", typeof( CommitMode ), typeof( DataGridVirtualizingCollectionViewSourceBase ),
new UIPropertyMetadata( CommitMode.PageReleasedFromMemory,
new PropertyChangedCallback( DataGridCollectionViewSourceBase.OnDataGridCollectionViewSourceBaseDependencyPropertyChanged ) ) );
public CommitMode CommitMode
{
get
{
return ( CommitMode )GetValue( DataGridVirtualizingCollectionViewSourceBase.CommitModeProperty );
}
set
{
this.SetValue( DataGridVirtualizingCollectionViewSourceBase.CommitModeProperty, value );
}
}
#endregion CommitMode
#region DATA VIRTUALIZATION EVENTS
public event EventHandler<CommitItemsEventArgs> CommitItems;
internal void OnCommitItems( CommitItemsEventArgs e )
{
if( this.CommitItems != null )
this.CommitItems( this, e );
}
#endregion DATA VIRTUALIZATION EVENTS
#region INTERNAL PROPERTIES
internal bool IsInitialized
{
get
{
return m_isInitialized;
}
}
#endregion INTERNAL PROPERTIES
#region INTERNAL METHODS
internal override void ApplyExtraPropertiesToView( DataGridCollectionViewBase currentView )
{
base.ApplyExtraPropertiesToView( currentView );
DataGridVirtualizingCollectionViewBase dataGridVirtualizingCollectionView = currentView as DataGridVirtualizingCollectionViewBase;
dataGridVirtualizingCollectionView.PreemptivePageQueryRatio = this.PreemptivePageQueryRatio;
dataGridVirtualizingCollectionView.CommitMode = this.CommitMode;
}
#endregion INTERNAL METHODS
#region PRIVATE FIELDS
private bool m_isInitialized;
#endregion PRIVATE FIELDS
}
}

77
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionView.cs

@ -1,77 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid
{
public sealed class DataGridVirtualizingQueryableCollectionView : DataGridVirtualizingCollectionViewBase
{
public DataGridVirtualizingQueryableCollectionView()
: this( null, true, DataGridVirtualizingCollectionViewBase.DefaultPageSize, DataGridVirtualizingCollectionViewBase.DefaultMaxRealizedItemCount )
{
}
public DataGridVirtualizingQueryableCollectionView( IQueryable queryableSource )
: this( queryableSource, true, DataGridVirtualizingCollectionViewBase.DefaultPageSize, DataGridVirtualizingCollectionViewBase.DefaultMaxRealizedItemCount )
{
}
public DataGridVirtualizingQueryableCollectionView( IQueryable queryableSource, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount )
: base( queryableSource, null, autoCreateItemProperties, pageSize, maxRealizedItemCount )
{
m_pageManagerSyncRoot = new object();
}
#region QueryableSource PROPERTY
public IQueryable QueryableSource
{
get
{
return this.ModelSource as IQueryable;
}
}
#endregion QueryableSource PROPERTY
#region INTERNAL METHODS
internal override DataGridVirtualizingCollectionViewGroupBase CreateNewRootGroup()
{
bool rootIsBottomLevel = ( this.GroupDescriptions == null ) ? true : ( this.GroupDescriptions.Count == 0 );
return new DataGridVirtualizingQueryableCollectionViewGroupRoot( this, m_pageManagerSyncRoot, rootIsBottomLevel );
}
internal override System.Collections.IEnumerator GetVirtualEnumerator()
{
return ( ( DataGridVirtualizingQueryableCollectionViewGroupRoot )this.RootGroup ).GetVirtualPageManager().GetEnumerator();
}
#endregion
#region PRIVATE FIELDS
private object m_pageManagerSyncRoot;
#endregion
}
}

54
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewDataProvider.cs

@ -1,54 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridVirtualizingQueryableCollectionViewDataProvider : DataGridCollectionViewBaseDataProvider
{
#region CONSTRUCTORS
public DataGridVirtualizingQueryableCollectionViewDataProvider( DataGridVirtualizingQueryableCollectionViewSource parentSource )
: base( parentSource )
{
}
#endregion CONSTRUCTORS
#region INTERNAL METHODS
internal override DataGridCollectionViewBase EnsureDataGridCollectionViewBaseCore()
{
DataGridVirtualizingQueryableCollectionViewSource parentSource = this.ParentSource as DataGridVirtualizingQueryableCollectionViewSource;
if( !parentSource.IsInitialized )
return null;
return new DataGridVirtualizingQueryableCollectionView(
parentSource.QueryableSource,
parentSource.AutoCreateItemProperties,
parentSource.PageSize,
parentSource.MaxRealizedItemCount );
}
#endregion INTERNAL METHODS
}
}

283
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewGroup.cs

@ -1,283 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq.Expressions;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridVirtualizingQueryableCollectionViewGroup : DataGridVirtualizingCollectionViewGroupBase
{
#region CONSTRUCTORS
public DataGridVirtualizingQueryableCollectionViewGroup(
object name,
int initialItemsCount,
int startGlobalIndex,
DataGridVirtualizingQueryableCollectionViewGroup parent,
int level,
bool isBottomLevel )
: base( name, initialItemsCount, startGlobalIndex, parent, level, isBottomLevel )
{
}
#endregion CONSTRUCTORS
#region INTERNAL PROPERTIES
internal IQueryable UnsortedFilteredQueryable
{
get
{
if( m_unsortedFilteredQueryable == null )
m_unsortedFilteredQueryable = this.CreateUnsortedFilteredQueryable();
return m_unsortedFilteredQueryable;
}
}
internal IQueryable Queryable
{
get
{
if( m_selectQueryable == null )
m_selectQueryable = this.CreateSelectQueryable( false );
return m_selectQueryable;
}
}
internal IQueryable ReversedQueryable
{
get
{
if( m_reversedSelectQueryable == null )
m_reversedSelectQueryable = this.CreateSelectQueryable( true );
return m_reversedSelectQueryable;
}
}
#endregion INTERNAL PROPERTIES
#region INTERNAL METHODS
internal override int QueryItemCount()
{
if( this.UnsortedFilteredQueryable != null )
{
try
{
return this.UnsortedFilteredQueryable.Count();
}
catch
{
// Timeout or other error occured.
}
}
return 0;
}
internal override ObservableCollection<object> QuerySubCollectionViewGroupList( GroupDescription childGroupBy, int nextLevel, bool nextLevelIsBottom )
{
string childGroupByPropertyName = DataGridCollectionViewBase.GetPropertyNameFromGroupDescription( childGroupBy );
if( String.IsNullOrEmpty( childGroupByPropertyName ) )
throw new NotSupportedException( "Custom groups are not supported when using a DataGridVirtualizingQueryableCollectionView." );
DataGridVirtualizingCollectionViewBase collectionView = this.GetCollectionView();
bool sortGroupBy = false;
ListSortDirection groupByDirection = ListSortDirection.Ascending;
foreach( SortDescription sortDescription in collectionView.SortDescriptions )
{
if( sortDescription.PropertyName == childGroupByPropertyName )
{
sortGroupBy = true;
groupByDirection = sortDescription.Direction;
break;
}
}
IQueryable groupsAndCountsQueryable = this.Queryable.GetSubGroupsAndCountsQueryable( childGroupByPropertyName, sortGroupBy, groupByDirection );
List<QueryableExtensions.IQueryableGroupNameCountPair> distinctValuesAndCounts = new List<QueryableExtensions.IQueryableGroupNameCountPair>();
try
{
System.Collections.IEnumerator enumerator = groupsAndCountsQueryable.GetEnumerator();
while( enumerator.MoveNext() )
{
QueryableExtensions.IQueryableGroupNameCountPair current = enumerator.Current as QueryableExtensions.IQueryableGroupNameCountPair;
if( current != null )
distinctValuesAndCounts.Add( current );
}
}
catch
{
// TimeOut exception on the connection or other.
distinctValuesAndCounts.Clear();
}
// If we are not the bottom level, we should have subgroups.
// However, if the connection timed out and the catch statement set the coundAndDistinctValues to an empty array,
// then we shouldn't add anything. We cannot reset on the spot since we might already be resetting.
// Create the collection of sub CollectionViewGroups
ObservableCollection<object> subCollectionViewGroupList = new ObservableCollection<object>();
int runningCount = this.StartGlobalIndex;
int distinctValuesCount = distinctValuesAndCounts.Count;
for( int i = 0; i < distinctValuesCount; i++ )
{
QueryableExtensions.IQueryableGroupNameCountPair queryableGroupNameCountPair = distinctValuesAndCounts[ i ];
subCollectionViewGroupList.Add(
new DataGridVirtualizingQueryableCollectionViewGroup( queryableGroupNameCountPair.GroupName, queryableGroupNameCountPair.Count, runningCount, this, nextLevel, nextLevelIsBottom ) );
runningCount += queryableGroupNameCountPair.Count;
}
return subCollectionViewGroupList;
}
internal virtual IQueryable CreateUnsortedFilteredQueryable()
{
int level = this.Level;
Debug.Assert( ( level > -1 ), "The DataGridVirtualizingGroupRoot should have overriden this method without calling base." );
// Sub group. Only group from parent, which will already be sorted.
DataGridVirtualizingQueryableCollectionViewGroup parentCollectionViewGroup = this.Parent as DataGridVirtualizingQueryableCollectionViewGroup;
IQueryable parentUnsortedQueryable = parentCollectionViewGroup.UnsortedFilteredQueryable;
Debug.Assert( parentUnsortedQueryable != null );
if( parentUnsortedQueryable == null )
return null;
// Narrow the filter to this group's clauses.
return this.FilterQueryable( parentUnsortedQueryable );
}
internal IQueryable CreateSelectQueryable( bool reversed )
{
// Sub group. Only group from parent. The sorting will be appended just before the Slice statement.
IQueryable queryable = this.UnsortedFilteredQueryable;
return this.SortQueryable( queryable, reversed );
}
internal override void DisposeCore()
{
m_unsortedFilteredQueryable = null;
m_reversedSelectQueryable = null;
m_selectQueryable = null;
base.DisposeCore();
}
#endregion INTERNAL METHODS
#region PRIVATE METHODS
private IQueryable FilterQueryable( IQueryable queryable )
{
// Filters a queryable to match this Group's clause.
// This method does not apply the AutoFilter clauses or the FilterRow clauses.
// It is the DataGridVirtualizingQueryableCollectionViewGroupRoot's job to do so on the
// base queryable used as a base for all other queryables.
if( queryable == null )
throw new ArgumentNullException( "queryable" );
int level = this.Level;
DataGridVirtualizingCollectionViewBase collectionView = this.GetCollectionView();
ObservableCollection<GroupDescription> groupDescriptions = collectionView.GroupDescriptions;
Debug.Assert( ( groupDescriptions != null ) && ( level < groupDescriptions.Count ) );
DataGridGroupDescription groupBy = groupDescriptions[ level ] as DataGridGroupDescription;
Debug.Assert( groupBy != null );
ParameterExpression sharedParameterExpression = queryable.CreateParameterExpression();
Expression expression = queryable.CreateEqualExpression( sharedParameterExpression, groupBy.PropertyName, this.Name );
return queryable.WhereFilter( sharedParameterExpression, expression );
}
private IQueryable SortQueryable( IQueryable queryable, bool reverseSort )
{
DataGridVirtualizingCollectionViewBase parentCollectionView = this.GetCollectionView();
Debug.Assert( parentCollectionView != null );
SortDescriptionCollection explicitSortDescriptions = parentCollectionView.SortDescriptions;
ListSortDirection directionToUseForImplicitSortDescriptions = ListSortDirection.Ascending;
if( explicitSortDescriptions.Count > 0 )
directionToUseForImplicitSortDescriptions = explicitSortDescriptions[ explicitSortDescriptions.Count - 1 ].Direction;
SortDescriptionCollection implicitSortDescriptions = new SortDescriptionCollection();
DataGridVirtualizingQueryableCollectionViewGroupRoot groupRoot =
parentCollectionView.RootGroup as DataGridVirtualizingQueryableCollectionViewGroupRoot;
Debug.Assert( groupRoot != null );
string[] primaryKeys = groupRoot.PrimaryKeys;
if( primaryKeys != null )
{
for( int i = 0; i < primaryKeys.Length; i++ )
{
string primaryKey = primaryKeys[ i ];
Debug.Assert( !string.IsNullOrEmpty( primaryKey ) );
implicitSortDescriptions.Add( new SortDescription( primaryKey, directionToUseForImplicitSortDescriptions ) );
}
}
return queryable.OrderBy( implicitSortDescriptions, explicitSortDescriptions, reverseSort );
}
#endregion PRIVATE METHODS
#region PRIVATE FIELDS
private IQueryable m_unsortedFilteredQueryable;
private IQueryable m_selectQueryable;
private IQueryable m_reversedSelectQueryable;
#endregion PRIVATE FIELDS
}
}

146
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewGroupRoot.cs

@ -1,146 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections;
using System.Linq.Expressions;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridVirtualizingQueryableCollectionViewGroupRoot : DataGridVirtualizingQueryableCollectionViewGroup
{
#region CONSTRUCTORS
internal DataGridVirtualizingQueryableCollectionViewGroupRoot(
DataGridVirtualizingQueryableCollectionView collectionView,
object pageManagerSyncRoot,
bool isBottomLevel )
: base( null, -1, 0, null, -1, isBottomLevel )
{
m_parentCollectionView = collectionView;
m_queryableSource = m_parentCollectionView.QueryableSource;
if( m_queryableSource != null )
{
m_primaryKeyPropertyNames = m_queryableSource.FindPrimaryKeys();
// Primary key optimizations are only possible when only one primary key is identified in the source.
// When dealing with sources defining more than one primary key, we would need to know in which order
bool supportsPrimaryKeyOptimizations = ( ( m_primaryKeyPropertyNames != null ) && ( m_primaryKeyPropertyNames.Length == 1 ) );
m_virtualPageManager = new DataGridLINQPageManager( collectionView,
pageManagerSyncRoot,
supportsPrimaryKeyOptimizations );
}
}
#endregion CONSTRUCTORS
#region PROTECTED METHODS
protected override DataGridVirtualizingCollectionViewBase GetCollectionView()
{
return m_parentCollectionView;
}
#endregion PROTECTED METHODS
#region INTERNAL PROPERTIES
public string[] PrimaryKeys
{
get
{
return m_primaryKeyPropertyNames;
}
}
#endregion INTERNAL PROPERTIES
#region INTERNAL METHODS
internal override IQueryable CreateUnsortedFilteredQueryable()
{
return m_queryableSource;
}
internal override int GetGlobalIndexOf( object item )
{
return m_virtualPageManager.GetGlobalIndexOf( item );
}
internal override DataGridPageManagerBase GetVirtualPageManager()
{
return m_virtualPageManager;
}
internal object[] GetItemPropertyDistinctValues( DataGridItemPropertyBase dataGridItemProperty )
{
if( m_queryableSource == null )
return new object[ 0 ];
IQueryable distinctQueryable = m_queryableSource.GetSubGroupsAndCountsQueryable( dataGridItemProperty.Name, false, ListSortDirection.Ascending );
List<object> distinctValuesAndCounts = new List<object>();
try
{
System.Collections.IEnumerator enumerator = distinctQueryable.GetEnumerator();
while( enumerator.MoveNext() )
{
QueryableExtensions.IQueryableGroupNameCountPair current = enumerator.Current as QueryableExtensions.IQueryableGroupNameCountPair;
if( current != null )
distinctValuesAndCounts.Add( current.GroupName );
}
return distinctValuesAndCounts.ToArray();
}
catch
{
// TimeOut exception on the connection or other.
return new object[ 0 ];
}
}
internal override void DisposeCore()
{
m_parentCollectionView = null;
m_queryableSource = null;
m_virtualPageManager = null;
base.DisposeCore();
}
#endregion INTERNAL METHODS
#region PRIVATE FIELDS
private DataGridVirtualizingQueryableCollectionView m_parentCollectionView;
private IQueryable m_queryableSource;
private string[] m_primaryKeyPropertyNames;
private DataGridLINQPageManager m_virtualPageManager;
#endregion PRIVATE FIELDS
}
}

77
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingQueryableCollectionViewSource.cs

@ -1,77 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
public class DataGridVirtualizingQueryableCollectionViewSource : DataGridVirtualizingCollectionViewSourceBase
{
static DataGridVirtualizingQueryableCollectionViewSource()
{
CollectionViewSource.CollectionViewTypeProperty.OverrideMetadata(
typeof( DataGridVirtualizingQueryableCollectionViewSource ),
new FrameworkPropertyMetadata( typeof( DataGridVirtualizingQueryableCollectionView ) ) );
}
#region QueryableSource Property
public static readonly DependencyProperty QueryableSourceProperty = DependencyProperty.Register(
"QueryableSource",
typeof( IQueryable ),
typeof( DataGridVirtualizingQueryableCollectionViewSource ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( DataGridVirtualizingQueryableCollectionViewSource.OnQueryableSourcePropertyChanged ) ) );
public IQueryable QueryableSource
{
get
{
return ( IQueryable )GetValue( DataGridVirtualizingQueryableCollectionViewSource.QueryableSourceProperty );
}
set
{
this.SetValue( DataGridVirtualizingQueryableCollectionViewSource.QueryableSourceProperty, value );
}
}
private static void OnQueryableSourcePropertyChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
var source = sender as DataGridCollectionViewSourceBase;
if( source == null )
return;
source.AdviseForwardedPropertyChanged();
var provider = source.DataSourceProvider;
if( provider != null )
{
provider.DelayRefresh( source.Dispatcher, DispatcherPriority.DataBind );
}
}
#endregion
internal override DataGridCollectionViewBaseDataProvider CreateDataProvider()
{
return new DataGridVirtualizingQueryableCollectionViewDataProvider( this );
}
}
}

141
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataRelationDetailDescription.cs

@ -1,141 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Data;
namespace Xceed.Wpf.DataGrid
{
internal class DataRelationDetailDescription : DataGridDetailDescription
{
public DataRelationDetailDescription()
: base()
{
}
public DataRelationDetailDescription( DataRelation relation )
: this()
{
if( relation == null )
throw new ArgumentNullException( "relation" );
this.DataRelation = relation;
m_userAssignedDataRelation = true;
}
#region DataRelation Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public DataRelation DataRelation
{
get
{
return m_dataRelation;
}
set
{
if( value == null )
throw new ArgumentNullException( "DataRelation" );
if( this.InternalIsSealed )
throw new InvalidOperationException( "An attempt was made to set the DataRelation property after the DataRelationDetailDescription has been sealed." );
m_dataRelation = value;
this.RelationName = value.RelationName;
this.Seal();
}
}
#endregion
protected internal override void Initialize( DataGridCollectionViewBase parentCollectionView )
{
base.Initialize( parentCollectionView );
if( this.DataRelation != null )
return;
string relationName = this.RelationName;
if( string.IsNullOrEmpty( relationName ) )
throw new InvalidOperationException( "An attempt was made to initialize a DataRelationDetailDescription whose RelationName property has not been set." );
this.DataRelation = this.FindDataRelation( parentCollectionView, relationName );
}
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem )
{
if( this.DataRelation == null )
throw new InvalidOperationException( "An attempt was made to obtain the details of a DataRelationDetailDescription object whose DataRelation property has not been set." );
this.Seal();
System.Data.DataRow dataRow = parentItem as System.Data.DataRow;
DataRowView dataRowView;
if( dataRow != null )
{
int rawIndex = parentCollectionView.IndexOfSourceItem( dataRow );
DataView dataView = parentCollectionView.SourceCollection as DataView;
if( dataView == null )
return null;
dataRowView = dataView[ rawIndex ];
}
else
{
dataRowView = parentItem as DataRowView;
}
if( dataRowView == null )
return null;
if( !m_userAssignedDataRelation )
{
if( m_dataRelation.ParentTable != dataRowView.Row.Table )
{
m_dataRelation = this.FindDataRelation( parentCollectionView, this.RelationName );
}
}
return dataRowView.CreateChildView( m_dataRelation );
}
private DataRelation FindDataRelation( DataGridCollectionViewBase parentCollectionView, string relationName )
{
DataView view = parentCollectionView.SourceCollection as DataView;
if( view == null )
throw new InvalidOperationException( "An attempt was made to initialize a DataRelationDetailDescription whose data source is not a DataView." );
foreach( DataRelation relation in view.Table.ChildRelations )
{
if( relation.RelationName == relationName )
{
return relation;
}
}
throw new InvalidOperationException( "An attempt was made to initialize a DataRelationDetailDescription whose data source does not contain a DataRelation corresponding to the specified name." );
}
private DataRelation m_dataRelation;
private bool m_userAssignedDataRelation;
}
}

192
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataRowColumnPropertyDescriptor.cs

@ -1,192 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
namespace Xceed.Wpf.DataGrid
{
internal sealed class DataRowColumnPropertyDescriptor : PropertyDescriptor
{
internal DataRowColumnPropertyDescriptor( DataColumn column )
: base( column.ColumnName, null )
{
if( column == null )
throw new ArgumentNullException( "column" );
m_column = column;
}
#region DisplayName Property
public override string DisplayName
{
get
{
return m_column.Caption;
}
}
#endregion
#region Attributes Property
public override AttributeCollection Attributes
{
get
{
if( typeof( IList ).IsAssignableFrom( this.PropertyType ) )
{
var array = new Attribute[ base.Attributes.Count + 1 ];
base.Attributes.CopyTo( array, 0 );
array[ array.Length - 1 ] = new ListBindableAttribute( false );
return new AttributeCollection( array );
}
return base.Attributes;
}
}
#endregion
#region ComponentType Property
public override Type ComponentType
{
get
{
return typeof( System.Data.DataRow );
}
}
#endregion
#region IsBrowsable Property
public override bool IsBrowsable
{
get
{
return ( m_column.ColumnMapping != MappingType.Hidden )
&& ( base.IsBrowsable );
}
}
#endregion
#region IsReadOnly Property
public override bool IsReadOnly
{
get
{
return m_column.ReadOnly;
}
}
#endregion
#region PropertyType Property
public override Type PropertyType
{
get
{
return ItemsSourceHelper.GetColumnDataType( m_column );
}
}
#endregion
public override bool CanResetValue( object component )
{
var value = this.GetValue( component );
return ( value != null )
&& ( value != DBNull.Value );
}
public override object GetValue( object component )
{
var dataRow = component as System.Data.DataRow;
if( dataRow == null )
return null;
var value = default( object );
try
{
value = dataRow[ m_column ];
}
catch
{
}
if( value == DBNull.Value )
return null;
return value;
}
public override void ResetValue( object component )
{
this.SetValue( component, null );
}
public override void SetValue( object component, object value )
{
var dataRow = component as System.Data.DataRow;
if( dataRow == null )
throw new InvalidOperationException( "An attempt was made to set a value on a DataRow that does not exist." );
if( this.IsReadOnly )
throw new InvalidOperationException( "An attempt was made to set a value on a read-only field." );
var oldValue = dataRow[ m_column ];
if( ( oldValue == null ) || ( oldValue == DBNull.Value ) )
{
if( ( ( value == null ) || ( value == DBNull.Value ) ) )
return;
}
else
{
if( oldValue.Equals( value ) )
return;
}
if( value == null )
{
dataRow[ m_column ] = DBNull.Value;
}
else
{
dataRow[ m_column ] = value;
}
this.OnValueChanged( component, EventArgs.Empty );
}
public override bool ShouldSerializeValue( object component )
{
return false;
}
private readonly DataColumn m_column;
}
}

229
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DeferredOperation.cs

@ -1,229 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
internal class DeferredOperation
{
internal static DeferredOperation RefreshDistinctValuesOperation = new DeferredOperation( DeferredOperationAction.RefreshDistincValues, false );
internal static DeferredOperation RefreshDistinctValuesOperationWithFilteredItemsChanged = new DeferredOperation( DeferredOperationAction.RefreshDistincValues, true );
public DeferredOperation( DeferredOperationAction action, bool filteredItemsChanged )
: this( action, -1, -1, null )
{
m_filteredItemsChanged = filteredItemsChanged;
}
public DeferredOperation( DeferredOperationAction action, object dataItem )
{
m_action = action;
m_dataItem = dataItem;
}
public DeferredOperation( DeferredOperationAction action, IList items )
{
m_action = action;
m_newItems = items;
}
public DeferredOperation( DeferredOperationAction action, int startingIndex, IList items )
: this( action, -1, startingIndex, items )
{
}
public DeferredOperation( DeferredOperationAction action, int newSourceItemCount, int startingIndex, IList items )
{
// newSourceItemCount is for when we are adding item in a IBindingList
// It is use to detect we 2 add are in fact only one, bcause the second one is just for confirming the first one.
m_action = action;
m_newSourceItemCount = newSourceItemCount;
switch( action )
{
case DeferredOperationAction.Add:
case DeferredOperationAction.Replace:
{
m_newItems = items;
m_newStartingIndex = startingIndex;
break;
}
case DeferredOperationAction.Remove:
{
m_oldItems = items;
m_oldStartingIndex = startingIndex;
break;
}
case DeferredOperationAction.Refresh:
case DeferredOperationAction.Resort:
case DeferredOperationAction.Regroup:
case DeferredOperationAction.RefreshDistincValues:
break;
default:
{
throw new ArgumentException( "An attempt was made to use the " + action.ToString() + " action, which is not supported by this constructor." );
}
}
}
public DeferredOperation( DeferredOperationAction action, int newSourceItemCount, int newStartingIndex, IList newItems, int oldStartingIndex, IList oldItems )
{
// newSourceItemCount is for when we are adding item in a IBindingList
// It is use to detect that 2 add are in fact only one, because the second one is just for confirming the first one.
m_action = action;
m_newSourceItemCount = newSourceItemCount;
m_newItems = newItems;
m_newStartingIndex = newStartingIndex;
m_oldItems = oldItems;
m_oldStartingIndex = oldStartingIndex;
}
#region Action Property
public DeferredOperationAction Action
{
get
{
return m_action;
}
}
private DeferredOperationAction m_action;
#endregion Action Property
#region NewSourceItemCount Property
public int NewSourceItemCount
{
get
{
return m_newSourceItemCount;
}
}
private int m_newSourceItemCount;
#endregion NewSourceItemCount Property
#region NewStartingIndex Property
public int NewStartingIndex
{
get
{
return m_newStartingIndex;
}
}
private int m_newStartingIndex;
#endregion NewStartingIndex Property
#region NewItems Property
public IList NewItems
{
get
{
return m_newItems;
}
}
private IList m_newItems;
#endregion NewItems Property
#region OldStartingIndex Property
public int OldStartingIndex
{
get
{
return m_oldStartingIndex;
}
}
private int m_oldStartingIndex;
#endregion OldStartingIndex Property
#region OldItems Property
public IList OldItems
{
get
{
return m_oldItems;
}
}
private IList m_oldItems;
#endregion OldItems Property
#region DataItem Property
public object DataItem
{
get
{
return m_dataItem;
}
}
private object m_dataItem;
#endregion
#region FilteredItemsChanged Property
public bool FilteredItemsChanged
{
get
{
return m_filteredItemsChanged;
}
}
private bool m_filteredItemsChanged;
#endregion FilteredItemsChanged Property
internal enum DeferredOperationAction
{
Unknow = 0,
Add = 1,
Move = 2,
Remove = 3,
Replace = 4,
Refresh = 5,
Resort = 6,
Regroup = 7,
RefreshDistincValues = 8,
ResetItem = 9,
RefreshUnboundItemProperties = 10
}
}
}

599
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DeferredOperationManager.cs

@ -1,599 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
internal sealed class DeferredOperationManager
{
#region Static Fields
private static readonly TimeSpan MaxProcessDuration = TimeSpan.FromMilliseconds( 100d );
private static readonly TimeSpan MaxQueueDuration = TimeSpan.FromMilliseconds( 20d );
#endregion
internal DeferredOperationManager( DataGridCollectionViewBase collectionView, Dispatcher dispatcher, bool postPendingRefreshWithoutDispatching )
{
m_collectionView = collectionView;
m_deferredOperations = new List<DeferredOperation>( 1000 );
m_invalidatedGroups = new HashSet<DataGridCollectionViewGroup>();
if( postPendingRefreshWithoutDispatching )
{
this.Add( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ) );
}
m_dispatcher = dispatcher;
}
#region HasPendingOperations Property
public bool HasPendingOperations
{
get
{
lock( this )
{
return ( m_pendingFlags.Data != 0 ) || ( m_deferredOperations.Count > 0 );
}
}
}
#endregion
#region RefreshPending Property
public bool RefreshPending
{
get
{
return m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RefreshPending ];
}
private set
{
m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RefreshPending ] = value;
}
}
#endregion
#region ResortPending Property
public bool ResortPending
{
get
{
return m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.ResortPending ];
}
private set
{
m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.ResortPending ] = value;
}
}
#endregion
#region RegroupPending Property
public bool RegroupPending
{
get
{
return m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RegroupPending ];
}
private set
{
m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RegroupPending ] = value;
}
}
#endregion
#region RefreshDistincValuesPending Property
public bool RefreshDistincValuesPending
{
get
{
return m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RefreshDistincValuesPending ];
}
private set
{
m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RefreshDistincValuesPending ] = value;
}
}
#endregion
#region RefreshDistincValuesWithFilteredItemChangedPending Property
public bool RefreshDistincValuesWithFilteredItemChangedPending
{
get
{
return m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RefreshDistincValuesWithFilteredItemChangedPending ];
}
private set
{
m_pendingFlags[ ( int )DeferredOperationManagerPendingFlags.RefreshDistincValuesWithFilteredItemChangedPending ] = value;
}
}
#endregion
#region DeferProcessOfInvalidatedGroupStats Property
internal bool DeferProcessOfInvalidatedGroupStats
{
private get
{
return m_deferProcessOfInvalidatedGroupStats;
}
set
{
lock( this )
{
//Make sure that stats calculation that have been defer are processed before defering again!
if( value && ( m_deferredOperationsToProcess > 0 ) )
{
m_forceProcessOfInvalidatedGroupStats = true;
}
m_deferProcessOfInvalidatedGroupStats = value;
}
}
}
private bool m_deferProcessOfInvalidatedGroupStats;
#endregion
public void ClearInvalidatedGroups()
{
lock( this )
{
if( ( m_dispatcherOperation != null ) && ( !this.HasPendingOperations ) )
{
m_dispatcherOperation.Abort();
m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
}
m_invalidatedGroups.Clear();
}
}
public void ClearDeferredOperations()
{
lock( this )
{
if( ( m_dispatcherOperation != null ) && ( m_invalidatedGroups.Count == 0 ) )
{
m_dispatcherOperation.Abort();
m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
}
m_pendingFlags[ -1 ] = false;
m_deferredOperations.Clear();
}
}
public void PurgeAddWithRemoveOrReplace()
{
if( m_deferredOperations.Count >= 2 )
{
var addOperation = m_deferredOperations[ 0 ];
if( addOperation.Action != DeferredOperation.DeferredOperationAction.Add )
return;
var addIndex = addOperation.NewStartingIndex;
var addCount = addOperation.NewItems.Count;
var firstIndexToRemove = 1;
var lastIndexToRemove = -1;
var count = m_deferredOperations.Count;
for( int i = 1; i < count; i++ )
{
var operation = m_deferredOperations[ i ];
var replaced = ( operation.Action == DeferredOperation.DeferredOperationAction.Replace );
var removed = ( operation.Action == DeferredOperation.DeferredOperationAction.Remove );
if( replaced || removed )
{
if( removed && ( i < count - 1 ) )
{
Debug.Fail( "How come we have a remove operation before the end?" );
return;
}
if( ( addIndex == operation.OldStartingIndex ) && ( addCount == operation.OldItems.Count ) )
{
lastIndexToRemove = i;
if( removed )
{
firstIndexToRemove = 0;
}
}
else
{
Debug.Fail( "Why do we have a replace or remove operation with different indexes?" );
return;
}
}
else
{
// Can be normal, we can receive 2 adds for the same item and same position when we are bound to an IBindingList ( like a DataView )
return;
}
}
if( lastIndexToRemove > -1 )
{
m_deferredOperations.RemoveRange( firstIndexToRemove, ( lastIndexToRemove - firstIndexToRemove ) + 1 );
}
}
}
public void Add( DeferredOperation operation )
{
lock( this )
{
if( this.RefreshPending )
return;
switch( operation.Action )
{
case DeferredOperation.DeferredOperationAction.Refresh:
{
this.RefreshPending = true;
m_deferredOperations.Clear();
break;
}
case DeferredOperation.DeferredOperationAction.RefreshDistincValues:
{
if( operation.FilteredItemsChanged )
{
this.RefreshDistincValuesWithFilteredItemChangedPending = true;
}
else
{
this.RefreshDistincValuesPending = true;
}
break;
}
case DeferredOperation.DeferredOperationAction.Regroup:
{
this.RegroupPending = true;
break;
}
case DeferredOperation.DeferredOperationAction.Resort:
{
this.ResortPending = true;
break;
}
default:
{
m_deferredOperations.Add( operation );
m_hasNewOperationsSinceStartTime = true;
if( this.DeferProcessOfInvalidatedGroupStats )
{
m_deferredOperationsToProcess++;
}
break;
}
}
if( ( m_dispatcher != null ) && ( m_dispatcherOperation == null ) )
{
Debug.Assert( m_collectionView.Loaded );
m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.DataBind, new DispatcherOperationCallback( this.Dispatched_Process ), null );
m_dispatcherOperationStartTime = DateTime.UtcNow;
m_hasNewOperationsSinceStartTime = false;
}
}
}
public void Combine( DeferredOperationManager sourceDeferredOperationManager )
{
lock( this )
{
this.RefreshPending = this.RefreshPending || sourceDeferredOperationManager.RefreshPending;
this.RegroupPending = this.RegroupPending || sourceDeferredOperationManager.RegroupPending;
this.ResortPending = this.ResortPending || sourceDeferredOperationManager.ResortPending;
this.RefreshDistincValuesPending = this.RefreshDistincValuesPending || sourceDeferredOperationManager.RefreshDistincValuesPending;
this.RefreshDistincValuesWithFilteredItemChangedPending = this.RefreshDistincValuesWithFilteredItemChangedPending || sourceDeferredOperationManager.RefreshDistincValuesWithFilteredItemChangedPending;
if( this.RefreshPending )
{
m_deferredOperations.Clear();
return;
}
List<DeferredOperation> sourceOperations = sourceDeferredOperationManager.m_deferredOperations;
if( sourceOperations.Count == 0 )
return;
m_deferredOperations.InsertRange( 0, sourceOperations );
}
}
public void Process()
{
this.Process( true );
}
public void InvalidateGroupStats( DataGridCollectionViewGroup group, bool calculateAllStats = false, bool resortGroups = true )
{
if( group == null )
return;
lock( this )
{
if( this.RefreshPending )
return;
// When set to false, this will prevent group resorting when the DataGridCollectionView.ProcessInvalidatedGroupStats() is called through the disptached call below.
// If the current method is called again and this variable is set to true before groups are processed, it will be fine, as the grid is now in a state that will support group resorting.
m_resortGroups = resortGroups;
var parent = group;
while( parent != null )
{
if( !m_invalidatedGroups.Contains( parent ) )
{
m_invalidatedGroups.Add( parent );
}
parent = parent.Parent;
}
if( m_dispatcher != null )
{
if( m_dispatcherOperation == null )
{
m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.DataBind, new DispatcherOperationCallback( this.Dispatched_Process ), null );
m_dispatcherOperationStartTime = DateTime.UtcNow;
}
else
{
m_hasNewOperationsSinceStartTime = true;
}
}
}
}
private object Dispatched_Process( object e )
{
this.Process( false );
return null;
}
private void Process( bool processAll )
{
//This method will be called again when Dispose() is called on the DeferRefreshHelper of the CollectionView.
if( m_collectionView.InDeferRefresh )
return;
if( !processAll )
{
lock( this )
{
if( ( m_hasNewOperationsSinceStartTime )
&& ( m_dispatcherOperation != null )
&& ( DateTime.UtcNow.Subtract( m_dispatcherOperationStartTime ) < DeferredOperationManager.MaxQueueDuration ) )
{
Debug.Assert( m_dispatcher != null );
m_dispatcherOperation = m_dispatcher.BeginInvoke( m_dispatcherOperation.Priority, new DispatcherOperationCallback( this.Dispatched_Process ), null );
m_hasNewOperationsSinceStartTime = false;
return;
}
}
}
// We lock here since it is possible that a DataTable Column's value array is being redimensioned
// while we are trying to process the DeferredOperation.
lock( m_collectionView.SyncRoot )
{
lock( this )
{
// Abort the current dispatcher operation
if( m_dispatcherOperation != null )
{
m_dispatcherOperation.Abort();
m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
}
// A deferredOperation can cause a DeferRefresh to be disposed of, hence provoking a re-entry in this method.
// As a result, all variables must be cached to prevent re-executing the same deferredOperation.
List<DeferredOperation> deferredOperations = m_deferredOperations;
//Set a new list in case new operations are added while processing the current operations.
m_deferredOperations = new List<DeferredOperation>( 10 );
bool refreshDistincValuesWithFilteredItemChangedPending = this.RefreshDistincValuesWithFilteredItemChangedPending;
this.RefreshDistincValuesWithFilteredItemChangedPending = false;
bool refreshDistincValuesPending = this.RefreshDistincValuesPending;
this.RefreshDistincValuesPending = false;
bool refreshPending = this.RefreshPending;
this.RefreshPending = false;
bool regroupPending = this.RegroupPending;
this.RegroupPending = false;
bool resortPending = this.ResortPending;
this.ResortPending = false;
bool refreshForced = false;
m_collectionView.RaisePreBatchCollectionChanged();
DateTime startTime = DateTime.UtcNow;
if( refreshPending )
{
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ), out refreshForced );
}
else if( regroupPending )
{
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Regroup, -1, null ), out refreshForced );
}
else if( resortPending )
{
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Resort, -1, null ), out refreshForced );
}
if( ( deferredOperations.Count > 0 ) && ( !refreshForced ) )
{
int count = deferredOperations.Count;
int operationIndex = 0;
while( ( operationIndex < count ) && ( !refreshForced ) && ( processAll || ( DateTime.UtcNow.Subtract( startTime ) < DeferredOperationManager.MaxProcessDuration ) ) )
{
m_collectionView.ExecuteSourceItemOperation( deferredOperations[ operationIndex ], out refreshForced );
operationIndex++;
}
if( ( operationIndex < count ) && ( !refreshForced ) )
{
deferredOperations.RemoveRange( 0, operationIndex );
m_deferredOperationsToProcess -= operationIndex;
}
else
{
deferredOperations.Clear();
m_deferredOperationsToProcess = 0;
}
}
if( m_deferredOperations.Count == 0 )
{
m_deferredOperations = deferredOperations;
}
else
{
// When this method is re-entered, the processAll parameter should be true, which means all deferredOperations should have been processed. When assigning it back to m_deferredOperations,
// it's count should be 0. Thus in the previous call on the stack, the "if" condition should always be true, hence this assert.
Debug.Assert( false, "Should never get there." );
//To be GC friendly, keep the original list, which at one point is the one created with a capacity of a 1000 items.
deferredOperations.InsertRange( deferredOperations.Count, m_deferredOperations );
m_deferredOperations = deferredOperations;
}
// The recalculation of the StatFunctions is performed last.
if( ( m_deferredOperationsToProcess <= 0 || m_forceProcessOfInvalidatedGroupStats ) && ( m_invalidatedGroups.Count != 0 ) )
{
m_collectionView.ProcessInvalidatedGroupStats( m_invalidatedGroups, m_resortGroups );
m_invalidatedGroups.Clear();
m_forceProcessOfInvalidatedGroupStats = false;
}
// Since a refresh has been forced, we don't want to process anything else.
if( !refreshForced )
{
if( processAll || ( DateTime.UtcNow.Subtract( startTime ) < DeferredOperationManager.MaxProcessDuration ) )
{
if( refreshDistincValuesWithFilteredItemChangedPending || refreshDistincValuesPending )
{
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.RefreshDistincValues,
refreshDistincValuesWithFilteredItemChangedPending ), out refreshForced );
}
}
else
{
if( refreshDistincValuesWithFilteredItemChangedPending )
{
this.RefreshDistincValuesWithFilteredItemChangedPending = true;
}
if( refreshDistincValuesPending )
{
this.RefreshDistincValuesPending = true;
}
}
}
m_collectionView.RaisePostBatchCollectionChanged();
if( this.HasPendingOperations || m_invalidatedGroups.Count != 0 )
{
Debug.Assert( !processAll );
Debug.Assert( m_dispatcher != null );
// Requeue pending operations
if( m_dispatcherOperation == null )
{
if( m_dispatcher != null )
{
m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.Input, new DispatcherOperationCallback( this.Dispatched_Process ), null );
m_dispatcherOperationStartTime = DateTime.UtcNow;
m_hasNewOperationsSinceStartTime = false;
}
}
else
{
m_dispatcherOperation.Priority = DispatcherPriority.Input;
m_dispatcherOperationStartTime = DateTime.UtcNow;
}
}
}
}
}
private readonly DataGridCollectionViewBase m_collectionView;
private List<DeferredOperation> m_deferredOperations;
private HashSet<DataGridCollectionViewGroup> m_invalidatedGroups;
private int m_deferredOperationsToProcess;
private BitVector32 m_pendingFlags;
private bool m_forceProcessOfInvalidatedGroupStats;
private bool m_resortGroups;
private readonly Dispatcher m_dispatcher;
private DispatcherOperation m_dispatcherOperation;
private DateTime m_dispatcherOperationStartTime;
private bool m_hasNewOperationsSinceStartTime;
[Flags]
private enum DeferredOperationManagerPendingFlags
{
RegroupPending = 1,
ResortPending = 2,
RefreshPending = 4,
RefreshDistincValuesPending = 8,
RefreshDistincValuesWithFilteredItemChangedPending = 16
}
}
}

74
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DistinctValuesDictionary.cs

@ -1,74 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System.Diagnostics;
using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid
{
internal class DistinctValuesDictionary : ReadOnlyDictionary<string, ReadOnlyObservableHashList>
{
public DistinctValuesDictionary( DataGridCollectionViewBase dataGridCollectionViewBase )
{
if( dataGridCollectionViewBase == null )
throw new DataGridInternalException( "dataGridCollectionView is null." );
m_dataGridCollectionViewBase = dataGridCollectionViewBase;
}
public override ReadOnlyObservableHashList this[ string key ]
{
get
{
return this.AssertValueIsCreated( key );
}
set
{
base[ key ] = value;
}
}
public override bool TryGetValue( string key, out ReadOnlyObservableHashList value )
{
// We force the creation of the key in the Dictionary
value = this.AssertValueIsCreated( key );
return true;
}
internal bool InternalTryGetValue( string key, out ReadOnlyObservableHashList value )
{
return base.TryGetValue( key, out value );
}
private ReadOnlyObservableHashList AssertValueIsCreated( string key )
{
ReadOnlyObservableHashList value = null;
if( !base.TryGetValue( key, out value ) )
{
value = new ReadOnlyObservableHashList();
this.InternalAdd( key, value );
}
Debug.Assert( value != null );
return value;
}
private DataGridCollectionViewBase m_dataGridCollectionViewBase;
}
}

83
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DistinctValuesRefreshNeededEventManager.cs

@ -1,83 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class DistinctValuesRefreshNeededEventManager : WeakEventManager
{
#region Constructor
private DistinctValuesRefreshNeededEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static DistinctValuesRefreshNeededEventManager CurrentManager
{
get
{
var managerType = typeof( DistinctValuesRefreshNeededEventManager );
var currentManager = ( DistinctValuesRefreshNeededEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new DistinctValuesRefreshNeededEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
}
protected override void StopListening( object source )
{
}
}
}

104
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/EmptyDataItemSafePropertyDescriptor.cs

@ -1,104 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
internal class EmptyDataItemSafePropertyDescriptor : PropertyDescriptor
{
#region STATIC MEMBERS
private const string PropertyName = "__EmptyDataItemPropertyDescriptor";
private static readonly Attribute[] EmptyAttributeArray = new Attribute[ 0 ];
#endregion STATIC MEMBERS
#region SINGLETON
internal static EmptyDataItemSafePropertyDescriptor Singleton
{
get
{
if( ms_Singleton == null )
ms_Singleton = new EmptyDataItemSafePropertyDescriptor( EmptyDataItemSafePropertyDescriptor.PropertyName );
return ms_Singleton;
}
}
private static EmptyDataItemSafePropertyDescriptor ms_Singleton;
#endregion SINGLETON
#region CONSTRUCTORS
public EmptyDataItemSafePropertyDescriptor( string name )
: base( name, EmptyDataItemSafePropertyDescriptor.EmptyAttributeArray )
{
}
#endregion CONSTRUCTORS
public override bool CanResetValue( object component )
{
return false;
}
public override Type ComponentType
{
get { return typeof( object ); }
}
public override object GetValue( object component )
{
if( component is EmptyDataItem )
return null;
return component;
}
public override bool IsReadOnly
{
get { return true; }
}
public override Type PropertyType
{
get { return typeof( object ); }
}
public override void ResetValue( object component )
{
throw new NotImplementedException();
}
public override void SetValue( object component, object value )
{
throw new NotImplementedException();
}
public override bool ShouldSerializeValue( object component )
{
return false;
}
}
}

107
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/EntityDetailDescription.cs

@ -1,107 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.ComponentModel;
using System.Data.Objects.DataClasses;
using System.Reflection;
namespace Xceed.Wpf.DataGrid
{
internal class EntityDetailDescription : DataGridDetailDescription
{
public EntityDetailDescription()
{
}
public EntityDetailDescription( string propertyName )
: this()
{
if( string.IsNullOrEmpty( propertyName ) )
throw new ArgumentException( "The specified property name is null or empty", "propertyName" );
this.RelationName = propertyName;
}
#region QueryDetails Event
public event EventHandler<QueryEntityDetailsEventArgs> QueryDetails;
protected virtual void OnQueryDetails( QueryEntityDetailsEventArgs e )
{
var handler = this.QueryDetails;
if( handler == null )
return;
handler.Invoke( this, e );
}
#endregion
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem )
{
EntityObject entityObject = parentItem as EntityObject;
if( entityObject == null )
return null;
// Even if EntityObject is not in a loadable state, we must still return the IList
// so that the ItemProperties can be extracted based on the elements type.
bool entityObjectLoadable = ItemsSourceHelper.IsEntityObjectLoadable( entityObject );
// We let the user take charge of handling the details.
QueryEntityDetailsEventArgs args = new QueryEntityDetailsEventArgs( entityObject );
if( entityObjectLoadable )
this.OnQueryDetails( args );
// The parentItem must implement IEntityWithRelationships
Type parentItemType = parentItem.GetType();
if( typeof( IEntityWithRelationships ).IsAssignableFrom( parentItemType ) )
{
// Since the relationship was based on the the property
// name, we must find that property using reflection.
PropertyInfo propertyInfo = parentItemType.GetProperty( this.RelationName );
if( propertyInfo != null )
{
RelatedEnd relatedEnd = propertyInfo.GetValue( parentItem, null ) as RelatedEnd;
if( relatedEnd != null )
{
// Make sure that the details are loaded
// except if the user already handled it.
if( !relatedEnd.IsLoaded
&& !args.Handled
&& entityObjectLoadable )
{
relatedEnd.Load();
}
IListSource listSource = relatedEnd as IListSource;
// Returns an IList to have proper change notification events.
if( listSource != null )
return listSource.GetList();
}
}
}
return null;
}
}
}

44
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/EnumerableDetailDescription.cs

@ -1,44 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
namespace Xceed.Wpf.DataGrid
{
internal class EnumerableDetailDescription : DataGridDetailDescription
{
public EnumerableDetailDescription()
: base()
{
this.RelationName = "Children";
}
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem )
{
IEnumerable enumerable = parentItem as IEnumerable;
if (enumerable == null)
return null;
this.Seal();
return enumerable;
}
}
}

89
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupDescriptionCollection.cs

@ -1,89 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class GroupDescriptionCollection : ObservableCollection<GroupDescription>
{
#region CONSTRUCTORS
public GroupDescriptionCollection()
{
}
#endregion CONSTRUCTORS
#region PROTECTED METHODS
protected override void InsertItem( int index, GroupDescription item )
{
string newGroupName;
if( this.IsGroupDescriptionAlreadyPresent( item, out newGroupName ) == true )
throw new DataGridInternalException( "A group with the specified name already exists in the collection: " + ( ( newGroupName != null ) ? newGroupName : "" ) );
base.InsertItem( index, item );
}
protected override void SetItem( int index, GroupDescription item )
{
string newGroupName;
if( this.IsGroupDescriptionAlreadyPresent( item, out newGroupName ) == true )
throw new DataGridInternalException( "A group with the specified name already exists in the collection: " + ( ( newGroupName != null ) ? newGroupName : "" ) );
base.SetItem( index, item );
}
#endregion PROTECTED METHODS
#region PRIVATE METHODS
private bool IsGroupDescriptionAlreadyPresent( GroupDescription newGroupDescription, out string newGroupName )
{
newGroupName = DataGridContext.GetColumnNameFromGroupDescription( newGroupDescription );
// We accept null or empty group names
if( !string.IsNullOrEmpty( newGroupName ) )
{
foreach( GroupDescription groupDescription in this.Items )
{
string groupName = DataGridContext.GetColumnNameFromGroupDescription( groupDescription );
if( !string.IsNullOrEmpty( groupName ) )
{
if( newGroupName == groupName )
{
return true;
}
}
}
}
return false;
}
#endregion PRIVATE METHODS
}
}

41
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupNameCountPair.cs

@ -1,41 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class GroupNameCountPair
{
public GroupNameCountPair( object name, int itemCount )
{
if( name == null )
throw new ArgumentNullException( "name" );
if( itemCount < 0 )
throw new ArgumentOutOfRangeException( "itemCount", "The specified item count must be greater than or equal to zero." );
this.Name = name;
this.ItemCount = itemCount;
}
public object Name { get; private set; }
public int ItemCount { get; private set; }
}
}

147
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupSortComparer.cs

@ -1,147 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Xceed.Utils.Data;
namespace Xceed.Wpf.DataGrid
{
internal class GroupSortComparer : IComparer<DataGridCollectionViewGroup>
{
public GroupSortComparer( List<SortInfo> sortInfos )
{
m_sortInfos = sortInfos;
}
#region IComparer<DataGridCollectionViewGroup> Members
public int Compare( DataGridCollectionViewGroup xGroup, DataGridCollectionViewGroup yGroup )
{
if( xGroup == null )
{
if( yGroup == null )
{
return 0;
}
else
{
return -1;
}
}
else
{
if( yGroup == null )
{
return 1;
}
}
var sortDirection = ListSortDirection.Ascending;
int result;
foreach( SortInfo sortInfo in m_sortInfos )
{
var foreignKeyDescription = sortInfo.ForeignKeyDescription;
var sortComparer = sortInfo.SortComparer;
sortDirection = sortInfo.SortDirection;
if( foreignKeyDescription != null )
{
result = sortComparer.Compare( foreignKeyDescription.GetDisplayValue( xGroup.Name ), foreignKeyDescription.GetDisplayValue( yGroup.Name ) );
}
else
{
result = sortComparer.Compare( xGroup.Name, yGroup.Name );
}
if( result != 0 )
{
if( sortDirection == ListSortDirection.Descending )
return -result;
return result;
}
}
if( sortDirection == ListSortDirection.Descending )
return yGroup.UnsortedIndex - xGroup.UnsortedIndex;
return xGroup.UnsortedIndex - yGroup.UnsortedIndex;
}
#endregion
private List<SortInfo> m_sortInfos;
public class SortInfo
{
public SortInfo( ListSortDirection sortDirection, IComparer sortComparer )
{
if( sortComparer == null )
throw new ArgumentNullException( "sortComparer" );
this.SortDirection = sortDirection;
this.SortComparer = sortComparer;
}
public SortInfo( DataGridForeignKeyDescription foreignKeyDescription, ListSortDirection sortDirection, IComparer sortComparer )
{
if( sortComparer == null )
throw new ArgumentNullException( "sortComparer" );
this.ForeignKeyDescription = foreignKeyDescription;
this.SortDirection = sortDirection;
this.SortComparer = sortComparer;
}
#region ForeignKeyDescription Property
internal DataGridForeignKeyDescription ForeignKeyDescription
{
get;
private set;
}
#endregion
#region SortDirection Property
public ListSortDirection SortDirection
{
get;
private set;
}
#endregion
#region SortComparer Property
public IComparer SortComparer
{
get;
private set;
}
#endregion
}
}
}

92
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ItemPropertyGroupSortStatNameChangedEventManager.cs

@ -1,92 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class ItemPropertyGroupSortStatNameChangedEventManager : WeakEventManager
{
private ItemPropertyGroupSortStatNameChangedEventManager()
{
}
#region CurrentManager Private Property
private static ItemPropertyGroupSortStatNameChangedEventManager CurrentManager
{
get
{
var managerType = typeof( ItemPropertyGroupSortStatNameChangedEventManager );
var currentManager = WeakEventManager.GetCurrentManager( managerType ) as ItemPropertyGroupSortStatNameChangedEventManager;
if( currentManager == null )
{
currentManager = new ItemPropertyGroupSortStatNameChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridItemPropertyCollection source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridItemPropertyCollection source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var target = source as DataGridItemPropertyCollection;
//target.ItemPropertyGroupSortStatNameChanged += new EventHandler( this.DeliverEvent );
target.ItemPropertyGroupSortStatNameChanged += target_ItemPropertyGroupSortStatNameChanged;
}
void target_ItemPropertyGroupSortStatNameChanged( object sender, EventArgs e )
{
this.DeliverEvent( sender, e );
}
protected override void StopListening( object source )
{
var target = source as DataGridItemPropertyCollection;
target.ItemPropertyGroupSortStatNameChanged -= new EventHandler( this.DeliverEvent );
}
}
}

116
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/JaggedArrayPropertyDescriptor.cs

@ -1,116 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.Collections;
using System.Globalization;
namespace Xceed.Wpf.DataGrid
{
internal class JaggedArrayPropertyDescriptor : PropertyDescriptor
{
public JaggedArrayPropertyDescriptor( int columnIndex, Type columnDataType )
: base( ".[" + columnIndex.ToString( CultureInfo.InvariantCulture ) + "]", null )
{
m_columnIndex = columnIndex;
m_columnDataType = columnDataType;
}
public override AttributeCollection Attributes
{
get
{
if( typeof( IList ).IsAssignableFrom( this.PropertyType ) )
{
Attribute[] array = new Attribute[ base.Attributes.Count + 1 ];
base.Attributes.CopyTo( array, 0 );
array[ array.Length - 1 ] = new ListBindableAttribute( false );
return new AttributeCollection( array );
}
return base.Attributes;
}
}
public override Type ComponentType
{
get
{
return m_columnDataType.MakeArrayType();
}
}
public override bool IsReadOnly
{
get
{
return false;
}
}
public override Type PropertyType
{
get
{
return m_columnDataType;
}
}
public override bool CanResetValue( object component )
{
return false;
}
public override object GetValue( object component )
{
Array arrayComponent = component as Array;
if( arrayComponent == null )
return null;
return arrayComponent.GetValue( m_columnIndex );
}
public override void ResetValue( object component )
{
}
public override void SetValue( object component, object value )
{
Array arrayComponent = component as Array;
if( arrayComponent == null )
throw new InvalidOperationException( "An attempt was made to set a value on something other than a one dimension array." );
if( this.IsReadOnly )
throw new InvalidOperationException( "An attempt was made to set a value on a read-only property." );
arrayComponent.SetValue( value, m_columnIndex );
}
public override bool ShouldSerializeValue( object component )
{
return false;
}
private int m_columnIndex;
private Type m_columnDataType;
}
}

47
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ListSourceDetailDescription.cs

@ -1,47 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
internal class ListSourceDetailDescription : DataGridDetailDescription
{
public ListSourceDetailDescription()
: base()
{
this.RelationName = "Children";
}
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem )
{
IListSource listSource = parentItem as IListSource;
if( listSource == null )
return null;
this.Seal();
return listSource.GetList();
}
}
}

78
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PostBatchCollectionChangedEventManager.cs

@ -1,78 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class PostBatchCollectionChangedEventManager : WeakEventManager
{
#region Constructor
private PostBatchCollectionChangedEventManager()
{
}
#endregion
#region CurrentManager Static Property
private static PostBatchCollectionChangedEventManager CurrentManager
{
get
{
var managerType = typeof( PostBatchCollectionChangedEventManager );
var currentManager = ( PostBatchCollectionChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new PostBatchCollectionChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
PostBatchCollectionChangedEventManager.CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
PostBatchCollectionChangedEventManager.CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
( ( DataGridCollectionViewBase )source ).PostBatchCollectionChanged += new EventHandler( this.OnEventRaised );
}
protected override void StopListening( object source )
{
( ( DataGridCollectionViewBase )source ).PostBatchCollectionChanged -= new EventHandler( this.OnEventRaised );
}
private void OnEventRaised( object sender, EventArgs e )
{
this.DeliverEvent( sender, e );
}
}
}

78
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PreBatchCollectionChangedEventManager.cs

@ -1,78 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class PreBatchCollectionChangedEventManager : WeakEventManager
{
#region Constructor
private PreBatchCollectionChangedEventManager()
{
}
#endregion
#region CurrentManager Static Property
private static PreBatchCollectionChangedEventManager CurrentManager
{
get
{
var managerType = typeof( PreBatchCollectionChangedEventManager );
var currentManager = ( PreBatchCollectionChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new PreBatchCollectionChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
PreBatchCollectionChangedEventManager.CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
PreBatchCollectionChangedEventManager.CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
( ( DataGridCollectionViewBase )source ).PreBatchCollectionChanged += new EventHandler( this.OnEventRaised );
}
protected override void StopListening( object source )
{
( ( DataGridCollectionViewBase )source ).PreBatchCollectionChanged -= new EventHandler( this.OnEventRaised );
}
private void OnEventRaised( object sender, EventArgs e )
{
this.DeliverEvent( sender, e );
}
}
}

182
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PropertyDetailDescription.cs

@ -1,182 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
internal class PropertyDetailDescription : DataGridDetailDescription
{
public PropertyDetailDescription()
: base()
{
}
public PropertyDetailDescription( PropertyDescriptor relation )
: this()
{
if( relation == null )
throw new ArgumentNullException( "relation" );
this.PropertyDescriptor = relation;
}
#region PropertyDescriptor Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public PropertyDescriptor PropertyDescriptor
{
get
{
return m_propertyDescriptor;
}
set
{
if( value == null )
throw new ArgumentNullException( "PropertyDescriptor" );
if( this.InternalIsSealed == true )
throw new InvalidOperationException( "An attempt was made to set the PropertyDescriptor property after the PropertyDetailDescription has been sealed." );
m_propertyDescriptor = value;
this.RelationName = value.Name;
this.Seal();
}
}
private PropertyDescriptor m_propertyDescriptor;
#endregion
protected internal override void Initialize( DataGridCollectionViewBase parentCollectionView )
{
base.Initialize( parentCollectionView );
if( this.PropertyDescriptor != null )
return;
string relationName = this.RelationName;
if( String.IsNullOrEmpty( relationName ) == true )
throw new InvalidOperationException( "An attempt was made to initialize a PropertyDetailDescription whose Name property has not been set." );
var enumeration = parentCollectionView as IEnumerable;
if( enumeration != null )
{
// Try to get it from the first item in the DataGridCollectionView
var firstItem = ItemsSourceHelper.GetFirstItemByEnumerable( enumeration );
if( firstItem != null )
{
var propertyDescriptor = this.GetPropertyDescriptorFromFirstItem( firstItem );
if( propertyDescriptor != null )
{
this.PropertyDescriptor = propertyDescriptor;
return;
}
}
}
// If the list is empty, check if the SourceCollection is ITypedList
var typedList = parentCollectionView.SourceCollection as ITypedList;
if( typedList != null )
{
var propertyDescriptor = this.GetPropertyDescriptorFromITypedList( typedList );
if( propertyDescriptor != null )
{
this.PropertyDescriptor = propertyDescriptor;
return;
}
}
throw new InvalidOperationException( "An attempt was made to initialize a PropertyDetailDescription whose data source does not contain a property that corresponds to the specified relation name." );
}
private PropertyDescriptor GetPropertyDescriptorFromITypedList( ITypedList typedList )
{
if( string.IsNullOrEmpty( this.RelationName ) || ( typedList == null ) )
return null;
var properties = typedList.GetItemProperties( null );
if( ( properties != null ) && ( properties.Count > 0 ) )
return properties[ this.RelationName ];
var listName = typedList.GetListName( null );
if( string.IsNullOrEmpty( listName ) )
return null;
var itemType = Type.GetType( listName, false, false );
if( itemType == null )
return null;
var descriptionProvider = TypeDescriptor.GetProvider( itemType );
if( descriptionProvider == null )
return null;
var descriptor = descriptionProvider.GetTypeDescriptor( itemType );
if( descriptor == null )
return null;
properties = descriptor.GetProperties();
if( ( properties != null ) && ( properties.Count > 0 ) )
return properties[ this.RelationName ];
return null;
}
private PropertyDescriptor GetPropertyDescriptorFromFirstItem( object firstItem )
{
if( string.IsNullOrEmpty( this.RelationName ) || ( firstItem == null ) )
return null;
var descriptor = ItemsSourceHelper.GetCustomTypeDescriptorFromItem( firstItem, firstItem.GetType() );
if( descriptor == null )
return null;
var properties = descriptor.GetProperties();
if( ( properties != null ) && ( properties.Count > 0 ) )
return properties[ this.RelationName ];
return null;
}
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem )
{
if( this.PropertyDescriptor == null )
throw new InvalidOperationException( "An attempt was made to obtain details of a PropertyDetailDescription object whose PropertyDescriptor property has not been set." );
this.Seal();
var value = this.PropertyDescriptor.GetValue( parentItem );
if( value == null )
return null;
var enumeration = value as IEnumerable;
if( enumeration == null )
{
var listSource = value as IListSource;
if( listSource != null )
{
enumeration = listSource.GetList();
}
}
return enumeration;
}
}
}

28
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PropertyRelationAttribute.cs

@ -1,28 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
[Obsolete( "The PropertyRelationAttribute is obsolete. All IEnumerable properties will automatically be detected as detail relations. ", false )]
[AttributeUsage( AttributeTargets.Property )]
public sealed class PropertyRelationAttribute: Attribute
{
}
}

87
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyCollectionRefreshEventManager.cs

@ -1,87 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class ProxyCollectionRefreshEventManager : WeakEventManager
{
#region Constructor
private ProxyCollectionRefreshEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ProxyCollectionRefreshEventManager CurrentManager
{
get
{
var managerType = typeof( ProxyCollectionRefreshEventManager );
var currentManager = ( ProxyCollectionRefreshEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ProxyCollectionRefreshEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxyCollectionRefresh += new EventHandler( this.DeliverEvent );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxyCollectionRefresh -= new EventHandler( this.DeliverEvent );
}
}
}

93
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyGroupDescriptionsChangedEventManager.cs

@ -1,93 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Specialized;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class ProxyGroupDescriptionsChangedEventManager : WeakEventManager
{
#region Constructor
private ProxyGroupDescriptionsChangedEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ProxyGroupDescriptionsChangedEventManager CurrentManager
{
get
{
var managerType = typeof( ProxyGroupDescriptionsChangedEventManager );
var currentManager = ( ProxyGroupDescriptionsChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ProxyGroupDescriptionsChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxyGroupDescriptionsChanged += new NotifyCollectionChangedEventHandler( this.OnEventRaised );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxyGroupDescriptionsChanged -= new NotifyCollectionChangedEventHandler( this.OnEventRaised );
}
private void OnEventRaised( object sender, NotifyCollectionChangedEventArgs e )
{
this.DeliverEvent( sender, e );
}
}
}

93
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxySortDescriptionsChangedEventManager.cs

@ -1,93 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Specialized;
using System.Windows;
namespace Xceed.Wpf.DataGrid
{
internal sealed class ProxySortDescriptionsChangedEventManager : WeakEventManager
{
#region Constructor
private ProxySortDescriptionsChangedEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ProxySortDescriptionsChangedEventManager CurrentManager
{
get
{
var managerType = typeof( ProxySortDescriptionsChangedEventManager );
var currentManager = ( ProxySortDescriptionsChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ProxySortDescriptionsChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( DataGridCollectionViewBase source, IWeakEventListener listener )
{
if( source == null )
throw new ArgumentNullException( "source" );
if( listener == null )
throw new ArgumentNullException( "listener" );
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxySortDescriptionsChanged += new NotifyCollectionChangedEventHandler( this.OnEventRaised );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxySortDescriptionsChanged -= new NotifyCollectionChangedEventHandler( this.OnEventRaised );
}
private void OnEventRaised( object sender, NotifyCollectionChangedEventArgs e )
{
this.DeliverEvent( sender, e );
}
}
}

47
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryDistinctValueEventArgs.cs

@ -1,47 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
public class QueryDistinctValueEventArgs : EventArgs
{
internal QueryDistinctValueEventArgs( object dataSourceValue )
{
this.DataSourceValue = dataSourceValue;
// Initialize the DistinctValue as the original DataSourceValue
// in case it is not modified during the QueryDistinctValue event
this.DistinctValue = dataSourceValue;
}
public object DataSourceValue
{
get;
private set;
}
public object DistinctValue
{
get;
set;
}
}
}

61
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryEntityDetailsEventArgs.cs

@ -1,61 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Data.Objects.DataClasses;
namespace Xceed.Wpf.DataGrid
{
public class QueryEntityDetailsEventArgs : EventArgs
{
#region CONSTRUCTORS
internal QueryEntityDetailsEventArgs( EntityObject parentItem )
: base()
{
if( parentItem == null )
throw new ArgumentNullException( "parentItem" );
this.ParentItem = parentItem;
}
#endregion CONSTRUCTORS
#region ParentItem Property
public EntityObject ParentItem
{
get;
private set;
}
#endregion ParentItem Property
#region Handled Property
public bool Handled
{
get;
set;
}
#endregion Handled Property
}
}

148
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryGroupsEventArgs.cs

@ -1,148 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
public class QueryGroupsEventArgs : EventArgs
{
#region CONSTRUCTORS
internal QueryGroupsEventArgs(
DataGridVirtualizingCollectionView collectionView,
DataGridVirtualizingCollectionViewGroup parentGroup,
GroupDescription childGroupDescription )
{
m_dataGridVirtualizingCollectionView = collectionView;
m_readonlyGroupPath = parentGroup.GroupPath.AsReadOnly();
m_childGroupDescription = childGroupDescription;
this.ChildGroupPropertyName = DataGridCollectionViewBase.GetPropertyNameFromGroupDescription( childGroupDescription );
m_sortDirection = SortDirection.None;
SortDescriptionCollection sortDescriptions = m_dataGridVirtualizingCollectionView.SortDescriptions;
int sortDescriptionCount = ( sortDescriptions == null ) ? 0 : sortDescriptions.Count;
for( int i = 0; i < sortDescriptions.Count ; i++ )
{
SortDescription sortDescription = sortDescriptions[ i ];
if( string.Equals( sortDescription.PropertyName, this.ChildGroupPropertyName ) )
{
m_sortDirection = ( sortDescription.Direction == ListSortDirection.Ascending ) ? SortDirection.Ascending : SortDirection.Descending;
break;
}
}
m_childGroupNameCountPairs = new List<GroupNameCountPair>();
}
#endregion CONSTRUCTORS
#region CollectionView PROPERTY
public DataGridVirtualizingCollectionView CollectionView
{
get
{
return m_dataGridVirtualizingCollectionView;
}
}
#endregion CollectionView PROPERTY
#region ChildGroupDescription PROPERTY
public GroupDescription ChildGroupDescription
{
get
{
return m_childGroupDescription;
}
}
#endregion ChildGroupDescription PROPERTY
#region ChildGroupPropertyName PROPERTY
public string ChildGroupPropertyName
{
get;
private set;
}
#endregion ChildGroupPropertyName PROPERTY
#region ChildSortDirection PROPERTY
public SortDirection ChildSortDirection
{
get
{
return m_sortDirection;
}
}
#endregion ChildSortDirection PROPERTY
#region ChildGroupNameCountPairs PROPERTY
public List<GroupNameCountPair> ChildGroupNameCountPairs
{
get
{
return m_childGroupNameCountPairs;
}
}
#endregion ChildGroupNameCountPairs PROPERTY
#region GroupPath PROPERTY
public ReadOnlyCollection<DataGridGroupInfo> GroupPath
{
get
{
return m_readonlyGroupPath;
}
}
#endregion GroupPath PROPERTY
#region PRIVATE FIELDS
private DataGridVirtualizingCollectionView m_dataGridVirtualizingCollectionView;
private GroupDescription m_childGroupDescription;
private SortDirection m_sortDirection;
private ReadOnlyCollection<DataGridGroupInfo> m_readonlyGroupPath;
private List<GroupNameCountPair> m_childGroupNameCountPairs;
#endregion PRIVATE FIELDS
}
}

90
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryItemCountEvent.cs

@ -1,90 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.DataGrid
{
public class QueryItemCountEventArgs : EventArgs
{
#region CONSTRUCTORS
internal QueryItemCountEventArgs( DataGridVirtualizingCollectionView collectionView,
DataGridVirtualizingCollectionViewGroup collectionViewGroup )
{
m_dataGridVirtualizingCollectionView = collectionView;
m_readonlyGroupPath = collectionViewGroup.GroupPath.AsReadOnly();
m_count = -1;
}
#endregion CONSTRUCTORS
#region CollectionView PROPERTY
public DataGridVirtualizingCollectionView CollectionView
{
get
{
return m_dataGridVirtualizingCollectionView;
}
}
#endregion CollectionView PROPERTY
#region GroupPath PROPERTY
public ReadOnlyCollection<DataGridGroupInfo> GroupPath
{
get
{
return m_readonlyGroupPath;
}
}
#endregion GroupPath PROPERTY
#region Count PROPERTY
public int Count
{
get
{
return m_count;
}
set
{
m_count = value;
}
}
#endregion Count PROPERTY
#region PRIVATE FIELDS
private DataGridVirtualizingCollectionView m_dataGridVirtualizingCollectionView;
private ReadOnlyCollection<DataGridGroupInfo> m_readonlyGroupPath;
private int m_count;
#endregion PRIVATE FIELDS
}
}

95
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryItemsEvent.cs

@ -1,95 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.DataGrid
{
public class QueryItemsEventArgs : EventArgs
{
internal QueryItemsEventArgs(
DataGridVirtualizingCollectionView collectionView,
DataGridVirtualizingCollectionViewGroup collectionViewGroup,
AsyncQueryInfo asyncQueryInfo )
{
m_dataGridVirtualizingCollectionView = collectionView;
// The collectionViewGroup can be null when we abort
// a QueryItems for the old RootGroup when
// DataGridVirtualizingCollectionViewBase.ForceRefresh
// is called
m_readonlyGroupPath = ( collectionViewGroup != null )
? collectionViewGroup.GroupPath.AsReadOnly()
: new ReadOnlyCollection<DataGridGroupInfo>( new List<DataGridGroupInfo>() );
m_asyncQueryInfo = asyncQueryInfo;
}
#region CollectionView PROPERTY
public DataGridVirtualizingCollectionView CollectionView
{
get
{
return m_dataGridVirtualizingCollectionView;
}
}
#endregion CollectionView PROPERTY
#region GroupPath PROPERTY
public ReadOnlyCollection<DataGridGroupInfo> GroupPath
{
get
{
return m_readonlyGroupPath;
}
}
#endregion GroupPath PROPERTY
#region AsyncQueryInfo PROPERTY
public AsyncQueryInfo AsyncQueryInfo
{
get
{
return m_asyncQueryInfo;
}
}
#endregion AsyncQueryInfo PROPERTY
#region PRIVATE FIELDS
private DataGridVirtualizingCollectionView m_dataGridVirtualizingCollectionView;
private AsyncQueryInfo m_asyncQueryInfo;
private ReadOnlyCollection<DataGridGroupInfo> m_readonlyGroupPath;
#endregion PRIVATE FIELDS
}
}

798
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryableExtensions.cs

@ -1,798 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace Xceed.Wpf.DataGrid
{
internal static class QueryableExtensions
{
#region REFLECTION METHODS
private static MemberInfo GetMemberInfo( Type type, string memberName )
{
MemberInfo[] members = type.FindMembers( MemberTypes.Property | MemberTypes.Field,
BindingFlags.Public | BindingFlags.Instance,
Type.FilterNameIgnoreCase, memberName );
if( members.Length != 0 )
return members[ 0 ];
return null;
}
internal static string[] FindPrimaryKeys( this IQueryable queryable )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
Type elementType = queryable.ElementType;
List<string> primaryKeyNames = new List<string>();
try
{
PropertyInfo[] properties = elementType.GetProperties();
for( int i = 0; i < properties.Length; i++ )
{
PropertyInfo propertyInfo = properties[ i ];
object[] attributes = propertyInfo.GetCustomAttributes( true );
for( int j = 0; j < attributes.Length; j++ )
{
Attribute attribute = attributes[ j ] as Attribute;
if( attribute == null )
continue;
Type attributeType = attribute.GetType();
if( attributeType.FullName == "System.Data.Linq.Mapping.ColumnAttribute" )
{
// LINQ to SQL support.
PropertyInfo isPrimaryKeyPropertyInfo = attributeType.GetProperty( "IsPrimaryKey" );
if( isPrimaryKeyPropertyInfo != null )
{
bool isPrimaryKey = ( bool )isPrimaryKeyPropertyInfo.GetValue( attribute, null );
if( isPrimaryKey )
primaryKeyNames.Add( propertyInfo.Name );
}
}
else if( attributeType.FullName == "System.Data.Objects.DataClasses.EdmScalarPropertyAttribute" )
{
// LINQ to Entity support.
PropertyInfo entityKeyPropertyInfo = attributeType.GetProperty( "EntityKeyProperty" );
if( entityKeyPropertyInfo != null )
{
bool isPrimaryKey = ( bool )entityKeyPropertyInfo.GetValue( attribute, null );
if( isPrimaryKey )
primaryKeyNames.Add( propertyInfo.Name );
}
}
}
}
}
catch
{
}
return primaryKeyNames.ToArray();
}
#endregion REFLECTION METHODS
#region ORDERING
internal static IQueryable OrderBy(
this IQueryable queryable,
SortDescriptionCollection implicitSortDescriptions,
SortDescriptionCollection explicitSortDescriptions,
bool reverse )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
if( ( implicitSortDescriptions == null ) && ( explicitSortDescriptions == null ) )
return queryable;
Expression orderedExpression = queryable.Expression;
Type queryableElementType = queryable.ElementType;
ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter( queryableElementType, "" ) };
string ascendingOrderByMethodName = "OrderBy";
string descendingOrderByMethodName = "OrderByDescending";
if( explicitSortDescriptions != null )
{
foreach( SortDescription sortDescription in explicitSortDescriptions )
{
MemberExpression sortMemberExpression = QueryableExtensions.GenerateMemberExpression( parameters[ 0 ], sortDescription.PropertyName );
string methodNameToUse;
if( ( sortDescription.Direction == ListSortDirection.Ascending && !reverse ) || ( sortDescription.Direction == ListSortDirection.Descending && reverse ) )
{
methodNameToUse = ascendingOrderByMethodName;
}
else
{
methodNameToUse = descendingOrderByMethodName;
}
orderedExpression = Expression.Call( typeof( Queryable ),
methodNameToUse,
new Type[] { queryableElementType, sortMemberExpression.Type },
orderedExpression, Expression.Quote( Expression.Lambda( sortMemberExpression, parameters ) ) );
ascendingOrderByMethodName = "ThenBy";
descendingOrderByMethodName = "ThenByDescending";
}
}
if( implicitSortDescriptions != null )
{
foreach( SortDescription sortDescription in implicitSortDescriptions )
{
MemberExpression sortMemberExpression = QueryableExtensions.GenerateMemberExpression( parameters[ 0 ], sortDescription.PropertyName );
string methodNameToUse;
if( ( sortDescription.Direction == ListSortDirection.Ascending && !reverse ) || ( sortDescription.Direction == ListSortDirection.Descending && reverse ) )
{
methodNameToUse = ascendingOrderByMethodName;
}
else
{
methodNameToUse = descendingOrderByMethodName;
}
orderedExpression = Expression.Call( typeof( Queryable ),
methodNameToUse,
new Type[] { queryableElementType, sortMemberExpression.Type },
orderedExpression, Expression.Quote( Expression.Lambda( sortMemberExpression, parameters ) ) );
ascendingOrderByMethodName = "ThenBy";
descendingOrderByMethodName = "ThenByDescending";
}
}
return queryable.Provider.CreateQuery( orderedExpression );
}
#endregion ORDERING
#region FILTERING
internal static Expression CreateStartsWithExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params string[] values )
{
return QueryableExtensions.FilterString( queryable, sharedParameterExpression, propertyName, values, StringFilterMode.StartsWith );
}
internal static Expression CreateEndsWithExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params string[] values )
{
return QueryableExtensions.FilterString( queryable, sharedParameterExpression, propertyName, values, StringFilterMode.EndsWith );
}
internal static Expression CreateContainsExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params string[] values )
{
return QueryableExtensions.FilterString( queryable, sharedParameterExpression, propertyName, values, StringFilterMode.Contains );
}
internal static Expression CreateGreaterThanExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params object[] values )
{
return QueryableExtensions.CreateBinaryComparison(
queryable,
sharedParameterExpression,
propertyName,
values,
BinaryExpression.GreaterThan );
}
internal static Expression CreateGreaterThanOrEqualExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params object[] values )
{
return QueryableExtensions.CreateBinaryComparison(
queryable,
sharedParameterExpression,
propertyName,
values,
BinaryExpression.GreaterThanOrEqual );
}
internal static Expression CreateLesserThanExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params object[] values )
{
return QueryableExtensions.CreateBinaryComparison(
queryable,
sharedParameterExpression,
propertyName,
values,
BinaryExpression.LessThan );
}
internal static Expression CreateLesserThanOrEqualExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params object[] values )
{
return QueryableExtensions.CreateBinaryComparison(
queryable,
sharedParameterExpression,
propertyName,
values,
BinaryExpression.LessThanOrEqual );
}
internal static Expression CreateEqualExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params object[] values )
{
return QueryableExtensions.CreateBinaryComparison(
queryable,
sharedParameterExpression,
propertyName,
values,
BinaryExpression.Equal );
}
internal static Expression CreateDifferentThanExpression(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
params object[] values )
{
return QueryableExtensions.CreateBinaryComparison(
queryable,
sharedParameterExpression,
propertyName,
values,
BinaryExpression.NotEqual );
}
internal static ParameterExpression CreateParameterExpression( this IQueryable queryable )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
return Expression.Parameter( queryable.ElementType, "" );
}
private static Expression CreateBinaryComparison(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
object[] values,
BinaryComparisonDelegate binaryComparisonDelegate )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
if( ( values == null ) || ( values.Length == 0 ) )
throw new ArgumentNullException( "values" );
if( binaryComparisonDelegate == null )
throw new ArgumentNullException( "binaryComparisonDelegate" );
MemberExpression memberExpression = QueryableExtensions.GenerateMemberExpression( sharedParameterExpression, propertyName );
Expression mergedFilterExpression = null;
for( int i = 0; i < values.Length; i++ )
{
ConstantExpression valueExpression = Expression.Constant( values[ i ] );
Expression newFilterExpression = binaryComparisonDelegate( memberExpression,
Expression.Convert( valueExpression, memberExpression.Type ) );
if( mergedFilterExpression == null )
{
mergedFilterExpression = newFilterExpression;
}
else
{
mergedFilterExpression = Expression.Or( mergedFilterExpression, newFilterExpression );
}
}
return mergedFilterExpression;
}
internal static IQueryable WhereFilter( this IQueryable queryable, ParameterExpression sharedParameterExpression, Expression expression )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
Type queryableElementType = queryable.ElementType;
LambdaExpression whereLambda = Expression.Lambda( expression, sharedParameterExpression );
MethodCallExpression whereCall =
Expression.Call(
typeof( Queryable ), "Where",
new Type[] { queryableElementType },
queryable.Expression,
Expression.Quote( whereLambda ) );
return queryable.Provider.CreateQuery( whereCall );
}
#endregion FILTERING
#region SELECTING
internal static IQueryable Select( this IQueryable queryable, string propertyName )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
if( string.IsNullOrEmpty( propertyName ) )
{
if( propertyName == null )
throw new ArgumentNullException( "propertyName" );
throw new ArgumentException( "A property name must be provided.", "propertyName" );
}
Type queryableElementType = queryable.ElementType;
ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter( queryableElementType, "" ) };
MemberExpression selectMemberExpression = QueryableExtensions.GenerateMemberExpression( parameters[ 0 ], propertyName );
LambdaExpression selectLambdaExpression = Expression.Lambda( selectMemberExpression, parameters );
return queryable.Provider.CreateQuery(
Expression.Call( typeof( Queryable ), "Select",
new Type[] { queryableElementType, selectLambdaExpression.Body.Type },
queryable.Expression, Expression.Quote( selectLambdaExpression ) ) );
}
internal static IQueryable GetSubGroupsAndCountsQueryable( this IQueryable queryable, string subGroupBy, bool sortGroupBy, ListSortDirection direction )
{
// Create GroupBy
Type queryableElementType = queryable.ElementType;
ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter( queryableElementType, "" ) };
MemberExpression memberExpression = QueryableExtensions.GenerateMemberExpression( parameters[ 0 ], subGroupBy );
LambdaExpression groupByLambdaExpression = Expression.Lambda( memberExpression, parameters );
MethodCallExpression groupByMethodExpression =
Expression.Call(
typeof( Queryable ), "GroupBy",
new Type[] { queryableElementType, groupByLambdaExpression.Body.Type },
new Expression[] { queryable.Expression, Expression.Quote( groupByLambdaExpression ) } );
IQueryable groupedResult = queryable.Provider.CreateQuery( groupByMethodExpression );
if( sortGroupBy )
groupedResult = groupedResult.OrderByKey( direction == ListSortDirection.Ascending );
ParameterExpression[] groupedParameters = new ParameterExpression[] { System.Linq.Expressions.Expression.Parameter( groupedResult.ElementType, "" ) };
MemberExpression keyMemberExpression = MemberExpression.Property( groupedParameters[ 0 ], "Key" );
MethodCallExpression countCallExpression = MethodCallExpression.Call( typeof( Enumerable ), "Count", new Type[] { queryableElementType }, groupedParameters );
QueryableGroupNameCountPairInfo queryableGroupNameCountPairInfo =
QueryableExtensions.QueryableGroupNameCountPairInfos.GetInfosForType( memberExpression.Type );
Expression[] newExpressionArguments = new Expression[ 2 ] { keyMemberExpression, countCallExpression };
NewExpression newExpression =
NewExpression.New(
queryableGroupNameCountPairInfo.ConstructorInfo,
newExpressionArguments,
new MemberInfo[] { queryableGroupNameCountPairInfo.KeyPropertyInfo, queryableGroupNameCountPairInfo.CountPropertyInfo } );
LambdaExpression finalLambdaExpression = System.Linq.Expressions.Expression.Lambda( newExpression, groupedParameters );
MethodCallExpression finalSelectExpression =
System.Linq.Expressions.Expression.Call(
typeof( Queryable ), "Select",
new Type[] { groupedResult.ElementType, finalLambdaExpression.Body.Type },
new System.Linq.Expressions.Expression[] { groupedResult.Expression, System.Linq.Expressions.Expression.Quote( finalLambdaExpression ) } );
return groupedResult.Provider.CreateQuery( finalSelectExpression );
}
internal static IQueryable Slice( this IQueryable queryable, int skip, int take )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
Expression skipAndTakeExpression = queryable.Expression;
Type queryableElementType = queryable.ElementType;
skipAndTakeExpression = QueryableExtensions.Skip( queryableElementType, skipAndTakeExpression, skip );
skipAndTakeExpression = QueryableExtensions.Take( queryableElementType, skipAndTakeExpression, take );
return queryable.Provider.CreateQuery( skipAndTakeExpression );
}
internal static int Count( this IQueryable queryable )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
Type queryableElementType = queryable.ElementType;
Expression expressionToCount = queryable.Expression;
MethodCallExpression countExpression = Expression.Call(
typeof( Queryable ), "Count",
new Type[] { queryableElementType }, expressionToCount );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Beginning Provider Execute for total count." );
int count = ( int )queryable.Provider.Execute( countExpression );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Ended Provider Execute for total count." );
return count;
}
#endregion SELECTING
#region PRIVATE METHODS
private static IQueryable OrderByKey( this IQueryable queryable, bool ascending )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
Expression orderedExpression = queryable.Expression;
Type queryableElementType = queryable.ElementType;
ParameterExpression parameter = queryable.CreateParameterExpression();
MemberExpression sortMemberExpression = QueryableExtensions.GenerateMemberExpression( parameter, "Key" );
string methodName = ( ascending ) ? "OrderBy" : "OrderByDescending";
orderedExpression = Expression.Call( typeof( Queryable ),
methodName,
new Type[] { queryableElementType, sortMemberExpression.Type },
orderedExpression, Expression.Quote( Expression.Lambda( sortMemberExpression, parameter ) ) );
return queryable.Provider.CreateQuery( orderedExpression );
}
internal static MemberExpression GenerateMemberExpression( ParameterExpression typeExpression, string name )
{
if( string.IsNullOrEmpty( name ) )
{
if( name == null )
throw new ArgumentNullException( "name" );
throw new ArgumentException( "A name must be provided.", "name" );
}
MemberExpression memberExpression = null;
MemberInfo member = QueryableExtensions.GetMemberInfo( typeExpression.Type, name );
if( member == null )
throw new DataGridInternalException( "MemberInfo is null." );
if( member is PropertyInfo )
{
// Member is a property.
memberExpression = Expression.Property( typeExpression, ( PropertyInfo )member );
}
else
{
// Member is a field.
memberExpression = Expression.Field( typeExpression, ( FieldInfo )member );
}
return memberExpression;
}
private static MethodCallExpression Take( Type queryableElementType, Expression expression, int count )
{
if( queryableElementType == null )
throw new ArgumentNullException( "queryableElementType" );
if( expression == null )
throw new ArgumentNullException( "expression" );
return Expression.Call( typeof( Queryable ), "Take", new Type[] { queryableElementType }, expression, Expression.Constant( count ) );
}
private static MethodCallExpression Skip( Type queryableElementType, Expression expression, int count )
{
if( queryableElementType == null )
throw new ArgumentNullException( "queryableElementType" );
if( expression == null )
throw new ArgumentNullException( "expression" );
return Expression.Call( typeof( Queryable ), "Skip", new Type[] { queryableElementType }, expression, Expression.Constant( count ) );
}
private static string GetMethodNameFromStringFilterMode( StringFilterMode stringFilterMode )
{
switch( stringFilterMode )
{
case StringFilterMode.StartsWith:
{
return "StartsWith";
}
case StringFilterMode.Contains:
{
return "Contains";
}
case StringFilterMode.EndsWith:
{
return "EndsWith";
}
}
Debug.Fail( "Should have handled the new StringFilterMode." );
return string.Empty;
}
private static Expression FilterString(
this IQueryable queryable,
ParameterExpression sharedParameterExpression,
string propertyName,
string[] values,
StringFilterMode stringFilterMode )
{
if( queryable == null )
throw new ArgumentNullException( "queryable" );
if( ( values == null ) || ( values.Length == 0 ) )
throw new ArgumentNullException( "values" );
string methodName = QueryableExtensions.GetMethodNameFromStringFilterMode( stringFilterMode );
Debug.Assert( !String.IsNullOrEmpty( methodName ) );
MemberExpression memberExpression = QueryableExtensions.GenerateMemberExpression( sharedParameterExpression, propertyName );
Expression mergedFilterCall = null;
for( int i = 0; i < values.Length; i++ )
{
ConstantExpression valueExpression = Expression.Constant( values[ i ] );
MethodCallExpression newFilterCall = Expression.Call(
memberExpression,
typeof( string ).GetMethod( methodName, new Type[] { typeof( string ) } ),
Expression.Convert( valueExpression, memberExpression.Type ) );
if( mergedFilterCall == null )
{
mergedFilterCall = newFilterCall;
}
else
{
mergedFilterCall = MethodCallExpression.Or( mergedFilterCall, newFilterCall );
}
}
return mergedFilterCall;
}
#endregion PRIVATE METHODS
#region PRIVATE FIELDS
private delegate Expression BinaryComparisonDelegate( Expression left, Expression right );
#endregion PRIVATE FIELDS
#region INTERNAL NESTED CLASSES
internal interface IQueryableGroupNameCountPair
{
object GroupName
{
get;
}
Type GroupNameType
{
get;
}
int Count
{
get;
}
}
#endregion INTERNAL NESTED CLASSES
#region PRIVATE NESTED CLASSES
private class QueryableGroupNameCountPair<T> : IQueryableGroupNameCountPair
{
public QueryableGroupNameCountPair( T groupName, int count )
{
this.GroupName = groupName;
this.Count = count;
}
public T GroupName
{
get;
set;
}
public int Count
{
get;
set;
}
#region QueryableGroupNameCountPair Members
object IQueryableGroupNameCountPair.GroupName
{
get
{
return this.GroupName;
}
}
public Type GroupNameType
{
get
{
return typeof( T );
}
}
int IQueryableGroupNameCountPair.Count
{
get
{
return this.Count;
}
}
#endregion
}
private static class QueryableGroupNameCountPairInfos
{
public static QueryableGroupNameCountPairInfo GetInfosForType( Type sourceType )
{
if( QueryableGroupNameCountPairInfos.ReflectionInfoDictionary == null )
QueryableGroupNameCountPairInfos.ReflectionInfoDictionary = new Dictionary<Type, QueryableGroupNameCountPairInfo>();
QueryableGroupNameCountPairInfo queryableGroupNameCountPairInfo;
if( !QueryableGroupNameCountPairInfos.ReflectionInfoDictionary.TryGetValue( sourceType, out queryableGroupNameCountPairInfo ) )
{
Type queryableGroupNameCountPairType = typeof( QueryableGroupNameCountPair<> ).MakeGenericType( sourceType );
ConstructorInfo constructorInfo =
queryableGroupNameCountPairType.GetConstructor( new Type[] { sourceType, typeof( int ) } );
PropertyInfo keyPropertyInfo = queryableGroupNameCountPairType.GetProperty( "GroupName" );
PropertyInfo countPropertyInfo = queryableGroupNameCountPairType.GetProperty( "Count" );
queryableGroupNameCountPairInfo = new QueryableGroupNameCountPairInfo()
{
Type = queryableGroupNameCountPairType,
ConstructorInfo = constructorInfo,
KeyPropertyInfo = keyPropertyInfo,
CountPropertyInfo = countPropertyInfo
};
QueryableGroupNameCountPairInfos.ReflectionInfoDictionary.Add( sourceType, queryableGroupNameCountPairInfo );
}
return queryableGroupNameCountPairInfo;
}
private static Dictionary<Type, QueryableGroupNameCountPairInfo> ReflectionInfoDictionary;
}
private struct QueryableGroupNameCountPairInfo
{
public Type Type
{
get;
set;
}
public ConstructorInfo ConstructorInfo
{
get;
set;
}
public PropertyInfo KeyPropertyInfo
{
get;
set;
}
public PropertyInfo CountPropertyInfo
{
get;
set;
}
}
#endregion PRIVATE NESTED CLASSES
#region PRIVATE NESTED ENUMS
private enum StringFilterMode
{
StartsWith = 0,
Contains = 1,
EndsWith = 2
}
#endregion PRIVATE NESTED ENUMS
}
}

104
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/RawItem.cs

@ -1,104 +0,0 @@
/*************************************************************************************
Extended WPF Toolkit
Copyright (C) 2007-2013 Xceed Software Inc.
This program is provided to you under the terms of the Microsoft Public
License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license
For more features, controls, and fast professional support,
pick up the Plus Edition at http://xceed.com/wpf_toolkit
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
// We use an intermediate liste to always acces the source with the index
// and never directly by keeping a variable that contains the source item directly.
// ( We do that to be able to work correctly with a DataView has source )
//
// RawItem is always pointing at the same item.
// The dataIndex may be changing to always represent the same item if the item is moving in the source.
internal class RawItem
{
public RawItem( int dataIndex, object dataItem )
{
m_dataIndex = dataIndex;
m_dataItem = dataItem;
m_sortedIndex = -1;
}
public int Index
{
get
{
return m_dataIndex;
}
}
public int SortedIndex
{
get
{
return m_sortedIndex;
}
}
public object DataItem
{
get
{
return m_dataItem;
}
}
public DataGridCollectionViewGroup ParentGroup
{
get
{
return m_parentGroup;
}
}
public int GetGlobalSortedIndex()
{
if( m_parentGroup == null )
return -1;
return m_sortedIndex + m_parentGroup.GetFirstRawItemGlobalSortedIndex();
}
internal void SetIndex( int newIndex )
{
m_dataIndex = newIndex;
}
internal void SetParentGroup( DataGridCollectionViewGroup parentGroup )
{
m_parentGroup = parentGroup;
}
internal void SetSortedIndex( int newIndex )
{
m_sortedIndex = newIndex;
}
internal void SetDataItem( object dataItem )
{
m_dataItem = dataItem;
}
private object m_dataItem;
private int m_dataIndex;
private int m_sortedIndex;
private DataGridCollectionViewGroup m_parentGroup;
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save