Browse Source

pull/1242/head
BoucherS_cp 11 years ago
parent
commit
af8b733790
  1. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/AssemblyVersionInfo.cs
  2. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/AssemblyVersionInfo.cs
  3. 44
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Theme.xaml
  4. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/AssemblyVersionInfo.cs
  5. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/AssemblyVersionInfo.cs
  6. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FocusElementManager.cs
  7. 11
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutFloatingWindowControl.cs
  8. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DockingManager.cs
  9. 6
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/generic.xaml
  10. 14
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualList.cs
  11. 5
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListEnumerator.cs
  12. 33
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPage.cs
  13. 51
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(ForeignKeys)/DataGridForeignKeyDescription.cs
  14. 40
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(ForeignKeys)/DataTableForeignKeyDescription.cs
  15. 125
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/CollectionViewGroupExtensions.cs
  16. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ConnectionErrorChangedEventManager.cs
  17. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ConnectionStateChangedEventManager.cs
  18. 858
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionView.cs
  19. 796
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewBase.cs
  20. 11
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewEnumerator.cs
  21. 649
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroup.cs
  22. 54
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroupRoot.cs
  23. 16
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewGroupSort.cs
  24. 17
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSource.cs
  25. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridCollectionViewSourceBase.cs
  26. 4
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridDetailDescription.cs
  27. 4
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemProperty.cs
  28. 336
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyBase.cs
  29. 30
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridItemPropertyCollection.cs
  30. 76
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridLINQPageManager.cs
  31. 1
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridSortDescriptionCollection.cs
  32. 20
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridUnboundItemProperty.cs
  33. 22
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DataGridVirtualizingCollectionViewBase.cs
  34. 59
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DeferredOperation.cs
  35. 272
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DeferredOperationManager.cs
  36. 10
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DistinctValuesDictionary.cs
  37. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/DistinctValuesRefreshNeededEventManager.cs
  38. 9
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/GroupSortComparer.cs
  39. 92
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ItemPropertyGroupSortStatNameChangedEventManager.cs
  40. 78
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PostBatchCollectionChangedEventManager.cs
  41. 78
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PreBatchCollectionChangedEventManager.cs
  42. 97
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/PropertyDetailDescription.cs
  43. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyApplyingFilterCriteriasEventManager.cs
  44. 93
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyAutoFilterValuesChangedEventManager.cs
  45. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyCollectionRefreshEventManager.cs
  46. 93
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxyGroupDescriptionsChangedEventManager.cs
  47. 93
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/ProxySortDescriptionsChangedEventManager.cs
  48. 83
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/QueryableExtensions.cs
  49. 145
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/RawItemMap.cs
  50. 87
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/RootGroupChangedEventManager.cs
  51. 407
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(ForeignKeys)/ForeignKeyConfiguration.cs
  52. 24
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(ForeignKeys)/ForeignKeyContentControl.cs
  53. 4969
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/CustomItemContainerGenerator.cs
  54. 109
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/DataItemDataProvider.cs
  55. 35
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/DataItemDataProviderBase.cs
  56. 70
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/EmptyDataItemDataProvider.cs
  57. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GeneratorNode.cs
  58. 171
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GeneratorNodeFactory.cs
  59. 27
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GeneratorNodeHelper.cs
  60. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GroupGeneratorNode.cs
  61. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/NotifyCollectionChangedGeneratorNode.cs
  62. 41
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/RangeSelectionVisitor.cs
  63. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/SelectAllVisitor.cs
  64. 72
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/VisibilityChangingEventManager.cs
  65. 39
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(enums)/AutoScrollCurrentItemSourceTriggersEnum.cs
  66. 37
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(enums)/AutoScrollCurrentItemTriggersEnum.cs
  67. 3
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(enums)/DistinctValuesConstraintEnum.cs
  68. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AssemblyVersionInfo.cs
  69. 34
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AutoResetFlag.cs
  70. 156
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AutoResetFlagFactory.cs
  71. 105
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AutoScrollCurrentItemSourceTriggersRestrictions.cs
  72. 6
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Automation/ColumnManagerCellAutomationPeer.cs
  73. 78
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Automation/DataGridGroupAutomationPeer.cs
  74. 20
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Automation/HeaderFooterItemAutomationPeer.cs
  75. 975
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Cell.cs
  76. 74
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/CellContentStringFormatChangedEventManager.cs
  77. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/CheckBox.cs
  78. 75
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ChildColumnVisibilityChangedEventManager.cs
  79. 9
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Column.GenericContentTemplateSelectorResources.xaml
  80. 132
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Column.cs
  81. 116
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnAddGroupCommand.cs
  82. 1127
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnBase.cs
  83. 269
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnCollection.cs
  84. 62
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnCommand.cs
  85. 26
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnGroupCommand.cs
  86. 580
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnManagerCell.cs
  87. 19
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnManagerRow.cs
  88. 5
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnReorderingEvent.cs
  89. 261
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnSortCommand.cs
  90. 1097
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnSynchronizationManager.cs
  91. 59
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/FilterCriterionToNullableBoolConverter.cs
  92. 112
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/StatResultConverter.cs
  93. 2
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/StringFormatConverter.cs
  94. 50
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/StringFormatMultiConverter.cs
  95. 28
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/CurrencyManager.cs
  96. 108
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataCell.cs
  97. 19
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridBindingInfo.cs
  98. 1388
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridContext.cs
  99. 1082
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridControl.cs
  100. 58
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridException.cs

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Aero/AssemblyVersionInfo.cs

@ -21,7 +21,7 @@
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "2.3";
public const string BaseVersion = "2.4";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
".0.0";

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/AssemblyVersionInfo.cs

@ -21,7 +21,7 @@
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "2.3";
public const string BaseVersion = "2.4";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
".0.0";

44
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.Metro/Theme.xaml

@ -54,19 +54,6 @@
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor31}"/>
<Setter Property="Background"
Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor10}" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor31}"/>
<Setter Property="Background"
Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor10}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="AvalonDock_ThemeMetro_ButtonStyle" TargetType="Button">
@ -85,19 +72,10 @@
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor31}"/>
<Setter Property="Background"
Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor10}" />
</Trigger>
</Style.Triggers>
</Style>
<!--DocumentPaneControlStyle-->
<Style x:Key="AvalonDock_ThemeMetro_DocumentPaneControlStyle" TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}">
<Setter Property="Background" Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor33}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
@ -171,22 +149,6 @@
</Setter.Value>
</Setter>
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Model.SelectedContent.IsActive}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Model.SelectedContent.IsLastFocusedDocument}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background"
Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor31}" />
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Model.SelectedContent.IsActive}" Value="False"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=Model.SelectedContent.IsLastFocusedDocument}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background"
Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor30}" />
</MultiDataTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
@ -377,8 +339,6 @@
<Setter Property="Panel.ZIndex" Value="0" />
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="BorderBrush" Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor13}"/>
<Setter Property="Background" Value="{DynamicResource AvalonDock_ThemeMetro_BaseColor9}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
@ -969,8 +929,7 @@
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="Header"
Background="{DynamicResource AvalonDock_ThemeMetro_BaseColor16}">
<Border x:Name="Header">
<avalonDockControls:AnchorablePaneTitle
Model="{Binding Model, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border>
@ -1437,7 +1396,6 @@
</Grid>
<Border Grid.Row="1"
BorderBrush="{DynamicResource AvalonDock_ThemeMetro_BaseColor11}"
BorderThickness="0,1,0,0"
Background="{DynamicResource AvalonDock_ThemeMetro_BaseColor7}"
MinHeight="200" >

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock.Themes.VS2010/AssemblyVersionInfo.cs

@ -21,7 +21,7 @@
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "2.3";
public const string BaseVersion = "2.4";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
".0.0";

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/AssemblyVersionInfo.cs

@ -21,7 +21,7 @@
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "2.3";
public const string BaseVersion = "2.4";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
".0.0";

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/FocusElementManager.cs

@ -227,7 +227,7 @@ namespace Xceed.Wpf.AvalonDock.Controls
{
_setFocusAsyncOperation = null;
}
}), DispatcherPriority.Background);
}), DispatcherPriority.Input);
}
}
}

11
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Controls/LayoutFloatingWindowControl.cs

@ -237,7 +237,6 @@ namespace Xceed.Wpf.AvalonDock.Controls
this.SetParentToMainWindowOf(Model.Root.Manager);
_hwndSrc = HwndSource.FromDependencyObject(this) as HwndSource;
_hwndSrcHook = new HwndSourceHook(FilterMessage);
_hwndSrc.AddHook(_hwndSrcHook);
@ -338,12 +337,18 @@ namespace Xceed.Wpf.AvalonDock.Controls
/// </summary>
protected virtual void OnIsDraggingChanged(DependencyPropertyChangedEventArgs e)
{
if( ( bool )e.NewValue )
{
CaptureMouse();
}
else
{
ReleaseMouseCapture();
}
}
#endregion
DragService _dragService = null;
void UpdatePositionAndSizeOfPanes()

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/DockingManager.cs

@ -188,7 +188,7 @@ namespace Xceed.Wpf.AvalonDock
if (Layout.ActiveContent != null)
FocusElementManager.SetFocusOnLastElement(Layout.ActiveContent);
_setFocusAsyncOperation = null;
}), DispatcherPriority.Background);
} ), DispatcherPriority.Input );
}
}

6
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.AvalonDock/Themes/generic.xaml

@ -171,7 +171,11 @@
<!--AnchorablePaneControlStyle-->
<Style x:Key="AnchorablePaneControlStyle" TargetType="{x:Type avalonDockControls:LayoutAnchorablePaneControl}">
<Setter Property="TabStripPlacement" Value="Bottom"/>
<Setter Property="Foreground"
Value="{Binding Model.Root.Manager.Foreground, RelativeSource={RelativeSource Self}}" />
<Setter Property="Background"
Value="{Binding Model.Root.Manager.Background, RelativeSource={RelativeSource Self}}" />
<Setter Property="TabStripPlacement" Value="Bottom"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type avalonDockControls:LayoutAnchorablePaneControl}">

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

@ -15,16 +15,12 @@
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Windows.Threading;
using System.Windows;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Text;
namespace Xceed.Wpf.DataGrid
{
@ -492,7 +488,7 @@ namespace Xceed.Wpf.DataGrid
internal void NotifyCommitComplete( AsyncCommitInfo asyncCommitInfo )
{
if( asyncCommitInfo.VirtualizedItemInfos.Length < 1 )
throw new DataGridInternalException();
throw new DataGridInternalException( "VirualizedItemInfos is empty." );
int indexForItemInPage = asyncCommitInfo.VirtualizedItemInfos[ 0 ].Index;

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

@ -15,10 +15,9 @@
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Xceed.Wpf.DataGrid
{
@ -95,7 +94,7 @@ namespace Xceed.Wpf.DataGrid
public bool MoveNext()
{
if( m_version != m_virtualList.PagingManager.Version )
throw new InvalidOperationException( "TODO: Collection was modified." );
throw new InvalidOperationException( "Collection was modified." );
if( m_beforeStart )
m_beforeStart = false;

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

@ -308,12 +308,22 @@ namespace Xceed.Wpf.DataGrid
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 );
}
@ -322,6 +332,8 @@ namespace Xceed.Wpf.DataGrid
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnAbortQueryItems( this, queryInfo );
this.IsAborting = false;
@ -337,6 +349,7 @@ namespace Xceed.Wpf.DataGrid
if( this.IsDisposed )
return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
Debug.Assert( !this.IsAborting );
this.ParentVirtualList.PagingManager.OnQueryItemsCompleted( this, queryInfo, fetchedItems );
@ -346,6 +359,11 @@ namespace Xceed.Wpf.DataGrid
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 )
@ -354,11 +372,21 @@ namespace Xceed.Wpf.DataGrid
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 );
if( this.ParentVirtualList.IsRestarting )
@ -367,6 +395,11 @@ namespace Xceed.Wpf.DataGrid
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 )

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

@ -14,28 +14,17 @@
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Data;
using System.Diagnostics;
using System.Windows;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public class DataGridForeignKeyDescription : DependencyObject
{
#region Constructors
public DataGridForeignKeyDescription()
{
}
#endregion
#region ForeignKeyConverter Property
public static readonly DependencyProperty ForeignKeyConverterProperty = DependencyProperty.Register(
@ -64,15 +53,13 @@ namespace Xceed.Wpf.DataGrid
"ItemsSource",
typeof( IEnumerable ),
typeof( DataGridForeignKeyDescription ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( DataGridForeignKeyDescription.OnItemsSourceChanged ) ) );
new FrameworkPropertyMetadata( null ) );
public IEnumerable ItemsSource
{
get
{
return m_itemsSource;
return ( IEnumerable )this.GetValue( DataGridForeignKeyDescription.ItemsSourceProperty );
}
set
{
@ -80,18 +67,6 @@ namespace Xceed.Wpf.DataGrid
}
}
private IEnumerable m_itemsSource; // = null;
private static void OnItemsSourceChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
DataGridForeignKeyDescription foreignKeyDescription = sender as DataGridForeignKeyDescription;
if( foreignKeyDescription != null )
{
foreignKeyDescription.m_itemsSource = e.NewValue as IEnumerable;
}
}
#endregion
#region IsAutoCreated Internal Property
@ -125,5 +100,27 @@ namespace Xceed.Wpf.DataGrid
}
#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
}
}

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

@ -14,14 +14,8 @@
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Collections;
using System.Windows;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
@ -56,7 +50,7 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_foreignKeyConstraint;
return ( ForeignKeyConstraint )this.GetValue( DataTableForeignKeyDescription.ForeignKeyConstraintProperty );
}
set
{
@ -66,18 +60,14 @@ namespace Xceed.Wpf.DataGrid
private static void OnForeignKeyConstraintChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
DataTableForeignKeyDescription foreignKeyDescription = sender as DataTableForeignKeyDescription;
var foreignKeyDescription = sender as DataTableForeignKeyDescription;
if( foreignKeyDescription != null )
{
foreignKeyDescription.m_foreignKeyConstraint = e.NewValue as ForeignKeyConstraint;
foreignKeyDescription.UpdateValuePath();
foreignKeyDescription.UpdateItemsSource();
}
}
private ForeignKeyConstraint m_foreignKeyConstraint;
#endregion
#region PRIVATE METHODS
@ -85,19 +75,21 @@ namespace Xceed.Wpf.DataGrid
private void UpdateValuePath()
{
// Affect the ValuePath if it was not explicitly set or bound
object valuePath = this.ReadLocalValue( ValuePathProperty );
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( ( m_foreignKeyConstraint != null )
&& ( m_foreignKeyConstraint.RelatedColumns != null )
&& ( m_foreignKeyConstraint.RelatedColumns.Length == 1 ) )
if( ( foreignKeyConstraint != null )
&& ( foreignKeyConstraint.RelatedColumns != null )
&& ( foreignKeyConstraint.RelatedColumns.Length == 1 ) )
{
string foreignFieldName = m_foreignKeyConstraint.RelatedColumns[ 0 ].ColumnName;
var foreignFieldName = foreignKeyConstraint.RelatedColumns[ 0 ].ColumnName;
if( !string.IsNullOrEmpty( foreignFieldName ) )
{
@ -109,11 +101,15 @@ namespace Xceed.Wpf.DataGrid
private void UpdateItemsSource()
{
if( ( m_foreignKeyConstraint != null )
&& ( m_foreignKeyConstraint.RelatedTable != null ) )
{
this.ItemsSource = m_foreignKeyConstraint.RelatedTable.DefaultView;
}
var foreignKeyConstraint = this.ForeignKeyConstraint;
if( foreignKeyConstraint == null )
return;
var relatedTable = foreignKeyConstraint.RelatedTable;
if( relatedTable == null )
return;
this.ItemsSource = relatedTable.DefaultView;
}
#endregion

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

@ -27,33 +27,136 @@ namespace Xceed.Wpf.DataGrid
{
public static class CollectionViewGroupExtensions
{
public static IList<object> GetItems( this CollectionViewGroup collectionViewGroup )
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 )
{
return dataGridVirtualizingCollectionViewGroupBase.VirtualItems;
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" );
DataGridCollectionViewGroup dataGridCollectionViewGroup = collectionViewGroup as DataGridCollectionViewGroup;
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 )
{
// 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.
return dataGridCollectionViewGroup.Items;
}
return collectionViewGroup.Items;
}
public static int GetItemCount( this CollectionViewGroup collectionViewGroup )
{
if( collectionViewGroup is DataGridVirtualizingCollectionViewGroupBase )
return ( ( DataGridVirtualizingCollectionViewGroupBase )collectionViewGroup ).VirtualItemCount;
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;
}
}
}
}
}

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

@ -0,0 +1,87 @@
/*************************************************************************************
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

@ -0,0 +1,87 @@
/*************************************************************************************
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 );
}
}
}

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

File diff suppressed because it is too large

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

File diff suppressed because it is too large

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

@ -58,7 +58,7 @@ namespace Xceed.Wpf.DataGrid
{
m_beforeStart = false;
if( ( m_currentGroup != null ) && ( m_currentGroup.RawItems == null ) )
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();
@ -71,14 +71,14 @@ namespace Xceed.Wpf.DataGrid
}
else
{
if( ( m_currentGroup == null ) || ( m_currentGroup.RawItems == null ) )
if( ( m_currentGroup == null ) || ( m_currentGroup.RawItems.Count == 0 ) )
{
m_afterEnd = true;
}
else
{
//check indexes
if( m_currentItemIndex < m_currentGroup.RawItems.Count )
if( m_currentItemIndex < m_currentGroup.RawItems.Count )
{
m_current = m_currentGroup.RawItems[ m_currentItemIndex ];
m_currentItemIndex++;
@ -114,7 +114,7 @@ namespace Xceed.Wpf.DataGrid
{
m_currentGroup = this.MoveToFirstLeafGroup( m_currentGroup, index );
foundNonEmptyLeafGroup = ( ( m_currentGroup.RawItems != null ) && ( m_currentGroup.RawItems.Count > 0 ) );
foundNonEmptyLeafGroup = ( m_currentGroup.RawItems.Count > 0 );
}
}
@ -144,8 +144,7 @@ namespace Xceed.Wpf.DataGrid
m_currentItemIndex = 0;
m_currentGroupIndex.Clear();
m_currentGroup = ( m_collectionView.Count == 0 ) ?
null : this.MoveToFirstLeafGroup( m_collectionView.RootGroup, 0 );
m_currentGroup = ( m_collectionView.Count == 0 ) ? null : this.MoveToFirstLeafGroup( m_collectionView.RootGroup, 0 );
}
#endregion

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

@ -18,36 +18,46 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Data;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Windows.Data;
using Xceed.Wpf.DataGrid.Stats;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewGroup : CollectionViewGroup, ICustomTypeDescriptor
{
public DataGridCollectionViewGroup( object name, DataGridCollectionViewGroup parent, int unsortedIndex )
: base( name )
protected DataGridCollectionViewGroup( int capacity )
: this( null, null, 0, capacity, 4 )
{
m_parent = parent;
m_unsortedIndex = unsortedIndex;
}
internal DataGridCollectionViewGroup(
DataGridCollectionViewGroup template,
DataGridCollectionViewGroup parent )
: this( template.Name, parent, template.m_unsortedIndex )
protected DataGridCollectionViewGroup( DataGridCollectionViewGroup template, DataGridCollectionViewGroup parent )
: this( template.Name, parent, template.m_unsortedIndex, template.m_sortedRawItems.Count, template.m_subGroups.Count )
{
m_nextSubGroupUnsortedIndex = template.m_nextSubGroupUnsortedIndex;
m_subGroupBy = template.m_subGroupBy;
}
if( template.m_groupsDictionary != null )
m_groupsDictionary = new Hashtable();
private DataGridCollectionViewGroup( object name, DataGridCollectionViewGroup parent, int unsortedIndex )
: this( name, parent, unsortedIndex, 4, 4 )
{
}
if( template.m_sortedRawItems != null )
m_sortedRawItems = new List<RawItem>( template.m_sortedRawItems.Count );
private DataGridCollectionViewGroup( object name, DataGridCollectionViewGroup parent, int unsortedIndex, int rawCapacity, int groupCapacity )
: base( name )
{
m_parent = parent;
m_unsortedIndex = unsortedIndex;
m_protectedItems = ObservableCollectionHelper.GetItems( base.ProtectedItems );
m_protectedItemsCollectionChanged = ObservableCollectionHelper.GetCollectionChanged( base.ProtectedItems );
m_optimizedItems = new OptimizedReadOnlyObservableCollection( this );
m_subGroups = new Dictionary<object, DataGridCollectionViewGroup>( groupCapacity );
m_sortedRawItems = new List<RawItem>( rawCapacity );
}
#region IsBottomLevel Property
@ -56,40 +66,24 @@ namespace Xceed.Wpf.DataGrid
{
get
{
// return true if .Items contain DataItem
// returns true if .Items contain DataItem
return ( m_subGroupBy == null );
}
}
#endregion IsBottomLevel Property
#endregion
#region Items Property
public new ReadOnlyObservableCollection<object> Items
internal new ReadOnlyObservableCollection<object> Items
{
get
{
// The optimized list is only able to handle Items. When we are not at the bottom level,
// this means that our Items collection return sub-groups.
if( this.IsBottomLevel )
{
if( m_optimizedItems == null )
m_optimizedItems = new OptimizedReadOnlyObservableCollection( this );
return m_optimizedItems;
}
// The group hierarchy can change over time. If, at this point,
// we are not eligible to return the optimized list (we contains
// sub groups or our source item list is not a DataGridCollectionView),
// we must reset our cached list.
m_optimizedItems = null;
return base.Items;
return m_optimizedItems;
}
}
#endregion Items Property
#endregion
#region ProtectedItems Property
@ -101,7 +95,7 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion ProtectedItems Property
#endregion
#region UnsortedIndex Property
@ -113,7 +107,7 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion UnsortedIndex Property
#endregion
#region SubGroupBy Property
@ -125,7 +119,7 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion SubGroupBy Property
#endregion
#region Parent Property
@ -137,7 +131,41 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion Parent Property
#endregion
#region CalculateAllStats Property
internal bool CalculateAllStats
{
get;
set;
}
#endregion
#region GlobalRawItemCount Property
internal int GlobalRawItemCount
{
get
{
return m_globalRawItemCount;
}
}
#endregion
#region RawItems Property
internal List<RawItem> RawItems
{
get
{
return m_sortedRawItems;
}
}
#endregion
protected virtual DataGridCollectionView GetCollectionView()
{
@ -147,34 +175,43 @@ namespace Xceed.Wpf.DataGrid
return null;
}
internal bool Contains( object dataItem )
internal bool Contains( object item )
{
var group = item as DataGridCollectionViewGroup;
if( group != null )
{
//Must make sure the group the group is ref equals, because there can be groups with a null name at more than one level.
DataGridCollectionViewGroup foundGroup;
if( m_subGroups.TryGetValue( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ), out foundGroup ) )
return ( foundGroup == group );
return false;
}
DataGridCollectionView collectionView = this.GetCollectionView();
if( collectionView != null )
{
RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( dataItem );
RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( item );
if( rawItem != null )
{
return ( rawItem.ParentGroup == this );
}
}
return false;
}
internal int IndexOf( object dataItem )
internal int IndexOf( object item )
{
if( item is DataGridCollectionViewGroup )
return this.ProtectedItems.IndexOf( item );
DataGridCollectionView collectionView = this.GetCollectionView();
if( collectionView != null )
{
RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( dataItem );
RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( item );
if( ( rawItem != null )
&& ( rawItem.ParentGroup == this ) )
{
if( ( rawItem != null ) && ( rawItem.ParentGroup == this ) )
return rawItem.SortedIndex;
}
}
return -1;
@ -184,24 +221,18 @@ namespace Xceed.Wpf.DataGrid
{
int index = 0;
DataGridCollectionViewGroup group = this;
DataGridCollectionViewGroup parent = group;
if( parent != null )
parent = parent.Parent;
DataGridCollectionViewGroup parent = this.Parent;
DataGridCollectionViewGroup currentGroup = null;
while( parent != null )
{
ReadOnlyObservableCollection<object> subGroups = parent.Items;
int subGroupCount = subGroups.Count;
DataGridCollectionViewGroup currentGroup = null;
for( int i = 0; i < subGroupCount; i++ )
foreach( object value in parent.ProtectedItems )
{
currentGroup = subGroups[ i ] as DataGridCollectionViewGroup;
if( currentGroup == group )
if( value == group )
break;
currentGroup = value as DataGridCollectionViewGroup;
index += currentGroup.GlobalRawItemCount;
}
@ -217,14 +248,10 @@ namespace Xceed.Wpf.DataGrid
bool oldIsBottomLevel = this.IsBottomLevel;
m_subGroupBy = groupBy;
if( m_subGroupBy != null )
{
if( m_groupsDictionary == null )
m_groupsDictionary = new Hashtable();
}
if( oldIsBottomLevel != this.IsBottomLevel )
{
this.OnPropertyChanged( new PropertyChangedEventArgs( "IsBottomLevel" ) );
}
}
internal DataGridCollectionViewGroup GetGroup(
@ -232,7 +259,7 @@ namespace Xceed.Wpf.DataGrid
int level,
CultureInfo culture,
ObservableCollection<GroupDescription> groupByList,
GroupSortComparer[] groupSortComparers )
List<GroupSortComparer> groupSortComparers )
{
// If sortComparers is null, we are in massive group creation, no order check.
@ -240,23 +267,19 @@ namespace Xceed.Wpf.DataGrid
throw new InvalidOperationException( "An attempt was made to get a group for which a GroupDescription has not been provided." );
object groupName = m_subGroupBy.GroupNameFromItem( rawItem.DataItem, level, culture );
DataGridGroupDescription dataGridGroupDescription = m_subGroupBy as DataGridGroupDescription;
DataGridCollectionViewGroup group;
if( dataGridGroupDescription != null )
if( ( m_subGroupBy is DataGridGroupDescription ) || ( m_subGroupBy is PropertyGroupDescription ) )
{
group = m_groupsDictionary[ DataGridCollectionViewGroup.GetHashKeyFromName( groupName ) ]
as DataGridCollectionViewGroup;
m_subGroups.TryGetValue( DataGridCollectionViewGroup.GetHashKeyFromName( groupName ), out group );
}
else
{
int itemCount = this.ItemCount;
//If dealing with an unknown GroupDescription type, use the standard method to retrieve a group, in case group retrival is handle differently.
group = null;
for( int i = 0; i < itemCount; i++ )
foreach( var tempGroup in m_subGroups.Values )
{
DataGridCollectionViewGroup tempGroup = this.ProtectedItems[ i ] as DataGridCollectionViewGroup;
if( m_subGroupBy.NamesMatch( tempGroup.Name, groupName ) )
{
group = tempGroup;
@ -267,8 +290,7 @@ namespace Xceed.Wpf.DataGrid
if( group == null )
{
group = this.CreateSubGroup(
groupName, level, groupByList, groupSortComparers );
group = this.CreateSubGroup( groupName, level, groupByList, groupSortComparers );
}
return group;
@ -276,32 +298,27 @@ namespace Xceed.Wpf.DataGrid
internal void SortItems(
SortDescriptionInfo[] sortDescriptionInfos,
GroupSortComparer[] groupSortComparers,
List<GroupSortComparer> groupSortComparers,
int level,
List<RawItem> globalRawItems,
DataGridCollectionViewGroup newSortedGroup )
{
int itemCount = this.ItemCount;
int itemCount = this.ProtectedItemCount;
if( itemCount == 0 )
return;
ObservableCollection<object> groupItems = this.ProtectedItems;
if( this.IsBottomLevel )
{
int[] indexes;
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]
DataGridCollectionViewSort collectionViewSort =
new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
DataGridCollectionViewSort collectionViewSort = new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
collectionViewSort.Sort( itemCount );
int index = 0;
@ -315,17 +332,17 @@ namespace Xceed.Wpf.DataGrid
else
{
int[] indexes;
indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ )
{
indexes[ i ] = i;
}
DataGridCollectionViewGroup[] subGroupsArray = new DataGridCollectionViewGroup[ itemCount ];
m_subGroups.Values.CopyTo( subGroupsArray, 0 );
// "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
DataGridCollectionViewGroupSort collectionViewSort =
new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], this );
DataGridCollectionViewGroupSort collectionViewSort = new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], subGroupsArray );
collectionViewSort.Sort( itemCount );
int index = 0;
@ -333,7 +350,7 @@ namespace Xceed.Wpf.DataGrid
for( int i = 1; i <= itemCount; i++ )
{
DataGridCollectionViewGroup oldGroup = ( DataGridCollectionViewGroup )groupItems[ indexes[ i ] ];
DataGridCollectionViewGroup oldGroup = subGroupsArray[ indexes[ i ] ];
DataGridCollectionViewGroup newGroup = new DataGridCollectionViewGroup( oldGroup, newSortedGroup );
// Sort sub items
@ -345,62 +362,48 @@ namespace Xceed.Wpf.DataGrid
}
}
internal int BinarySearchGroup( DataGridCollectionViewGroup value, IComparer<DataGridCollectionViewGroup> comparer )
internal void SortGroups( List<GroupSortComparer> groupSortComparers, int level )
{
if( comparer == null )
throw new ArgumentNullException( "comparer" );
ObservableCollection<object> items = this.ProtectedItems;
Debug.Assert( items.Count == this.ItemCount );
int itemCount = this.ProtectedItemCount;
int low = 0;
int hi = ( items.Count ) - 1;
if( itemCount == 0 )
return;
while( low <= hi )
int[] indexes;
indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ )
{
int compareResult;
int median = ( low + ( ( hi - low ) >> 1 ) );
indexes[ i ] = i;
}
DataGridCollectionViewGroup medianGroup = items[ median ] as DataGridCollectionViewGroup;
DataGridCollectionViewGroup[] subGroupsArray = new DataGridCollectionViewGroup[ itemCount ];
m_subGroups.Values.CopyTo( subGroupsArray, 0 );
// We exclude ourself from the research because we seek for a new valid position
if( medianGroup == value )
{
if( low == hi )
return low;
// "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
DataGridCollectionViewGroupSort collectionViewSort = new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], subGroupsArray );
median++;
medianGroup = items[ median ] as DataGridCollectionViewGroup;
}
collectionViewSort.Sort( itemCount );
level++;
m_protectedItems.Clear();
try
{
compareResult = comparer.Compare( medianGroup, value );
}
catch( Exception exception )
{
throw new InvalidOperationException( "IComparer has failed to compare the values.", exception );
}
for( int i = 1; i <= itemCount; i++ )
{
DataGridCollectionViewGroup group = subGroupsArray[ indexes[ i ] ];
if( compareResult == 0 )
{
return median;
}
if( compareResult < 0 )
// Sort sub groups
if( !group.IsBottomLevel )
{
low = median + 1;
}
else
{
hi = median - 1;
group.SortGroups( groupSortComparers, level );
}
m_protectedItems.Add( group );
}
return ~low;
this.ProtectedItemCount = m_protectedItems.Count;
m_protectedItemsCollectionChanged.Invoke( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
internal void CreateFixedGroupNames( int fixedGroupLevel, ObservableCollection<GroupDescription> groupByList, GroupSortComparer[] groupSortComparers )
internal void CreateFixedGroupNames( int fixedGroupLevel, ObservableCollection<GroupDescription> groupByList, List<GroupSortComparer> groupSortComparers )
{
GroupDescription groupDescription = this.SubGroupBy;
@ -419,43 +422,6 @@ namespace Xceed.Wpf.DataGrid
}
internal int GlobalRawItemCount
{
get
{
return m_globalRawItemCount;
}
}
internal List<RawItem> RawItems
{
get
{
return m_sortedRawItems;
}
}
internal void GetGlobalItems( List<object> items )
{
if( this.IsBottomLevel )
{
items.AddRange( this.ProtectedItems );
return;
}
int count = this.ItemCount;
for( int i = 0; i < count; i++ )
{
DataGridCollectionViewGroup subGroup = this.ProtectedItems[ i ] as DataGridCollectionViewGroup;
if( subGroup == null )
throw new InvalidOperationException( "Sub-groups cannot be null (Nothing in Visual Basic)." );
subGroup.GetGlobalItems( items );
}
}
internal RawItem GetRawItemAtGlobalSortedIndex( int index )
{
if( this.IsBottomLevel )
@ -464,19 +430,14 @@ namespace Xceed.Wpf.DataGrid
}
else
{
int count = this.ItemCount;
for( int i = 0; i < count; i++ )
foreach( object value in this.ProtectedItems )
{
DataGridCollectionViewGroup subGroups = this.ProtectedItems[ i ] as DataGridCollectionViewGroup;
if( subGroups == null )
throw new InvalidOperationException( "Sub-groups cannot be null (Nothing in Visual Basic)." );
DataGridCollectionViewGroup subGroup = value as DataGridCollectionViewGroup;
int subGroupCount = subGroups.GlobalRawItemCount;
int subGroupCount = subGroup.GlobalRawItemCount;
if( index < subGroupCount )
return subGroups.GetRawItemAtGlobalSortedIndex( index );
return subGroup.GetRawItemAtGlobalSortedIndex( index );
index -= subGroupCount;
}
@ -499,9 +460,6 @@ namespace Xceed.Wpf.DataGrid
{
Debug.Assert( this.IsBottomLevel );
if( m_sortedRawItems == null )
m_sortedRawItems = new List<RawItem>( 4 );
m_globalRawItemCount++;
DataGridCollectionViewGroup parent = m_parent;
@ -526,21 +484,13 @@ namespace Xceed.Wpf.DataGrid
this.ProtectedItems.Insert( index, rawItem.DataItem );
}
internal void RemoveRawItem( RawItem rawItem )
{
if( !this.IsBottomLevel )
throw new InvalidOperationException( "An attempt was made to remove a data item from a group other than the bottom-level group." );
int index = this.RawItemIndexOf( rawItem );
this.RemoveRawItemAt( index );
}
internal virtual void RemoveRawItemAt( int index )
{
Debug.Assert( this.IsBottomLevel );
Debug.Assert( m_sortedRawItems != null );
Debug.Assert( m_sortedRawItems.Count > 0 );
if( m_sortedRawItems == null )
int count = m_sortedRawItems.Count;
if( count == 0 )
return;
if( index != -1 )
@ -554,8 +504,6 @@ namespace Xceed.Wpf.DataGrid
parent = parent.Parent;
}
int count = m_sortedRawItems.Count;
for( int i = index + 1; i < count; i++ )
{
m_sortedRawItems[ i ].SetSortedIndex( i - 1 );
@ -570,7 +518,9 @@ namespace Xceed.Wpf.DataGrid
this.ProtectedItems.RemoveAt( index );
if( ( this.ProtectedItemCount == 0 ) && ( m_parent != null ) )
{
m_parent.RemoveGroup( this );
}
}
}
@ -606,7 +556,7 @@ namespace Xceed.Wpf.DataGrid
if( m_sortedRawItems == null )
return -1; // ~0
Debug.Assert( ( m_sortedRawItems.Count == this.ItemCount ) || ( this is DataGridCollectionViewGroupRoot ) );
Debug.Assert( ( m_sortedRawItems.Count == this.ProtectedItemCount ) || ( this is DataGridCollectionViewGroupRoot ) );
int low = 0;
int hi = ( m_sortedRawItems.Count ) - 1;
@ -664,7 +614,7 @@ namespace Xceed.Wpf.DataGrid
if( view == null )
return null;
Stats.StatFunction statFunction = view.StatFunctions[ propertyName ];
StatFunction statFunction = view.StatFunctions[ propertyName ];
Debug.Assert( view != null );
@ -674,12 +624,17 @@ namespace Xceed.Wpf.DataGrid
return this.GetStatFunctionResult( statFunction, view ).Value;
}
internal Stats.StatResult GetStatFunctionResult( Stats.StatFunction statFunction, DataGridCollectionView view )
internal StatResult GetStatFunctionResult( StatFunction statFunction, DataGridCollectionView view )
{
if( !m_statFunctionValues.ContainsKey( statFunction ) )
this.CalculateStatFunctionValue( statFunction, view );
StatResult result;
if( !m_statFunctionValues.TryGetValue( statFunction, out result ) )
{
result = null;
m_statFunctionValues[ statFunction ] = result;
}
return m_statFunctionValues[ statFunction ];
return result;
}
// This clears the value of all the previously calculated StatFunction Results for this group.
@ -688,31 +643,80 @@ namespace Xceed.Wpf.DataGrid
m_statFunctionValues.Clear();
}
internal void InvokeStatFunctionsPropertyChanged( DataGridCollectionView view )
internal void InvokeStatFunctionsPropertyChanged( DataGridCollectionView collectionView )
{
if( view.CalculateChangedPropertyStatsOnly )
if( this.HasPropertyChangedListeners )
{
foreach( Stats.StatFunction statFunction in view.InvalidatedStatFunctions )
if( collectionView.CalculateChangedPropertyStatsOnly && !this.CalculateAllStats )
{
foreach( StatFunction statFunction in collectionView.InvalidatedStatFunctions )
{
this.OnPropertyChanged( new PropertyChangedEventArgs( statFunction.ResultPropertyName ) );
{
this.OnPropertyChanged( new PropertyChangedEventArgs( statFunction.ResultPropertyName ) );
}
}
}
}
else
{
foreach( PropertyDescriptor statFunctionPropertyDescriptor in view.GetStatFunctionProperties() )
else
{
this.OnPropertyChanged( new PropertyChangedEventArgs( statFunctionPropertyDescriptor.Name ) );
foreach( PropertyDescriptor statFunctionPropertyDescriptor in collectionView.GetStatFunctionProperties() )
{
this.OnPropertyChanged( new PropertyChangedEventArgs( statFunctionPropertyDescriptor.Name ) );
}
}
}
this.CalculateAllStats = false;
}
private void CalculateStatFunctionValue( Stats.StatFunction statFunction, DataGridCollectionView view )
private int BinarySearchGroup( DataGridCollectionViewGroup value, IComparer<DataGridCollectionViewGroup> comparer )
{
m_statFunctionValues[ statFunction ] = new Stats.StatResult(
new InvalidOperationException( Log.NotToolkitStr( "Statistical functions" ) )
);
if( comparer == null )
throw new ArgumentNullException( "comparer" );
int low = 0;
int hi = ( this.ProtectedItemCount ) - 1;
int median;
int compareResult;
while( low <= hi )
{
median = ( low + ( ( hi - low ) >> 1 ) );
DataGridCollectionViewGroup medianGroup = this.ProtectedItems[ median ] as DataGridCollectionViewGroup;
if( medianGroup == value )
{
if( low == hi )
return low;
return median;
}
try
{
compareResult = comparer.Compare( medianGroup, value );
}
catch( Exception exception )
{
throw new InvalidOperationException( "IComparer has failed to compare the values.", exception );
}
if( compareResult == 0 )
{
return median;
}
if( compareResult < 0 )
{
low = median + 1;
}
else
{
hi = median - 1;
}
}
return ~low;
}
private static object GetHashKeyFromName( object groupName )
@ -723,7 +727,8 @@ namespace Xceed.Wpf.DataGrid
return groupName;
}
private DataGridCollectionViewGroup CreateSubGroup( object groupName, int level, ObservableCollection<GroupDescription> groupByList, GroupSortComparer[] groupSortComparers )
private DataGridCollectionViewGroup CreateSubGroup( object groupName, int level, ObservableCollection<GroupDescription> groupByList,
List<GroupSortComparer> groupSortComparers )
{
// If sortComparers is null, we are in massive group creation, no order check.
DataGridCollectionViewGroup group = new DataGridCollectionViewGroup( groupName, this, m_nextSubGroupUnsortedIndex );
@ -745,7 +750,9 @@ namespace Xceed.Wpf.DataGrid
index = this.BinarySearchGroup( group, groupSortComparers[ level ] );
if( index < 0 )
{
index = ~index;
}
}
level++;
@ -764,7 +771,7 @@ namespace Xceed.Wpf.DataGrid
{
Debug.Assert( !this.IsBottomLevel );
m_groupsDictionary.Add( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ), group );
m_subGroups.Add( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ), group );
this.ProtectedItemCount++;
this.ProtectedItems.Insert( index, group );
}
@ -783,12 +790,15 @@ namespace Xceed.Wpf.DataGrid
Debug.Assert( !this.IsBottomLevel );
Debug.Assert( ( group.m_globalRawItemCount == 0 ) && ( group.ProtectedItemCount == 0 ) );
m_subGroups.Remove( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ) );
this.ProtectedItemCount--;
m_groupsDictionary.Remove( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ) );
this.ProtectedItems.Remove( group );
if( ( this.ProtectedItemCount == 0 ) && ( m_parent != null ) )
if( ( m_subGroups.Count == 0 ) && ( m_parent != null ) )
{
m_parent.RemoveGroup( this );
}
}
#region ICustomTypeDescriptor Members
@ -893,20 +903,211 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region INotifyPropertyChanged Members
protected sealed override event PropertyChangedEventHandler PropertyChanged
{
add
{
this.PropertyChangedImpl += value;
}
remove
{
this.PropertyChangedImpl -= value;
}
}
protected override void OnPropertyChanged( PropertyChangedEventArgs e )
{
var handler = this.PropertyChangedImpl;
if( handler == null )
return;
handler.Invoke( this, e );
}
private bool HasPropertyChangedListeners
{
get
{
return ( this.PropertyChangedImpl != null );
}
}
private event PropertyChangedEventHandler PropertyChangedImpl;
#endregion
private PropertyDescriptorCollection m_classProperties;
private Dictionary<Stats.StatFunction, Stats.StatResult> m_statFunctionValues = new Dictionary<Stats.StatFunction, Stats.StatResult>( s_statFunctionComparer );
private readonly Dictionary<StatFunction, StatResult> m_statFunctionValues = new Dictionary<StatFunction, StatResult>( StatFunctionComparer.Default );
protected int m_globalRawItemCount;
protected List<RawItem> m_sortedRawItems;
protected readonly List<RawItem> m_sortedRawItems;
private readonly OptimizedReadOnlyObservableCollection m_optimizedItems;
private readonly Dictionary<object, DataGridCollectionViewGroup> m_subGroups;
private readonly IList<object> m_protectedItems;
private readonly Action<NotifyCollectionChangedEventArgs> m_protectedItemsCollectionChanged;
private Hashtable m_groupsDictionary;
private GroupDescription m_subGroupBy;
private DataGridCollectionViewGroup m_parent;
private int m_unsortedIndex;
private readonly DataGridCollectionViewGroup m_parent;
private readonly int m_unsortedIndex;
private int m_nextSubGroupUnsortedIndex;
private static Stats.StatFunctionComparer s_statFunctionComparer = new Stats.StatFunctionComparer();
#region OptimizedReadOnlyObservableCollection Private Class
// We re-implement IList and IList<object> to override the implementation of the
// IndexOf and Contains methods to use our optimized way.
private sealed class OptimizedReadOnlyObservableCollection : ReadOnlyObservableCollection<object>, IList, IList<object>
{
internal OptimizedReadOnlyObservableCollection( DataGridCollectionViewGroup dataGridCollectionViewGroup )
: base( dataGridCollectionViewGroup.ProtectedItems )
{
if( dataGridCollectionViewGroup == null )
throw new ArgumentNullException( "dataGridCollectionViewGroup" );
m_dataGridCollectionViewGroup = dataGridCollectionViewGroup;
}
public new int IndexOf( object item )
{
// The DataGridCollectionViewGroup has been optimized to use the information
// stored on the RawItem associated with the data item instead of searching the item in the list.
return m_dataGridCollectionViewGroup.IndexOf( item );
}
public new bool Contains( object item )
{
// The DataGridCollectionViewGroup has been optimized to use the information
// stored on the RawItem associated with the data item instead of searching the item in the list.
return m_dataGridCollectionViewGroup.Contains( item );
}
private readonly DataGridCollectionViewGroup m_dataGridCollectionViewGroup;
}
#endregion
#region ObservableCollectionHelper Private Class
private static class ObservableCollectionHelper
{
private const string AssemblyName = "Xceed.Wpf.DataGrid.CollectionViewGroupExtractor";
private const string GetItemsMethodName = "GetItems";
private const string GetCollectionChangedMethodName = "GetCollectionChanged";
private static readonly Func<ObservableCollection<object>, IList<object>> s_getItems;
private static readonly Func<ObservableCollection<object>, Action<NotifyCollectionChangedEventArgs>> s_collectionChanged;
static ObservableCollectionHelper()
{
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( new AssemblyName( ObservableCollectionHelper.AssemblyName ), AssemblyBuilderAccess.RunAndCollect );
var moduleBuilder = assemblyBuilder.DefineDynamicModule( ObservableCollectionHelper.AssemblyName );
var typeBuilder = moduleBuilder.DefineType( "ObservableCollectionExtractor", TypeAttributes.Class | TypeAttributes.NotPublic | TypeAttributes.AutoLayout, typeof( ObservableCollection<object> ) );
ObservableCollectionHelper.DefineGetItemsMethod( typeBuilder );
ObservableCollectionHelper.DefineGetCollectionChangedMethod( typeBuilder );
var targetType = typeBuilder.CreateType();
s_getItems = ( Func<ObservableCollection<object>, IList<object>> )Delegate.CreateDelegate( typeof( Func<ObservableCollection<object>, IList<object>> ), targetType.GetMethod( ObservableCollectionHelper.GetItemsMethodName, BindingFlags.Public | BindingFlags.Static ) );
s_collectionChanged = ( Func<ObservableCollection<object>, Action<NotifyCollectionChangedEventArgs>> )Delegate.CreateDelegate( typeof( Func<ObservableCollection<object>, Action<NotifyCollectionChangedEventArgs>> ), targetType.GetMethod( ObservableCollectionHelper.GetCollectionChangedMethodName, BindingFlags.Public | BindingFlags.Static ) );
}
internal static IList<object> GetItems( ObservableCollection<object> source )
{
if( source == null )
throw new ArgumentNullException( "source" );
var storage = ( s_getItems != null ) ? s_getItems.Invoke( source ) : null;
if( storage == null )
throw new InvalidOperationException( "TODODOC: Unable to retrieve the ObservableCollection<>'s items storage." );
private OptimizedReadOnlyObservableCollection m_optimizedItems;
return storage;
}
internal static Action<NotifyCollectionChangedEventArgs> GetCollectionChanged( ObservableCollection<object> source )
{
if( source == null )
throw new ArgumentNullException( "source" );
var collectionChanged = ( s_collectionChanged != null ) ? s_collectionChanged.Invoke( source ) : null;
if( collectionChanged == null )
throw new InvalidOperationException( "TODODOC: Unable to retrieve the ObservableCollection<>'s collection change method." );
return collectionChanged;
}
private static void DefineGetItemsMethod( TypeBuilder typeBuilder )
{
var propertyInfo = typeof( ObservableCollection<object> ).GetProperty( "Items", BindingFlags.Instance | BindingFlags.NonPublic, null, typeof( IList<object> ), new Type[ 0 ], null );
if( ( propertyInfo == null ) || !propertyInfo.CanRead )
throw new InvalidOperationException( "TODODOC: Unable to retrieve the ObservableCollection<>.Items property." );
var methodInfo = propertyInfo.GetGetMethod( true );
if( ( methodInfo == null ) || !ObservableCollectionHelper.HasCallingConvention( methodInfo.CallingConvention, CallingConventions.HasThis ) )
throw new InvalidOperationException( "TODODOC: Unable to retrieve the ObservableCollection<>.Items property." );
var methodBuilder = typeBuilder.DefineMethod(
ObservableCollectionHelper.GetItemsMethodName,
MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard,
typeof( IList<object> ),
new Type[] { typeof( ObservableCollection<object> ) } );
var body = methodBuilder.GetILGenerator();
// Load the reference to the ObservableCollection and put it on top of the stack.
body.Emit( OpCodes.Ldarg_0 );
// Invoke the property getter of the reference. This operation pops the reference
// from the stack and pushes the result of the property getter.
body.Emit( OpCodes.Callvirt, methodInfo );
// Since the result of the propery getter will be retrieved by the method's caller,
// we may leave it on the stack and simply return.
body.Emit( OpCodes.Ret );
}
private static void DefineGetCollectionChangedMethod( TypeBuilder typeBuilder )
{
var methodInfo = typeof( ObservableCollection<object> ).GetMethod( "OnCollectionChanged", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof( NotifyCollectionChangedEventArgs ) }, null );
if( ( methodInfo == null ) || methodInfo.IsPrivate || !ObservableCollectionHelper.HasCallingConvention( methodInfo.CallingConvention, CallingConventions.HasThis ) )
throw new InvalidOperationException( "TODODOC: Unable to retrieve the ObservableCollection<>.OnCollectionChanged method." );
var constructorInfo = typeof( Action<NotifyCollectionChangedEventArgs> ).GetConstructor( new Type[] { typeof( object ), typeof( IntPtr ) } );
if( ( constructorInfo == null ) || constructorInfo.IsPrivate || !ObservableCollectionHelper.HasCallingConvention( constructorInfo.CallingConvention, CallingConventions.HasThis ) )
throw new InvalidOperationException( "TODODOC: Unable to retrieve the Action<>'s constructor." );
var methodBuilder = typeBuilder.DefineMethod(
ObservableCollectionHelper.GetCollectionChangedMethodName,
MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard,
typeof( Action<NotifyCollectionChangedEventArgs> ),
new Type[] { typeof( ObservableCollection<object> ) } );
var body = methodBuilder.GetILGenerator();
// Load the reference to the ObservableCollection and put it on top of the stack.
body.Emit( OpCodes.Ldarg_0 );
// The last loaded reference will be consume in the call to "new Action<>".
// We must duplicate the value since it will be consume by the call that retrieve the
// target method's address.
body.Emit( OpCodes.Dup );
// This operation pops the top ObservableCollection's reference from the stack
// and pushes the ObservableCollection<>.OnCollectionChanged method's address.
body.Emit( OpCodes.Ldvirtftn, methodInfo );
// Create an Action<> delegate from the first ObservableCollection's reference we
// have put on the stack and the target method's address.
body.Emit( OpCodes.Newobj, constructorInfo );
// The resulting delegate should be on top of the stack. We simply leave it there
// so it will be retrieved by the method's caller.
body.Emit( OpCodes.Ret );
}
private static bool HasCallingConvention( CallingConventions source, CallingConventions value )
{
return ( ( source & value ) == value );
}
}
#endregion
}
}

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

@ -16,22 +16,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewGroupRoot : DataGridCollectionViewGroup
{
#region CONSTRUCTORS
public DataGridCollectionViewGroupRoot( DataGridCollectionView parentCollectionView )
: base( null, null, 0 )
internal DataGridCollectionViewGroupRoot( DataGridCollectionView parentCollectionView )
: base( 128 )
{
if( parentCollectionView == null )
throw new ArgumentNullException( "parentCollectionView" );
m_parentCollectionView = parentCollectionView;
}
@ -41,44 +34,28 @@ namespace Xceed.Wpf.DataGrid
m_parentCollectionView = template.m_parentCollectionView;
}
#endregion CONSTRUCTORS
#region PROTECTED METHODS
protected override DataGridCollectionView GetCollectionView()
{
return m_parentCollectionView;
}
#endregion PROTECTED METHODS
#region INTERNAL METHODS
internal void SortRootRawItems( SortDescriptionInfo[] sortDescriptionInfos, List<RawItem> globalRawItems )
{
Debug.Assert( this.IsBottomLevel );
List<RawItem> rawItems = this.RawItems;
if( rawItems == null )
return;
int itemCount = rawItems.Count;
int itemCount = m_sortedRawItems.Count;
if( itemCount == 0 )
return;
int[] indexes;
indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ )
{
indexes[ i ] = rawItems[ i ].Index;
indexes[ i ] = m_sortedRawItems[ i ].Index;
}
// "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
DataGridCollectionViewSort collectionViewSort =
new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
DataGridCollectionViewSort collectionViewSort = new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
collectionViewSort.Sort( itemCount );
int index = 0;
@ -87,22 +64,15 @@ namespace Xceed.Wpf.DataGrid
{
RawItem newRawItem = globalRawItems[ indexes[ i ] ];
newRawItem.SetSortedIndex( index );
rawItems[ index ] = newRawItem;
m_sortedRawItems[ index ] = newRawItem;
index++;
}
}
#endregion INTERNAL METHODS
#region RawItem management for BottomLevel
internal override void InsertRawItem( int index, RawItem rawItem )
{
Debug.Assert( this.IsBottomLevel );
if( m_sortedRawItems == null )
m_sortedRawItems = new List<RawItem>( 128 );
m_globalRawItemCount++;
int count = m_sortedRawItems.Count;
@ -119,11 +89,15 @@ namespace Xceed.Wpf.DataGrid
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--;
int count = m_sortedRawItems.Count;
for( int i = index + 1; i < count; i++ )
{
@ -155,12 +129,6 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion RawItem management for BottomLevel
#region PRIVATE FILEDS
private DataGridCollectionView m_parentCollectionView;
#endregion PRIVATE FIELDS
}
}

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

@ -27,31 +27,25 @@ namespace Xceed.Wpf.DataGrid
{
internal class DataGridCollectionViewGroupSort : IndexWeakHeapSort
{
public DataGridCollectionViewGroupSort(
int[] dataIndexArray,
GroupSortComparer groupSortedComparer,
DataGridCollectionViewGroup parentGroup )
public DataGridCollectionViewGroupSort( int[] dataIndexArray, GroupSortComparer groupSortedComparer, DataGridCollectionViewGroup[] protectedItems )
: base( dataIndexArray )
{
if( parentGroup == null )
throw new ArgumentNullException( "parentGroup" );
if( groupSortedComparer == null )
throw new ArgumentNullException( "groupSortedComparer" );
m_groupSortedComparer = groupSortedComparer;
m_groups = parentGroup.ProtectedItems;
m_groups = protectedItems;
}
public override int Compare( int xDataIndex, int yDataIndex )
{
DataGridCollectionViewGroup xGroup = m_groups[ xDataIndex ] as DataGridCollectionViewGroup;
DataGridCollectionViewGroup yGroup = m_groups[ yDataIndex ] as DataGridCollectionViewGroup;
DataGridCollectionViewGroup xGroup = m_groups[ xDataIndex ];
DataGridCollectionViewGroup yGroup = m_groups[ yDataIndex ];
return m_groupSortedComparer.Compare( xGroup, yGroup );
}
private GroupSortComparer m_groupSortedComparer;
private ObservableCollection<object> m_groups;
private DataGridCollectionViewGroup[] m_groups;
}
}

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

@ -15,15 +15,11 @@
***********************************************************************************/
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Windows;
using System.Windows.Data;
using System.Collections;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Diagnostics;
using Xceed.Wpf.DataGrid.Stats;
namespace Xceed.Wpf.DataGrid
@ -64,7 +60,7 @@ namespace Xceed.Wpf.DataGrid
#region StatFunctions Property
internal ObservableCollection<Stats.StatFunction> StatFunctions
internal ObservableCollection<StatFunction> StatFunctions
{
get
{
@ -72,7 +68,7 @@ namespace Xceed.Wpf.DataGrid
}
}
private ObservableCollection<Stats.StatFunction> m_statFunctions;
private StatFunctionCollection m_statFunctions;
#endregion StatFunctions Property
@ -115,11 +111,10 @@ namespace Xceed.Wpf.DataGrid
DataGridCollectionView dataGridCollectionView = currentView as DataGridCollectionView;
dataGridCollectionView.StatFunctions.Clear();
int count = m_statFunctions.Count;
for( int i = 0; i < count; i++ )
foreach( var statFunction in m_statFunctions )
{
dataGridCollectionView.StatFunctions.Add( m_statFunctions[ i ] );
dataGridCollectionView.StatFunctions.Add( statFunction );
}
dataGridCollectionView.UpdateChangedPropertyStatsOnly = this.UpdateChangedPropertyStatsOnly;

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

@ -482,7 +482,9 @@ namespace Xceed.Wpf.DataGrid
internal void OnEditCanceled( DataGridItemEventArgs e )
{
if( this.EditCanceled != null )
{
this.EditCanceled( this, e );
}
}
public event EventHandler<DataGridItemCancelEventArgs> CommittingEdit;

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

@ -108,7 +108,7 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region AutoCreateItemProperty Public Property
#region AutoCreateItemProperties Public Property
public bool AutoCreateItemProperties
{
@ -258,7 +258,7 @@ namespace Xceed.Wpf.DataGrid
#region StatFunctions Public Property
public StatFunctionCollection StatFunctions
internal StatFunctionCollection StatFunctions
{
get
{

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

@ -384,7 +384,7 @@ namespace Xceed.Wpf.DataGrid
#endregion PropertyDescriptor Property
#region IsAutoCreated
#region IsAutoCreated Property
public bool IsAutoCreated
{
@ -392,7 +392,7 @@ namespace Xceed.Wpf.DataGrid
private set;
}
#endregion IsAutoCreated
#endregion IsAutoCreated Property
#region PUBLIC METHODS

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

@ -15,15 +15,12 @@
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using Xceed.Wpf.DataGrid.Converters;
using System.Windows.Data;
using Xceed.Wpf.DataGrid.Converters;
using Xceed.Wpf.DataGrid.FilterCriteria;
namespace Xceed.Wpf.DataGrid
@ -31,22 +28,25 @@ namespace Xceed.Wpf.DataGrid
public abstract partial class DataGridItemPropertyBase : INotifyPropertyChanged, ICloneable
{
#region CONSTRUCTORS
protected DataGridItemPropertyBase()
{
this.Browsable = true;
}
protected DataGridItemPropertyBase( DataGridItemPropertyBase template )
: this()
{
m_name = template.m_name;
m_dataType = template.m_dataType;
m_title = template.m_title;
m_readOnly = template.m_readOnly;
m_overrideReadOnlyForInsertion = template.m_overrideReadOnlyForInsertion;
m_isASubRelationship = template.m_isASubRelationship;
m_browsable = template.m_browsable;
m_calculateDistinctValues = template.m_calculateDistinctValues;
m_synonym = template.m_synonym;
m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ];
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ];
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ];
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ];
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ];
m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ];
m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] = template.m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ];
m_converter = template.m_converter;
m_converterCulture = template.m_converterCulture;
m_converterParameter = template.m_converterParameter;
@ -86,20 +86,18 @@ namespace Xceed.Wpf.DataGrid
if( isReadOnly.HasValue )
{
m_readOnly = isReadOnly.Value;
this.SetIsReadOnly( isReadOnly.Value );
}
m_overrideReadOnlyForInsertion = overrideReadOnlyForInsertion;
this.SetOverrideReadOnlyForInsertion( overrideReadOnlyForInsertion );
m_dataType = dataType;
if( isASubRelationship != null )
{
m_isASubRelationship = isASubRelationship;
this.SetIsASubRelationship( isASubRelationship );
}
}
#endregion CONSTRUCTORS
#region Name Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
@ -114,7 +112,7 @@ namespace Xceed.Wpf.DataGrid
if( string.IsNullOrEmpty( value ) )
throw new ArgumentException( "Name is null (Nothing in Visual Basic) or empty.", "Name" );
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the name of a property already added to a containing collection." );
m_name = value;
@ -136,7 +134,7 @@ namespace Xceed.Wpf.DataGrid
}
set
{
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the DataType of a property already added to a containing collection." );
this.SetDataType( value );
@ -161,11 +159,11 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_readOnly;
return m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ];
}
set
{
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the IsReadOnly property of a DataGridItemProperty already added to a containing collection." );
this.SetIsReadOnly( value );
@ -174,11 +172,9 @@ namespace Xceed.Wpf.DataGrid
internal void SetIsReadOnly( bool isReadOnly )
{
m_readOnly = isReadOnly;
m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ] = isReadOnly;
}
private bool m_readOnly;
#endregion IsReadOnly Property
#region OverrideReadOnlyForInsertion Property
@ -187,11 +183,14 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_overrideReadOnlyForInsertion;
if( !m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] )
return null;
return m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ];
}
set
{
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the OverrideReadOnlyForInsertion property of a DataGridItemProperty already added to a containing collection." );
this.SetOverrideReadOnlyForInsertion( value );
@ -200,11 +199,18 @@ namespace Xceed.Wpf.DataGrid
internal void SetOverrideReadOnlyForInsertion( Nullable<bool> overrideReadOnlyForInsertion )
{
m_overrideReadOnlyForInsertion = overrideReadOnlyForInsertion;
if( overrideReadOnlyForInsertion.HasValue )
{
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ] = overrideReadOnlyForInsertion.Value;
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] = true;
}
else
{
m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet
| DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ] = false;
}
}
private Nullable<bool> m_overrideReadOnlyForInsertion;
#endregion OverrideReadOnlyForInsertion Property
#region IsASubRelationship Property
@ -213,24 +219,37 @@ namespace Xceed.Wpf.DataGrid
{
get
{
if( m_isASubRelationship == null )
{
if( m_dataType == null )
return false;
if( m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] )
return m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ];
bool isASubRelationship = ItemsSourceHelper.IsASubRelationship( m_dataType );
if( m_dataType == null )
return false;
if( m_initialized )
m_isASubRelationship = isASubRelationship;
bool isASubRelationship = ItemsSourceHelper.IsASubRelationship( m_dataType );
return isASubRelationship;
if( this.Initialized )
{
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ] = isASubRelationship;
m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] = true;
}
return m_isASubRelationship.Value;
return isASubRelationship;
}
}
private Nullable<bool> m_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 IsASubRelationship Property
@ -256,6 +275,33 @@ namespace Xceed.Wpf.DataGrid
#endregion Title Property
#region Synonym Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
public string Synonym
{
get
{
return m_synonym;
}
set
{
if( this.Initialized )
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 )
{
m_synonym = value;
}
private string m_synonym;
#endregion Synonym Property
#region SortComparer Property
public IComparer SortComparer
@ -284,7 +330,7 @@ namespace Xceed.Wpf.DataGrid
}
set
{
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the Converter property of a DataGridItemProperty already added to a containing collection." );
m_converter = value;
@ -293,7 +339,7 @@ namespace Xceed.Wpf.DataGrid
internal IValueConverter GetBindingConverter( object sourceItem )
{
if( !m_initialized )
if( !this.Initialized )
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 )
@ -328,7 +374,7 @@ namespace Xceed.Wpf.DataGrid
}
set
{
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the ConverterCulture property of a DataGridItemProperty already added to a containing collection." );
m_converterCulture = value;
@ -349,7 +395,7 @@ namespace Xceed.Wpf.DataGrid
}
set
{
if( m_initialized )
if( this.Initialized )
throw new InvalidOperationException( "An attempt was made to change the ConverterParameter property of a DataGridItemProperty already added to a containing collection." );
m_converterParameter = value;
@ -409,18 +455,6 @@ namespace Xceed.Wpf.DataGrid
#endregion FilterCriterion Property
#region ValueChanged Event
private void OnValueChanged( ValueChangedEventArgs e )
{
if( this.ValueChanged != null )
this.ValueChanged( this, e );
}
internal event EventHandler<ValueChangedEventArgs> ValueChanged;
#endregion ComponentValueChanged Event
#region CalculateDistinctValues Property
public bool CalculateDistinctValues
@ -428,20 +462,20 @@ namespace Xceed.Wpf.DataGrid
get
{
// Always activate DistinctValues if not explicitly specified
if( !m_isCalculateDistinctValuesInitialized )
if( !this.IsCalculateDistinctValuesInitialized )
return true;
return m_calculateDistinctValues;
return m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ];
}
set
{
if( m_calculateDistinctValues != value )
if( value != m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] )
{
m_calculateDistinctValues = value;
m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] = value;
this.OnPropertyChanged( "CalculateDistinctValues" );
}
m_isCalculateDistinctValuesInitialized = true;
this.IsCalculateDistinctValuesInitialized = true;
}
}
@ -449,17 +483,14 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_isCalculateDistinctValuesInitialized;
return m_flags[ DataGridItemPropertyBaseFlags.IsCalculateDistinctValuesInitialized ];
}
set
{
m_isCalculateDistinctValuesInitialized = value;
m_flags[ DataGridItemPropertyBaseFlags.IsCalculateDistinctValuesInitialized ] = value;
}
}
private bool m_calculateDistinctValues; // = null;
private bool m_isCalculateDistinctValuesInitialized;
#endregion CalculateDistinctValues Property
#region MaxDistinctValues Property
@ -484,7 +515,7 @@ namespace Xceed.Wpf.DataGrid
#endregion MaxDistinctValues Property
#region DistinctValuesSortComparer
#region DistinctValuesSortComparer Property
public IComparer DistinctValuesSortComparer
{
@ -494,7 +525,7 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region DistinctValuesEqualityComparer
#region DistinctValuesEqualityComparer Property
public IEqualityComparer DistinctValuesEqualityComparer
{
@ -510,18 +541,16 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_initialized;
return m_flags[ DataGridItemPropertyBaseFlags.IsInitialized ];
}
set
{
Debug.Assert( value );
m_initialized = value;
m_flags[ DataGridItemPropertyBaseFlags.IsInitialized ] = value;
}
}
private bool m_initialized;
#endregion Initialized Property
#region Browsable Property
@ -532,48 +561,16 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_browsable;
return m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ];
}
set
{
m_browsable = value;
m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ] = value;
}
}
private bool m_browsable = true;
#endregion Browsable Property
#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
#region ForeignKeyDescription Property
public DataGridForeignKeyDescription ForeignKeyDescription
@ -614,6 +611,8 @@ namespace Xceed.Wpf.DataGrid
if( m_groupSortStatResultPropertyName != value )
{
m_groupSortStatResultPropertyName = value;
this.OnPropertyChanged( "GroupSortStatResultPropertyName" );
}
}
}
@ -632,7 +631,49 @@ namespace Xceed.Wpf.DataGrid
#endregion GroupSortStatResultComparer Property
#region PUBLIC METHODS
#region ValueChanged Event
private void OnValueChanged( ValueChangedEventArgs e )
{
if( this.ValueChanged != null )
{
this.ValueChanged( this, e );
}
}
internal event EventHandler<ValueChangedEventArgs> ValueChanged;
#endregion ComponentValueChanged Event
#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 )
{
@ -661,11 +702,11 @@ namespace Xceed.Wpf.DataGrid
UnboundDataItem unboundDataItem = component as UnboundDataItem;
if( unboundDataItem != null )
{
component = unboundDataItem.DataItem;
}
bool isReadOnly = ( this.OverrideReadOnlyForInsertion.HasValue && this.OverrideReadOnlyForInsertion.Value )
? false
: this.IsReadOnly;
bool isReadOnly = ( this.OverrideReadOnlyForInsertion.HasValue && this.OverrideReadOnlyForInsertion.Value ) ? false : this.IsReadOnly;
if( isReadOnly )
throw new InvalidOperationException( "An attempt was made to set a read-only property." );
@ -699,10 +740,6 @@ namespace Xceed.Wpf.DataGrid
}
#endif
#endregion PUBLIC METHODS
#region PROTECTED METHODS
protected abstract object GetValueCore( object component );
protected virtual void SetValueCore( object component, object value )
@ -710,10 +747,6 @@ namespace Xceed.Wpf.DataGrid
this.OnValueChanged( new ValueChangedEventArgs( component ) );
}
#endregion PROTECTED METHODS
#region INTERNAL METHODS
internal PropertyDescriptorFromItemPropertyBase GetPropertyDescriptorForBinding()
{
if( m_propertyDescriptorFromItemProperty == null )
@ -731,8 +764,6 @@ namespace Xceed.Wpf.DataGrid
{
}
#endregion INTERNAL METHODS
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
@ -745,11 +776,8 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region PRIVATE FIELDS
private PropertyDescriptorFromItemPropertyBase m_propertyDescriptorFromItemProperty;
#endregion PRIVATE FIELDS
private BitFlags m_flags;
internal class ValueChangedEventArgs : EventArgs
{
@ -764,5 +792,67 @@ namespace Xceed.Wpf.DataGrid
private set;
}
}
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;
}
[Flags]
private enum DataGridItemPropertyBaseFlags : ushort
{
IsReadOnly = 0x0001,
IsOverrideReadOnlyForInsertionSet = 0x0002,
IsOverrideReadOnlyForInsertion = 0x0004,
IsASubRelationshipSet = 0x0008,
IsASubRelationship = 0x0010,
CalculateDistinctValues = 0x0020,
IsCalculateDistinctValuesInitialized = 0x0040,
IsInitialized = 0x0080,
IsBrowsable = 0x0100,
}
}
}

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

@ -96,6 +96,7 @@ namespace Xceed.Wpf.DataGrid
oldItem.FilterCriterionChanged -= new EventHandler( DataGridItemProperty_FilterCriterionChanged );
oldItem.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
oldItem.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
}
}
@ -118,6 +119,7 @@ namespace Xceed.Wpf.DataGrid
}
item.ValueChanged += new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged += new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
item.SetUnspecifiedPropertiesValues( this );
try
@ -127,6 +129,7 @@ namespace Xceed.Wpf.DataGrid
catch
{
item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
throw;
}
@ -144,6 +147,7 @@ namespace Xceed.Wpf.DataGrid
oldItem.FilterCriterionChanged -= new EventHandler( DataGridItemProperty_FilterCriterionChanged );
oldItem.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
oldItem.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
}
item.FilterCriterionChanged += new EventHandler( DataGridItemProperty_FilterCriterionChanged );
@ -165,6 +169,7 @@ namespace Xceed.Wpf.DataGrid
}
item.ValueChanged += new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged += new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
item.SetUnspecifiedPropertiesValues( this );
item.Initialized = true;
@ -180,6 +185,7 @@ namespace Xceed.Wpf.DataGrid
catch
{
item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
item.Initialized = false;
if( item is DataGridUnboundItemProperty )
@ -255,6 +261,7 @@ namespace Xceed.Wpf.DataGrid
item.FilterCriterionChanged -= this.DataGridItemProperty_FilterCriterionChanged;
item.ValueChanged -= this.DataGridItemProperty_ValueChanged;
item.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
}
}
@ -308,7 +315,9 @@ namespace Xceed.Wpf.DataGrid
internal void SuspendUnboundItemPropertyChanged( object component )
{
if( m_unboundItemPropertyChangedSuspended == null )
{
m_unboundItemPropertyChangedSuspended = new Hashtable( 1 );
}
m_unboundItemPropertyChangedSuspended[ component ] = DBNull.Value;
}
@ -324,7 +333,9 @@ namespace Xceed.Wpf.DataGrid
m_unboundItemPropertyChangedSuspended.Remove( component );
if( m_unboundItemPropertyChangedSuspended.Count == 0 )
{
m_unboundItemPropertyChangedSuspended = null;
}
this.RefreshUnboundItemProperty( component );
}
@ -405,6 +416,25 @@ namespace Xceed.Wpf.DataGrid
}
}
#region ItemPropertyGroupSortStatNameChanged Event
internal event EventHandler ItemPropertyGroupSortStatNameChanged;
private void OnDataGridItemProperty_PropertyChanged( object sender, PropertyChangedEventArgs e )
{
if( e.PropertyName != "GroupSortStatResultPropertyName" )
return;
var handler = this.ItemPropertyGroupSortStatNameChanged;
if( handler == null )
return;
handler.Invoke( this, e );
}
#endregion
private List<DataGridItemPropertyBase> m_defaultItemProperties;
private Type m_itemType;
private int m_unboundItemPropertyCount;

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

@ -24,8 +24,6 @@ namespace Xceed.Wpf.DataGrid
{
internal class DataGridLINQPageManager : DataGridPageManagerBase
{
#region CONSTRUCTORS
public DataGridLINQPageManager( DataGridVirtualizingQueryableCollectionView collectionView, object syncRoot, bool supportsPrimaryKeyOptimizations )
: base( collectionView )
{
@ -33,9 +31,11 @@ namespace Xceed.Wpf.DataGrid
m_syncRoot = syncRoot;
}
#endregion CONSTRUCTORS
#region DATA VIRTUALIZATION
protected override void DisposeCore()
{
m_syncRoot = null;
base.DisposeCore();
}
protected override int OnQueryItemCountCore( VirtualList virtualList )
{
@ -80,6 +80,19 @@ namespace Xceed.Wpf.DataGrid
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 )
{
@ -91,8 +104,8 @@ namespace Xceed.Wpf.DataGrid
return;
IQueryable queryable = ( IQueryable )parameters[ 1 ];
object[] items = new object[ queryInfo.RequestedItemCount ];
int requestedItemCount = queryInfo.RequestedItemCount;
object[] items = new object[ requestedItemCount ];
System.Collections.IEnumerator enumerator;
@ -104,22 +117,23 @@ namespace Xceed.Wpf.DataGrid
try
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization,"Beginning Provider Execute for page at start index: " + queryInfo.StartIndex.ToString() );
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() );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Ended Provider Execute for page at start index: " + queryInfo.StartIndex.ToString() );
int i = 0;
while( enumerator.MoveNext() )
while( enumerator.MoveNext() && ( i < requestedItemCount ) )
{
object current = enumerator.Current;
if( current != null )
{
items[ i ] = enumerator.Current;
i++;
i++;
}
}
}
catch( Exception exception )
@ -131,6 +145,18 @@ namespace Xceed.Wpf.DataGrid
}
}
items = items.Where( item => item != null ).ToArray();
try
{
if( items.Count() != requestedItemCount )
throw new InvalidOperationException( "TODODOC : The number of non-null items return 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 )
@ -139,33 +165,7 @@ namespace Xceed.Wpf.DataGrid
queryInfo.EndQuery( items );
}
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 );
}
}
protected override void DisposeCore()
{
m_syncRoot = null;
base.DisposeCore();
}
#endregion DATA VIRTUALIZATION
#region PRIVATE FIELDS
private object m_syncRoot;
private bool m_supportsPrimaryKeyOptimizations;
#endregion PRIVATE FIELDS
}
}

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

@ -95,7 +95,6 @@ namespace Xceed.Wpf.DataGrid
m_parentCollection.m_deferResortCount++;
}
#region IDisposable Members
public void Dispose()

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

@ -23,8 +23,6 @@ namespace Xceed.Wpf.DataGrid
{
public class DataGridUnboundItemProperty : DataGridItemPropertyBase
{
#region CONSTRUTORS
public DataGridUnboundItemProperty()
{
}
@ -69,10 +67,6 @@ namespace Xceed.Wpf.DataGrid
this.CommittingValue += template.CommittingValue;
}
#endregion CONSTRUTORS
#region PUBLIC METHODS
public override object Clone()
{
Type type = this.GetType();
@ -83,17 +77,9 @@ namespace Xceed.Wpf.DataGrid
return base.Clone();
}
#endregion PUBLIC METHODS
#region PUBLIC EVENTS
public event EventHandler<DataGridItemPropertyQueryValueEventArgs> QueryValue;
public event EventHandler<DataGridItemPropertyCommittingValueEventArgs> CommittingValue;
#endregion PUBLIC EVENTS
#region PROTECTED METHODS
protected override object GetValueCore( object component )
{
if( this.QueryValue != null )
@ -116,10 +102,6 @@ namespace Xceed.Wpf.DataGrid
base.SetValueCore( component, value );
}
#endregion PROTECTED METHODS
#region INTERNAL METHODS
internal void Refresh( object component )
{
PropertyDescriptorFromItemPropertyBase propertyDescriptor = this.GetPropertyDescriptorForBinding();
@ -147,7 +129,5 @@ namespace Xceed.Wpf.DataGrid
this.OverrideReadOnlyForInsertion = false;
}
}
#endregion INTERNAL METHODS
}
}

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

@ -15,20 +15,10 @@
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Globalization;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Data;
using Xceed.Utils.Collections;
using Xceed.Utils.Data;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
@ -47,7 +37,6 @@ namespace Xceed.Wpf.DataGrid
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 );
@ -68,7 +57,7 @@ namespace Xceed.Wpf.DataGrid
internal override DataGridCollectionViewBase CreateDetailDataGridCollectionViewBase(
IEnumerable detailDataSource,
DataGridDetailDescription parentDetailDescription,
DataGridCollectionViewBase rootDataGridCollectionViewBase )
DataGridCollectionViewBase parentDataGridCollectionViewBase )
{
throw new NotImplementedException();
}
@ -82,7 +71,6 @@ namespace Xceed.Wpf.DataGrid
get
{
bool canGroup = true;
return canGroup;
}
}
@ -368,7 +356,9 @@ namespace Xceed.Wpf.DataGrid
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.
@ -925,7 +915,11 @@ namespace Xceed.Wpf.DataGrid
}
if( sendResetNotification )
{
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
this.OnPropertyChanged( new PropertyChangedEventArgs( "Groups" ) );
}
}

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

@ -23,29 +23,34 @@ namespace Xceed.Wpf.DataGrid
{
internal class DeferredOperation
{
#region CONSTRUCTORS
internal static DeferredOperation RefreshDistinctValuesOperation = new DeferredOperation( DeferredOperationAction.RefreshDistincValues, false );
public DeferredOperation(
DeferredOperationAction action,
bool filteredItemsChanged )
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,
int startingIndex,
IList items )
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 )
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.
@ -82,13 +87,7 @@ namespace Xceed.Wpf.DataGrid
}
}
public DeferredOperation(
DeferredOperationAction action,
int newSourceItemCount,
int newStartingIndex,
IList newItems,
int oldStartingIndex,
IList oldItems )
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.
@ -100,8 +99,6 @@ namespace Xceed.Wpf.DataGrid
m_oldStartingIndex = oldStartingIndex;
}
#endregion CONSTRUCTORS
#region Action Property
public DeferredOperationAction Action
@ -186,6 +183,20 @@ namespace Xceed.Wpf.DataGrid
#endregion OldItems Property
#region DataItem Property
public object DataItem
{
get
{
return m_dataItem;
}
}
private object m_dataItem;
#endregion
#region FilteredItemsChanged Property
public bool FilteredItemsChanged
@ -210,7 +221,9 @@ namespace Xceed.Wpf.DataGrid
Refresh = 5,
Resort = 6,
Regroup = 7,
RefreshDistincValues = 8
RefreshDistincValues = 8,
ResetItem = 9,
RefreshUnboundItemProperties = 10
}
}
}

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

@ -16,27 +16,31 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Threading;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid
{
internal class DeferredOperationManager
internal sealed class DeferredOperationManager
{
public DeferredOperationManager(
DataGridCollectionViewBase collectionViewToUpdate,
Dispatcher dispatcher,
bool postPendingRefreshWithoutDispatching )
#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_collectionViewToUpdate = collectionViewToUpdate;
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;
}
@ -49,7 +53,7 @@ namespace Xceed.Wpf.DataGrid
{
lock( this )
{
return ( m_pendingFlags.Data != 0 ) || ( m_deferredOperations != null );
return ( m_pendingFlags.Data != 0 ) || ( !m_isProcessingOperations && m_deferredOperations.Count > 0 );
}
}
}
@ -136,6 +140,32 @@ namespace Xceed.Wpf.DataGrid
#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 )
@ -144,9 +174,11 @@ namespace Xceed.Wpf.DataGrid
{
m_dispatcherOperation.Abort();
m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
}
m_invalidatedGroups = null;
m_invalidatedGroups.Clear();
}
}
@ -154,22 +186,21 @@ namespace Xceed.Wpf.DataGrid
{
lock( this )
{
if( ( m_dispatcherOperation != null ) && ( m_invalidatedGroups == null ) )
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 = null;
m_deferredOperations.Clear();
}
}
public void PurgeAddWithRemoveOrReplace()
{
if( m_deferredOperations == null )
return;
if( m_deferredOperations.Count >= 2 )
{
DeferredOperation addOperation = m_deferredOperations[ 0 ];
@ -205,7 +236,9 @@ namespace Xceed.Wpf.DataGrid
lastIndexToRemove = i;
if( removed )
{
firstIndexToRemove = 0;
}
}
else
{
@ -223,9 +256,7 @@ namespace Xceed.Wpf.DataGrid
if( lastIndexToRemove > -1 )
{
m_deferredOperations.RemoveRange(
firstIndexToRemove,
( lastIndexToRemove - firstIndexToRemove ) + 1 );
m_deferredOperations.RemoveRange( firstIndexToRemove, ( lastIndexToRemove - firstIndexToRemove ) + 1 );
}
}
}
@ -242,7 +273,7 @@ namespace Xceed.Wpf.DataGrid
case DeferredOperation.DeferredOperationAction.Refresh:
{
this.RefreshPending = true;
m_deferredOperations = null;
m_deferredOperations.Clear();
break;
}
@ -274,22 +305,25 @@ namespace Xceed.Wpf.DataGrid
default:
{
if( m_deferredOperations == null )
m_deferredOperations = new List<DeferredOperation>();
m_deferredOperations.Add( operation );
m_hasNewOperationsSinceStartTime = true;
if( this.DeferProcessOfInvalidatedGroupStats )
{
m_deferredOperationsToProcess++;
}
break;
}
}
if( ( m_dispatcher != null ) && ( m_dispatcherOperation == null ) )
{
Debug.Assert( m_collectionViewToUpdate.Loaded );
Debug.Assert( m_collectionView.Loaded );
m_dispatcherOperation = m_dispatcher.BeginInvoke(
DispatcherPriority.DataBind,
new DispatcherOperationCallback( this.Dispatched_Process ),
null );
m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.DataBind, new DispatcherOperationCallback( this.Dispatched_Process ), null );
m_dispatcherOperationStartTime = DateTime.UtcNow;
m_hasNewOperationsSinceStartTime = false;
}
}
}
@ -298,29 +332,23 @@ namespace Xceed.Wpf.DataGrid
{
lock( this )
{
this.RefreshPending |= sourceDeferredOperationManager.RefreshPending;
this.RegroupPending |= sourceDeferredOperationManager.RegroupPending;
this.ResortPending |= sourceDeferredOperationManager.ResortPending;
this.RefreshDistincValuesPending |= sourceDeferredOperationManager.RefreshDistincValuesPending;
this.RefreshDistincValuesWithFilteredItemChangedPending |=
sourceDeferredOperationManager.RefreshDistincValuesWithFilteredItemChangedPending;
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 = null;
m_deferredOperations.Clear();
return;
}
List<DeferredOperation> sourceOperations = sourceDeferredOperationManager.m_deferredOperations;
if( ( sourceOperations == null ) || ( sourceOperations.Count == 0 ) )
if( sourceOperations.Count == 0 )
return;
if( m_deferredOperations == null )
m_deferredOperations = new List<DeferredOperation>();
m_deferredOperations.InsertRange( 0, sourceOperations );
}
}
@ -330,7 +358,7 @@ namespace Xceed.Wpf.DataGrid
this.Process( true );
}
internal void InvalidateGroupStats( DataGridCollectionViewGroup group )
public void InvalidateGroupStats( DataGridCollectionViewGroup group, bool calculateAllStats = false )
{
if( group == null )
return;
@ -340,28 +368,31 @@ namespace Xceed.Wpf.DataGrid
if( this.RefreshPending )
return;
if( m_invalidatedGroups == null )
m_invalidatedGroups = new List<DataGridCollectionViewGroup>( 64 );
DataGridCollectionViewGroup parent = group;
while( parent != null )
{
if( !m_invalidatedGroups.Contains( parent ) )
{
parent.ClearStatFunctionsResult();
m_invalidatedGroups.Add( parent );
}
parent.ClearStatFunctionsResult();
parent.CalculateAllStats = calculateAllStats;
parent = parent.Parent;
}
if( ( m_dispatcherOperation == null ) && ( m_dispatcher != null ) )
if( m_dispatcher != null )
{
m_dispatcherOperation = m_dispatcher.BeginInvoke(
DispatcherPriority.DataBind,
new DispatcherOperationCallback( this.Dispatched_Process ),
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;
}
}
}
}
@ -371,7 +402,7 @@ namespace Xceed.Wpf.DataGrid
if( item == null )
throw new ArgumentNullException( "item" );
if( m_deferredOperations == null )
if( m_deferredOperations.Count == 0 )
return false;
int deferredOperationsCount = m_deferredOperations.Count;
@ -388,7 +419,7 @@ namespace Xceed.Wpf.DataGrid
{
object oldItem = deferredOperation.OldItems[ j ];
if( Object.Equals( oldItem, item ) )
if( object.Equals( oldItem, item ) )
return true;
}
}
@ -406,14 +437,29 @@ namespace Xceed.Wpf.DataGrid
private void Process( bool processAll )
{
//This method will be called again when Dispose() is called on the DeferRefreshHelper of the CollectionView.
if( m_collectionViewToUpdate.InDeferRefresh )
if( m_collectionView.InDeferRefresh )
return;
bool refreshForced = false;
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_collectionViewToUpdate.SyncRoot )
lock( m_collectionView.SyncRoot )
{
lock( this )
{
@ -422,18 +468,13 @@ namespace Xceed.Wpf.DataGrid
{
m_dispatcherOperation.Abort();
m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
}
int operationIndex = 0;
long startTicks = DateTime.Now.Ticks;
// The fact of processing a deferredOperations can cause other DeferRefresh on the CollectionView
// that will finaly call this Process() again even if not yet completed.
// So we must cache all the flags and deferredOperations in local variable to prevent
// double execution of the operation.
List<DeferredOperation> deferredOperations = m_deferredOperations;
m_deferredOperations = null;
// The fact of processing a deferredOperations can cause other DeferRefresh on the CollectionView that will finaly call this Process() again even if not yet completed.
// So we must cache all the flags in local variable to prevent double execution of the operation, except for m_deferredOperation which has its own flag is set.
m_isProcessingOperations = true;
bool refreshDistincValuesWithFilteredItemChangedPending = this.RefreshDistincValuesWithFilteredItemChangedPending;
this.RefreshDistincValuesWithFilteredItemChangedPending = false;
bool refreshDistincValuesPending = this.RefreshDistincValuesPending;
@ -444,85 +485,86 @@ namespace Xceed.Wpf.DataGrid
this.RegroupPending = false;
bool resortPending = this.ResortPending;
this.ResortPending = false;
List<DataGridCollectionViewGroup> invalidatedGroups = m_invalidatedGroups;
m_invalidatedGroups = null;
bool ensureGroupPosition = true;
bool refreshForced = false;
m_collectionView.RaisePreBatchCollectionChanged();
DateTime startTime = DateTime.UtcNow;
if( refreshPending )
{
Debug.Assert( deferredOperations == null );
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation(
DeferredOperation.DeferredOperationAction.Refresh, -1, null ), out refreshForced );
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ), out refreshForced );
}
else if( regroupPending )
{
ensureGroupPosition = false;
// Regrouping also do resorting
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation(
DeferredOperation.DeferredOperationAction.Regroup, -1, null ), out refreshForced );
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Regroup, -1, null ), out refreshForced );
}
else if( resortPending )
{
ensureGroupPosition = false;
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation(
DeferredOperation.DeferredOperationAction.Resort, -1, null ), out refreshForced );
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Resort, -1, null ), out refreshForced );
}
if( ( deferredOperations != null ) && ( !refreshForced ) )
if( ( m_deferredOperations.Count > 0 ) && ( !refreshForced ) )
{
int count = deferredOperations.Count;
int count = m_deferredOperations.Count;
int operationIndex = 0;
while( ( operationIndex < count ) && ( ( processAll ) || ( DateTime.Now.Ticks - startTicks ) < 1000000 ) && ( !refreshForced ) )
while( ( operationIndex < count ) && ( !refreshForced ) && ( processAll || ( DateTime.UtcNow.Subtract( startTime ) < DeferredOperationManager.MaxProcessDuration ) ) )
{
m_collectionViewToUpdate.ExecuteSourceItemOperation( deferredOperations[ operationIndex ], out refreshForced );
m_collectionView.ExecuteSourceItemOperation( m_deferredOperations[ operationIndex ], out refreshForced );
operationIndex++;
}
if( ( operationIndex < count ) && ( !refreshForced ) )
{
deferredOperations.RemoveRange( 0, operationIndex );
if( m_deferredOperations == null )
{
m_deferredOperations = deferredOperations;
}
else
{
Debug.Assert( false, "Should never get there." );
m_deferredOperations.InsertRange( 0, deferredOperations );
}
m_deferredOperations.RemoveRange( 0, operationIndex );
m_deferredOperationsToProcess -= operationIndex;
}
else
{
m_deferredOperations.Clear();
m_deferredOperationsToProcess = 0;
}
}
m_isProcessingOperations = false;
// The recalculation of the StatFunctions is performed last.
if( invalidatedGroups != null )
m_collectionViewToUpdate.ProcessInvalidatedGroupStats( invalidatedGroups, ensureGroupPosition );
if( ( m_deferredOperationsToProcess <= 0 || m_forceProcessOfInvalidatedGroupStats ) && ( m_invalidatedGroups.Count != 0 ) )
{
m_collectionView.ProcessInvalidatedGroupStats( m_invalidatedGroups );
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.Now.Ticks - startTicks ) < 1000000 ) )
if( processAll || ( DateTime.UtcNow.Subtract( startTime ) < DeferredOperationManager.MaxProcessDuration ) )
{
if( refreshDistincValuesWithFilteredItemChangedPending || refreshDistincValuesPending )
{
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation(
DeferredOperation.DeferredOperationAction.RefreshDistincValues, refreshDistincValuesWithFilteredItemChangedPending ), out refreshForced );
m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.RefreshDistincValues,
refreshDistincValuesWithFilteredItemChangedPending ), out refreshForced );
}
}
else
{
if( refreshDistincValuesWithFilteredItemChangedPending )
{
this.RefreshDistincValuesWithFilteredItemChangedPending = true;
}
if( refreshDistincValuesPending )
{
this.RefreshDistincValuesPending = true;
}
}
}
if( this.HasPendingOperations )
m_collectionView.RaisePostBatchCollectionChanged();
if( this.HasPendingOperations || m_invalidatedGroups.Count != 0 )
{
Debug.Assert( !processAll );
Debug.Assert( m_dispatcher != null );
@ -532,29 +574,33 @@ namespace Xceed.Wpf.DataGrid
{
if( m_dispatcher != null )
{
m_dispatcherOperation = m_dispatcher.BeginInvoke(
DispatcherPriority.Input,
new DispatcherOperationCallback( this.Dispatched_Process ),
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 DataGridCollectionViewBase m_collectionViewToUpdate;
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_isProcessingOperations;
private bool m_forceProcessOfInvalidatedGroupStats;
private Dispatcher m_dispatcher;
private readonly Dispatcher m_dispatcher;
private DispatcherOperation m_dispatcherOperation;
private List<DataGridCollectionViewGroup> m_invalidatedGroups;
private DateTime m_dispatcherOperationStartTime;
private bool m_hasNewOperationsSinceStartTime;
[Flags]
private enum DeferredOperationManagerPendingFlags

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

@ -14,12 +14,8 @@
***********************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using Xceed.Utils.Collections;
using System.Diagnostics;
using System.Collections;
using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid
{
@ -28,7 +24,7 @@ namespace Xceed.Wpf.DataGrid
public DistinctValuesDictionary( DataGridCollectionViewBase dataGridCollectionViewBase )
{
if( dataGridCollectionViewBase == null )
throw new DataGridInternalException();
throw new DataGridInternalException( "dataGridCollectionView is null." );
m_dataGridCollectionViewBase = dataGridCollectionViewBase;
}
@ -66,7 +62,7 @@ namespace Xceed.Wpf.DataGrid
{
value = new ReadOnlyObservableHashList();
this.InternalAdd( key, value );
m_dataGridCollectionViewBase.ForceRefreshDistinctValuesForFieldName( key, value.InnerObservableHashList );
m_dataGridCollectionViewBase.ForceRefreshDistinctValuesForFieldName( key );
}
Debug.Assert( value != null );

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

@ -0,0 +1,87 @@
/*************************************************************************************
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 )
{
var target = ( DataGridCollectionViewBase )source;
target.DistinctValuesRefreshNeeded += new EventHandler( this.DeliverEvent );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.DistinctValuesRefreshNeeded -= new EventHandler( this.DeliverEvent );
}
}
}

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

@ -56,11 +56,10 @@ namespace Xceed.Wpf.DataGrid
ListSortDirection sortDirection = ListSortDirection.Ascending;
int result;
int sortInfoCount = m_sortInfos.Count;
for( int i = 0; i < sortInfoCount; i++ )
foreach( SortInfo sortInfo in m_sortInfos )
//for( int i = 0; i < sortInfoCount; i++ )
{
SortInfo sortInfo = m_sortInfos[ i ];
string statResultPropertyName = sortInfo.StatResultPropertyName;
IComparer sortComparer = sortInfo.SortComparer;
sortDirection = sortInfo.SortDirection;
@ -97,12 +96,12 @@ namespace Xceed.Wpf.DataGrid
public class SortInfo
{
public SortInfo( string name, ListSortDirection sortDirection, IComparer sortComparer )
public SortInfo( string statResultPropertyName, ListSortDirection sortDirection, IComparer sortComparer )
{
if( sortComparer == null )
throw new ArgumentNullException( "sortComparer" );
this.StatResultPropertyName = name;
this.StatResultPropertyName = statResultPropertyName;
this.SortDirection = sortDirection;
this.SortComparer = sortComparer;
}

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

@ -0,0 +1,92 @@
/*************************************************************************************
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 );
}
}
}

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

@ -0,0 +1,78 @@
/*************************************************************************************
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

@ -0,0 +1,78 @@
/*************************************************************************************
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 );
}
}
}

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

@ -128,87 +128,54 @@ namespace Xceed.Wpf.DataGrid
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 iTypedList )
private PropertyDescriptor GetPropertyDescriptorFromITypedList( ITypedList typedList )
{
if( string.IsNullOrEmpty( this.RelationName ) == true )
if( string.IsNullOrEmpty( this.RelationName ) || ( typedList == null ) )
return null;
Type objectType = null;
ICustomTypeDescriptor customTypeDescriptor = null;
PropertyDescriptorCollection properties = null;
PropertyDescriptor relationDescriptor = null;
TypeDescriptionProvider typeDescriptionProvider = null;
PropertyDescriptorCollection properties;
if( iTypedList != null )
{
properties = iTypedList.GetItemProperties( null );
properties = typedList.GetItemProperties( null );
if( ( properties != null ) && ( properties.Count > 0 ) )
return properties[ this.RelationName ];
if( ( properties != null ) && ( properties.Count > 0 ) )
{
relationDescriptor = properties[ this.RelationName ];
}
else
{
string listName = iTypedList.GetListName( null );
var listName = typedList.GetListName( null );
if( string.IsNullOrEmpty( listName ) )
return null;
if( string.IsNullOrEmpty( listName ) == false )
{
objectType = Type.GetType( listName, false, false );
var itemType = Type.GetType( listName, false, false );
if( itemType == null )
return null;
if( objectType != null )
{
typeDescriptionProvider = TypeDescriptor.GetProvider( objectType );
if( typeDescriptionProvider != null )
{
customTypeDescriptor = typeDescriptionProvider.GetTypeDescriptor( objectType );
if( customTypeDescriptor != null )
{
properties = customTypeDescriptor.GetProperties();
if( ( properties != null ) && ( properties.Count > 0 ) )
relationDescriptor = properties[ this.RelationName ];
}
}
}
}
}
}
var descriptionProvider = TypeDescriptor.GetProvider( itemType );
if( descriptionProvider == null )
return null;
return relationDescriptor;
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 ) == true )
if( string.IsNullOrEmpty( this.RelationName ) || ( firstItem == null ) )
return null;
Type objectType = null;
ICustomTypeDescriptor customTypeDescriptor = null;
PropertyDescriptorCollection properties = null;
PropertyDescriptor relationDescriptor = null;
TypeDescriptionProvider typeDescriptionProvider = null;
objectType = firstItem.GetType();
if( objectType != null )
{
typeDescriptionProvider = TypeDescriptor.GetProvider( objectType );
if( typeDescriptionProvider != null )
{
customTypeDescriptor = typeDescriptionProvider.GetTypeDescriptor( objectType, firstItem );
if( customTypeDescriptor != null )
{
properties = customTypeDescriptor.GetProperties();
var descriptor = ItemsSourceHelper.GetCustomTypeDescriptor( firstItem, firstItem.GetType() );
if( descriptor == null )
return null;
if( ( properties != null ) && ( properties.Count > 0 ) )
relationDescriptor = properties[ this.RelationName ];
}
}
}
var properties = descriptor.GetProperties();
if( ( properties != null ) && ( properties.Count > 0 ) )
return properties[ this.RelationName ];
return relationDescriptor;
return null;
}
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem )

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

@ -0,0 +1,87 @@
/*************************************************************************************
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 ProxyApplyingFilterCriteriasEventManager : WeakEventManager
{
#region Constructor
private ProxyApplyingFilterCriteriasEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ProxyApplyingFilterCriteriasEventManager CurrentManager
{
get
{
var managerType = typeof( ProxyApplyingFilterCriteriasEventManager );
var currentManager = ( ProxyApplyingFilterCriteriasEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ProxyApplyingFilterCriteriasEventManager();
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.ProxyApplyingFilterCriterias += new EventHandler( this.DeliverEvent );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxyApplyingFilterCriterias -= new EventHandler( this.DeliverEvent );
}
}
}

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

@ -0,0 +1,93 @@
/*************************************************************************************
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 ProxyAutoFilterValuesChangedEventManager : WeakEventManager
{
#region Constructor
private ProxyAutoFilterValuesChangedEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static ProxyAutoFilterValuesChangedEventManager CurrentManager
{
get
{
var managerType = typeof( ProxyAutoFilterValuesChangedEventManager );
var currentManager = ( ProxyAutoFilterValuesChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ProxyAutoFilterValuesChangedEventManager();
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.ProxyAutoFilterValuesChanged += new NotifyCollectionChangedEventHandler( this.OnEventRaised );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionViewBase )source;
target.ProxyAutoFilterValuesChanged -= new NotifyCollectionChangedEventHandler( this.OnEventRaised );
}
private void OnEventRaised( object sender, NotifyCollectionChangedEventArgs e )
{
this.DeliverEvent( sender, e );
}
}
}

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

@ -0,0 +1,87 @@
/*************************************************************************************
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

@ -0,0 +1,93 @@
/*************************************************************************************
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

@ -0,0 +1,93 @@
/*************************************************************************************
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 );
}
}
}

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

@ -16,12 +16,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.ComponentModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
@ -482,9 +481,9 @@ namespace Xceed.Wpf.DataGrid
typeof( Queryable ), "Count",
new Type[] { queryableElementType }, expressionToCount );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization,"Beginning Provider Execute for total count." );
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." );
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Ended Provider Execute for total count." );
return count;
}
@ -531,7 +530,7 @@ namespace Xceed.Wpf.DataGrid
MemberInfo member = QueryableExtensions.GetMemberInfo( typeExpression.Type, name );
if( member == null )
throw new DataGridInternalException();
throw new DataGridInternalException( "MemberInfo is null." );
if( member is PropertyInfo )
{
@ -651,9 +650,20 @@ namespace Xceed.Wpf.DataGrid
internal interface IQueryableGroupNameCountPair
{
object GroupName { get; }
Type GroupNameType { get; }
int Count { get; }
object GroupName
{
get;
}
Type GroupNameType
{
get;
}
int Count
{
get;
}
}
#endregion INTERNAL NESTED CLASSES
@ -668,24 +678,42 @@ namespace Xceed.Wpf.DataGrid
this.Count = count;
}
public T GroupName { get; set; }
public int Count { get; set; }
public T GroupName
{
get;
set;
}
public int Count
{
get;
set;
}
#region QueryableGroupNameCountPair Members
object IQueryableGroupNameCountPair.GroupName
{
get { return this.GroupName; }
get
{
return this.GroupName;
}
}
public Type GroupNameType
{
get { return typeof( T ); }
get
{
return typeof( T );
}
}
int IQueryableGroupNameCountPair.Count
{
get { return this.Count; }
get
{
return this.Count;
}
}
#endregion
@ -729,10 +757,29 @@ namespace Xceed.Wpf.DataGrid
private struct QueryableGroupNameCountPairInfo
{
public Type Type { get; set; }
public ConstructorInfo ConstructorInfo { get; set; }
public PropertyInfo KeyPropertyInfo { get; set; }
public PropertyInfo CountPropertyInfo { get; set; }
public Type Type
{
get;
set;
}
public ConstructorInfo ConstructorInfo
{
get;
set;
}
public PropertyInfo KeyPropertyInfo
{
get;
set;
}
public PropertyInfo CountPropertyInfo
{
get;
set;
}
}
#endregion PRIVATE NESTED CLASSES

145
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/RawItemMap.cs

@ -0,0 +1,145 @@
/*************************************************************************************
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;
using System.Linq;
namespace Xceed.Wpf.DataGrid
{
internal sealed class RawItemMap
{
#region [] Property
internal RawItem this[ object dataItem ]
{
get
{
Debug.Assert( dataItem != null );
RawItem value;
if( m_singleMap.TryGetValue( dataItem, out value ) )
return value;
RawItem[] values;
if( m_multiMap.TryGetValue( dataItem, out values ) )
return values[ 0 ];
return null;
}
}
#endregion
internal void Add( object dataItem, RawItem rawItem )
{
Debug.Assert( dataItem != null );
Debug.Assert( rawItem != null );
Debug.Assert( dataItem == rawItem.DataItem );
RawItem single;
RawItem[] multiple;
if( m_singleMap.TryGetValue( dataItem, out single ) )
{
Debug.Assert( rawItem != single, "It's not normal to be called twice for the same RawItem." );
m_multiMap.Add( dataItem, new RawItem[] { single, rawItem } );
m_singleMap.Remove( dataItem );
}
else if( m_multiMap.TryGetValue( dataItem, out multiple ) )
{
Debug.Assert( !multiple.Contains( rawItem ), "It's not normal to be called twice for the same RawItem." );
var length = multiple.Length;
Array.Resize<RawItem>( ref multiple, length + 1 );
multiple[ length ] = rawItem;
m_multiMap[ dataItem ] = multiple;
}
else
{
m_singleMap.Add( dataItem, rawItem );
}
}
internal void Remove( object dataItem, RawItem rawItem )
{
Debug.Assert( dataItem != null );
Debug.Assert( rawItem != null );
Debug.Assert( dataItem == rawItem.DataItem );
if( m_singleMap.Remove( dataItem ) )
return;
RawItem[] multiple;
if( !m_multiMap.TryGetValue( dataItem, out multiple ) )
return;
var length = multiple.Length;
if( length == 2 )
{
if( multiple[ 0 ] == rawItem )
{
m_singleMap.Add( dataItem, multiple[ 1 ] );
m_multiMap.Remove( dataItem );
}
else if( multiple[ 1 ] == rawItem )
{
m_singleMap.Add( dataItem, multiple[ 0 ] );
m_multiMap.Remove( dataItem );
}
}
else
{
Debug.Assert( length > 2 );
var index = Array.IndexOf( multiple, rawItem );
if( index < 0 )
return;
RawItem[] copy = new RawItem[ length - 1 ];
if( index > 0 )
{
Array.Copy( multiple, 0, copy, 0, index );
}
if( index < length - 1 )
{
Array.Copy( multiple, index + 1, copy, index, length - index - 1 );
}
m_multiMap[ dataItem ] = copy;
}
}
internal void Clear()
{
m_singleMap.Clear();
m_multiMap.Clear();
}
#region Private Fields
private readonly Dictionary<object, RawItem> m_singleMap = new Dictionary<object, RawItem>( 128 );
private readonly Dictionary<object, RawItem[]> m_multiMap = new Dictionary<object, RawItem[]>( 0 );
#endregion
}
}

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

@ -0,0 +1,87 @@
/*************************************************************************************
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 RootGroupChangedEventManager : WeakEventManager
{
#region Constructor
private RootGroupChangedEventManager()
{
}
#endregion
#region CurrentManager Private Property
private static RootGroupChangedEventManager CurrentManager
{
get
{
var managerType = typeof( RootGroupChangedEventManager );
var currentManager = ( RootGroupChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new RootGroupChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
#endregion
public static void AddListener( DataGridCollectionView 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( DataGridCollectionView 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 = ( DataGridCollectionView )source;
target.RootGroupChanged += new EventHandler( this.DeliverEvent );
}
protected override void StopListening( object source )
{
var target = ( DataGridCollectionView )source;
target.RootGroupChanged -= new EventHandler( this.DeliverEvent );
}
}
}

407
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(ForeignKeys)/ForeignKeyConfiguration.cs

@ -15,25 +15,21 @@
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Diagnostics;
using System.ComponentModel;
using System.Collections;
using System.Globalization;
using System.Collections.Specialized;
using System.Data;
using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid
{
public class ForeignKeyConfiguration : DependencyObject
public class ForeignKeyConfiguration : DependencyObject, IWeakEventListener
{
#region Constructors
static ForeignKeyConfiguration()
{
ForeignKeyConfiguration.DefaultDistinctValueItemContentTemplateProperty = ForeignKeyConfiguration.DefaultDistinctValueItemContentTemplatePropertyKey.DependencyProperty;
@ -45,30 +41,25 @@ namespace Xceed.Wpf.DataGrid
public ForeignKeyConfiguration()
{
this.SetDefaultDistinctValueItemContentTemplate( Column.GenericContentTemplateSelector.ForeignKeyDistinctValueItemContentTemplate );
this.SetDefaultCellContentTemplate( Column.GenericContentTemplateSelector.ForeignKeyCellContentTemplate );
this.SetDefaultGroupValueTemplate( Column.GenericContentTemplateSelector.ForeignKeyGroupValueTemplate );
this.SetDefaultScrollTipContentTemplate( Column.GenericContentTemplateSelector.ForeignKeyScrollTipContentTemplate );
this.SetDefaultCellContentTemplate( GenericContentTemplateSelector.ForeignKeyCellContentTemplate );
this.SetDefaultGroupValueTemplate( GenericContentTemplateSelector.ForeignKeyGroupValueTemplate );
this.SetDefaultScrollTipContentTemplate( GenericContentTemplateSelector.ForeignKeyScrollTipContentTemplate );
this.SetDefaultCellEditor( DefaultCellEditorSelector.ForeignKeyCellEditor );
}
#endregion
#region ValuePath Property
public static readonly DependencyProperty ValuePathProperty = DependencyProperty.Register(
"ValuePath",
typeof( string ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnSelectedValuePathChanged ) ) );
new FrameworkPropertyMetadata( null ) );
public string ValuePath
{
get
{
return m_ValuePath;
return ( string )this.GetValue( ForeignKeyConfiguration.ValuePathProperty );
}
set
{
@ -76,18 +67,6 @@ namespace Xceed.Wpf.DataGrid
}
}
private string m_ValuePath; // = null;
private static void OnSelectedValuePathChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
ForeignKeyConfiguration foreignKeyConfiguration = sender as ForeignKeyConfiguration;
if( foreignKeyConfiguration != null )
{
foreignKeyConfiguration.m_ValuePath = e.NewValue as string;
}
}
#endregion
#region DisplayMemberPath Property
@ -96,15 +75,13 @@ namespace Xceed.Wpf.DataGrid
"DisplayMemberPath",
typeof( string ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnDisplayMemberPathChanged ) ) );
new FrameworkPropertyMetadata( null ) );
public string DisplayMemberPath
{
get
{
return m_displayMemberPath;
return ( string )this.GetValue( ForeignKeyConfiguration.DisplayMemberPathProperty );
}
set
{
@ -112,18 +89,6 @@ namespace Xceed.Wpf.DataGrid
}
}
private string m_displayMemberPath; // = null;
private static void OnDisplayMemberPathChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
ForeignKeyConfiguration foreignKeyConfiguration = sender as ForeignKeyConfiguration;
if( foreignKeyConfiguration != null )
{
foreignKeyConfiguration.m_displayMemberPath = e.NewValue as string;
}
}
#endregion
#region ItemContainerStyle Property
@ -132,15 +97,13 @@ namespace Xceed.Wpf.DataGrid
"ItemContainerStyle",
typeof( Style ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnItemContainerStyleChanged ) ) );
new FrameworkPropertyMetadata( null ) );
public Style ItemContainerStyle
{
get
{
return m_itemContainerStyle;
return ( Style )this.GetValue( ForeignKeyConfiguration.ItemContainerStyleProperty );
}
set
{
@ -148,16 +111,6 @@ namespace Xceed.Wpf.DataGrid
}
}
private Style m_itemContainerStyle; // = null;
private static void OnItemContainerStyleChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
ForeignKeyConfiguration foreignKeyConfiguration = sender as ForeignKeyConfiguration;
if( foreignKeyConfiguration != null )
foreignKeyConfiguration.m_itemContainerStyle = e.NewValue as Style;
}
#endregion
#region ItemContainerStyleSelector Property
@ -166,15 +119,13 @@ namespace Xceed.Wpf.DataGrid
"ItemContainerStyleSelector",
typeof( StyleSelector ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnItemContainerStyleSelectorChanged ) ) );
new FrameworkPropertyMetadata( null ) );
public StyleSelector ItemContainerStyleSelector
{
get
{
return m_itemContainerStyleSelector;
return ( StyleSelector )this.GetValue( ForeignKeyConfiguration.ItemContainerStyleSelectorProperty );
}
set
{
@ -182,18 +133,6 @@ namespace Xceed.Wpf.DataGrid
}
}
private StyleSelector m_itemContainerStyleSelector; // = null;
private static void OnItemContainerStyleSelectorChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
ForeignKeyConfiguration foreignKeyConfiguration = sender as ForeignKeyConfiguration;
if( foreignKeyConfiguration != null )
{
foreignKeyConfiguration.m_itemContainerStyleSelector = e.NewValue as StyleSelector;
}
}
#endregion
#region IsAutoCreated Property
@ -220,8 +159,7 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_itemsSource;
return ( IEnumerable )this.GetValue( ForeignKeyConfiguration.ItemsSourceProperty );
}
set
{
@ -229,18 +167,65 @@ namespace Xceed.Wpf.DataGrid
}
}
private IEnumerable m_itemsSource;
private static void OnItemsSourceChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{
ForeignKeyConfiguration foreignConfiguration = sender as ForeignKeyConfiguration;
var foreignConfiguration = sender as ForeignKeyConfiguration;
if( foreignConfiguration != null )
{
foreignConfiguration.m_itemsSource = e.NewValue as IEnumerable;
foreignConfiguration.OnItemsSourceChanged( ( IEnumerable )e.OldValue, ( IEnumerable )e.NewValue );
}
}
private void OnItemsSourceChanged( IEnumerable oldItemsSource, IEnumerable newItemsSource )
{
//Unsubscribe from the old list changed event, if any.
if( oldItemsSource != null )
{
var oldNotifyCollectionChanged = oldItemsSource as INotifyCollectionChanged;
if( oldNotifyCollectionChanged != null )
{
CollectionChangedEventManager.RemoveListener( oldNotifyCollectionChanged, this );
}
else
{
var oldBindingList = oldItemsSource as IBindingList;
if( oldBindingList != null && oldBindingList.SupportsChangeNotification )
{
ListChangedEventManager.RemoveListener( oldBindingList, this );
}
}
}
//Subscribe from to the new list changed event, if any.
if( newItemsSource != null )
{
var newNotifyCollectionChanged = newItemsSource as INotifyCollectionChanged;
if( newNotifyCollectionChanged != null )
{
CollectionChangedEventManager.AddListener( newNotifyCollectionChanged, this );
}
else
{
var newBindingList = newItemsSource as IBindingList;
if( newBindingList != null && newBindingList.SupportsChangeNotification )
{
ListChangedEventManager.AddListener( newBindingList, this );
}
}
}
}
private void OnNotifiyCollectionChanged()
{
var handler = this.NotifiyCollectionChanged;
if( handler == null )
return;
handler.Invoke( this, EventArgs.Empty );
}
internal event EventHandler NotifiyCollectionChanged;
#endregion
#region ForeignKeyConverter Property
@ -265,6 +250,126 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region ForeignKeyValueConverter Property
public static readonly DependencyProperty ForeignKeyValueConverterProperty = DependencyProperty.Register(
"ForeignKeyValueConverter",
typeof( IValueConverter ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( null ) );
public IValueConverter ForeignKeyValueConverter
{
get
{
return ( IValueConverter )this.GetValue( ForeignKeyConfiguration.ForeignKeyValueConverterProperty );
}
set
{
this.SetValue( ForeignKeyConfiguration.ForeignKeyValueConverterProperty, value );
}
}
#endregion
#region ForeignKeyValueConverterParameter Property
public static readonly DependencyProperty ForeignKeyValueConverterParameterProperty = DependencyProperty.Register(
"ForeignKeyValueConverterParameter",
typeof( object ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( null ) );
public object ForeignKeyValueConverterParameter
{
get
{
return ( object )this.GetValue( ForeignKeyConfiguration.ForeignKeyValueConverterParameterProperty );
}
set
{
this.SetValue( ForeignKeyConfiguration.ForeignKeyValueConverterParameterProperty, value );
}
}
#endregion
#region ForeignKeyValueConverterCulture Property
public static readonly DependencyProperty ForeignKeyValueConverterCultureProperty = DependencyProperty.Register(
"ForeignKeyValueConverterCulture",
typeof( CultureInfo ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( null ) );
public CultureInfo ForeignKeyValueConverterCulture
{
get
{
return ( CultureInfo )this.GetValue( ForeignKeyConfiguration.ForeignKeyValueConverterCultureProperty );
}
set
{
this.SetValue( ForeignKeyConfiguration.ForeignKeyValueConverterCultureProperty, value );
}
}
#endregion
#region UseDefaultFilterCriterion Property
public static readonly DependencyProperty UseDefaultFilterCriterionProperty = DependencyProperty.Register(
"UseDefaultFilterCriterion",
typeof( bool ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( true ) );
public bool UseDefaultFilterCriterion
{
get
{
return ( bool )this.GetValue( ForeignKeyConfiguration.UseDefaultFilterCriterionProperty );
}
set
{
this.SetValue( ForeignKeyConfiguration.UseDefaultFilterCriterionProperty, value );
}
}
#endregion
#region UseDisplayedValueWhenExporting Property
public static readonly DependencyProperty UseDisplayedValueWhenExportingProperty = DependencyProperty.Register(
"UseDisplayedValueWhenExporting",
typeof( bool ),
typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( true ) );
public bool UseDisplayedValueWhenExporting
{
get
{
return ( bool )this.GetValue( ForeignKeyConfiguration.UseDisplayedValueWhenExportingProperty );
}
set
{
this.SetValue( ForeignKeyConfiguration.UseDisplayedValueWhenExportingProperty, value );
}
}
#endregion
#region ValuePathDataType Property
internal Type ValuePathDataType
{
get;
set;
}
#endregion
#region DefaultDistinctValueItemContentTemplate Property
private static readonly DependencyPropertyKey DefaultDistinctValueItemContentTemplatePropertyKey = DependencyProperty.RegisterReadOnly(
@ -396,7 +501,6 @@ namespace Xceed.Wpf.DataGrid
internal static readonly DependencyProperty DefaultCellEditorProperty;
internal CellEditor DefaultCellEditor
{
get
@ -417,42 +521,72 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region Static Methods
internal object GetDisplayMemberValue( object fieldValue )
{
try
{
var valuePath = this.ValuePath;
var displayMemberPath = this.DisplayMemberPath;
if( ( valuePath == null ) || ( displayMemberPath == null ) )
return fieldValue;
internal static void UpdateColumnsForeignKeyConfigurations(
Dictionary<string,ColumnBase> columns,
IEnumerable itemsSourceCollection,
Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors,
bool autoCreateForeignKeyConfigurations )
var itemsSource = this.ItemsSource;
//Convert the value from the ValuePath value to the DisplayMemberPath value, using a DataRowView or reflection.
if( ( itemsSource is DataView ) || ( itemsSource is DataTable ) )
{
foreach( object item in itemsSource )
{
DataRowView dataRowView = item as DataRowView;
if( dataRowView != null )
{
var value = dataRowView[ valuePath ];
if( fieldValue.Equals( value ) )
return dataRowView[ displayMemberPath ];
}
}
}
else
{
foreach( object item in itemsSource )
{
var value = item.GetType().GetProperty( valuePath ).GetValue( item, null );
if( fieldValue.Equals( value ) )
return item.GetType().GetProperty( displayMemberPath ).GetValue( item, null );
}
}
}
catch
{
//Swallow the exception, no need to terminate the application, since the original value will be exported.
}
return fieldValue;
}
internal static void UpdateColumnsForeignKeyConfigurations( Dictionary<string, ColumnBase> columns, IEnumerable itemsSourceCollection,
Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors, bool autoCreateForeignKeyConfigurations )
{
DataGridCollectionViewBase collectionViewBase =
itemsSourceCollection as DataGridCollectionViewBase;
DataGridCollectionViewBase collectionViewBase = itemsSourceCollection as DataGridCollectionViewBase;
if( collectionViewBase != null )
{
ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView(
columns,
collectionViewBase.ItemProperties,
autoCreateForeignKeyConfigurations );
ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( columns, collectionViewBase.ItemProperties, autoCreateForeignKeyConfigurations );
}
else
{
ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors(
columns,
fieldDescriptors,
autoCreateForeignKeyConfigurations );
ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors( columns, fieldDescriptors, autoCreateForeignKeyConfigurations );
}
}
// If a DataGridCollectionViewBase is used, get the ItemProperties it defines
// to be able to retreive DataGridForeignKeyDescription for each of them
// If a DataGridCollectionViewBase is used, get the ItemProperties it defines to be able to retreive DataGridForeignKeyDescription for each of them
// to get the auto-detected ForeignKey ItemsSource (if any).
// If a DataGridCollectionViewBase is not used, the ItemsSource must be
// manually specified on each Column in order to correctly display/edit the Data
internal static void UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView(
Dictionary<string,ColumnBase> columns,
DataGridItemPropertyCollection itemProperties,
bool autoCreateForeignKeyConfigurations )
// If a DataGridCollectionViewBase is not used, the ItemsSource must be manually specified on each Column in order to correctly display/edit the Data
internal static void UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( Dictionary<string, ColumnBase> columns, DataGridItemPropertyCollection itemProperties,
bool autoCreateForeignKeyConfigurations )
{
if( itemProperties == null )
return;
@ -467,17 +601,13 @@ namespace Xceed.Wpf.DataGrid
ColumnBase column;
columns.TryGetValue( itemProperty.Name, out column );
ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription(
column as Column,
description,
autoCreateForeignKeyConfigurations );
ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription( column as Column, description, autoCreateForeignKeyConfigurations );
}
}
private static void UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors(
Dictionary<string, ColumnBase> columns,
Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors,
bool autoCreateForeignKeyConfigurations )
private static void UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors( Dictionary<string, ColumnBase> columns,
Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors,
bool autoCreateForeignKeyConfigurations )
{
if( columns == null )
return;
@ -495,17 +625,12 @@ namespace Xceed.Wpf.DataGrid
ColumnBase column;
columns.TryGetValue( fieldDescriptor.Name, out column );
ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription(
column as Column,
description,
autoCreateForeignKeyConfigurations );
ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription( column as Column, description, autoCreateForeignKeyConfigurations );
}
}
internal static void SynchronizeForeignKeyConfigurationFromForeignKeyDescription(
Column column,
DataGridForeignKeyDescription description,
bool autoCreateForeignKeyConfigurations )
internal static void SynchronizeForeignKeyConfigurationFromForeignKeyDescription( Column column, DataGridForeignKeyDescription description,
bool autoCreateForeignKeyConfigurations )
{
if( ( description == null ) || ( column == null ) )
return;
@ -522,21 +647,22 @@ namespace Xceed.Wpf.DataGrid
column.ForeignKeyConfiguration = configuration;
}
// ValuePath will be affected to the FieldName when the
// configuration is auto-created to be able to modify
// local source using foreign key value
// ValuePath will be affected to the FieldName when the configuration is auto-created to be able to modify local source using foreign key value
if( configuration.IsAutoCreated )
{
if( string.IsNullOrEmpty( configuration.ValuePath ) )
{
configuration.ValuePath = description.ValuePath;
}
if( string.IsNullOrEmpty( configuration.DisplayMemberPath ) )
{
configuration.DisplayMemberPath = description.DisplayMemberPath;
}
}
// Affect the ItemsSource on the configuration if it is not
// already set
if( ( configuration.ItemsSource == null )
&& ( description.ItemsSource != null ) )
// Affect the ItemsSource on the configuration if it is not already set
if( ( configuration.ItemsSource == null ) && ( description.ItemsSource != null ) )
{
configuration.ItemsSource = description.ItemsSource;
}
@ -548,6 +674,19 @@ namespace Xceed.Wpf.DataGrid
}
}
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( ( managerType == typeof( CollectionChangedEventManager ) ) || ( managerType == typeof( ListChangedEventManager ) ) )
{
this.OnNotifiyCollectionChanged();
return true;
}
return false;
}
#endregion
}
}

24
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(ForeignKeys)/ForeignKeyContentControl.cs

@ -28,14 +28,8 @@ namespace Xceed.Wpf.DataGrid
{
internal class ForeignKeyContentControl : ContentControl
{
#region Static Members
private static readonly Binding BindingToValue;
#endregion
#region Constructors
static ForeignKeyContentControl()
{
ForeignKeyContentControl.BindingToValue = new Binding();
@ -56,8 +50,6 @@ namespace Xceed.Wpf.DataGrid
this.Focusable = false;
}
#endregion
#region ForeignKeyConfiguration Property
public static readonly DependencyProperty ForeignKeyConfigurationProperty = DependencyProperty.Register(
@ -154,14 +146,12 @@ namespace Xceed.Wpf.DataGrid
if( contentControl != null )
{
contentControl.NotifyKeyChanged();
contentControl.NotifyValueChanged();
}
}
#endregion
#region Protected Methods
protected void NotifyKeyChanged()
{
if( m_isBeingModified )
@ -196,10 +186,6 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion
#region Private Methods
private void OnKeyChanged()
{
ForeignKeyConfiguration configuration = this.ForeignKeyConfiguration;
@ -220,7 +206,7 @@ namespace Xceed.Wpf.DataGrid
if( ( configuration != null ) && ( configuration.ForeignKeyConverter != null ) )
{
this.Key = configuration.ForeignKeyConverter.GetValueFromKey( this.Value, configuration );
this.Key = configuration.ForeignKeyConverter.GetKeyFromValue( this.Value, configuration );
}
else
{
@ -228,12 +214,6 @@ namespace Xceed.Wpf.DataGrid
}
}
#endregion
#region Private Fields
private bool m_isBeingModified; // = false;
#endregion
}
}

4969
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/CustomItemContainerGenerator.cs

File diff suppressed because it is too large

109
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/DataItemDataProvider.cs

@ -0,0 +1,109 @@
/*************************************************************************************
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.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
internal sealed class DataItemDataProvider : DataItemDataProviderBase
{
#region Static Fields
private static readonly object EmptyDataItem = new object();
#endregion
#region IsEmpty Property
public override bool IsEmpty
{
get
{
return m_isEmpty;
}
}
private void SetIsEmpty( bool value )
{
if( m_isEmpty == value )
return;
m_isEmpty = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "IsEmpty" ) );
}
private bool m_isEmpty = true;
#endregion
public override void SetDataItem( object dataItem )
{
if( m_dataItem == dataItem )
return;
m_dataItem = dataItem;
if( this.IsRefreshDeferred )
return;
this.Refresh();
}
public override void ClearDataItem()
{
if( m_dataItem == DataItemDataProvider.EmptyDataItem )
return;
m_dataItem = DataItemDataProvider.EmptyDataItem;
if( this.IsRefreshDeferred )
return;
this.Refresh();
}
protected override void BeginQuery()
{
if( this.IsRefreshDeferred )
return;
base.BeginQuery();
if( m_dataItem == DataItemDataProvider.EmptyDataItem )
{
this.OnQueryFinished( null, null, this.OnDataChanged, true );
}
else
{
this.OnQueryFinished( m_dataItem, null, this.OnDataChanged, false );
}
}
private object OnDataChanged( object arg )
{
this.SetIsEmpty( ( bool )arg );
return null;
}
#region Private Fields
private object m_dataItem = DataItemDataProvider.EmptyDataItem;
#endregion
}
}

35
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/DataItemDataProviderBase.cs

@ -0,0 +1,35 @@
/*************************************************************************************
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.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
internal abstract class DataItemDataProviderBase : DataSourceProvider
{
#region IsEmpty Property
public abstract bool IsEmpty
{
get;
}
#endregion
public abstract void SetDataItem( object dataItem );
public abstract void ClearDataItem();
}
}

70
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/EmptyDataItemDataProvider.cs

@ -0,0 +1,70 @@
/*************************************************************************************
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.Threading;
namespace Xceed.Wpf.DataGrid
{
internal sealed class EmptyDataItemDataProvider : DataItemDataProviderBase
{
#region Constructor
private EmptyDataItemDataProvider()
{
}
#endregion
#region Instance Static Property
internal static EmptyDataItemDataProvider Instance
{
get
{
if( m_instance == null )
{
Interlocked.CompareExchange<EmptyDataItemDataProvider>( ref EmptyDataItemDataProvider.m_instance, new EmptyDataItemDataProvider(), null );
}
return m_instance;
}
}
private static EmptyDataItemDataProvider m_instance;
#endregion
#region IsEmpty Property
public override bool IsEmpty
{
get
{
return true;
}
}
#endregion
public override void SetDataItem( object dataItem )
{
}
public override void ClearDataItem()
{
}
}
}

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GeneratorNode.cs

@ -19,7 +19,7 @@ using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public partial class GeneratorNode
internal partial class GeneratorNode
{
internal GeneratorNode( GeneratorNode parent )
{

171
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GeneratorNodeFactory.cs

@ -19,11 +19,9 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Windows.Data;
using System.Windows.Controls;
using System.Collections.ObjectModel;
using Xceed.Wpf.DataGrid.Utils;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
@ -33,61 +31,53 @@ namespace Xceed.Wpf.DataGrid
NotifyCollectionChangedEventHandler groupsChangedHandler,
EventHandler<ExpansionStateChangedEventArgs> expansionStateChangedHandler,
EventHandler isExpandedChangingHandler,
EventHandler isExpandedChangedHandler )
EventHandler isExpandedChangedHandler,
DataGridControl dataGridControl )
{
if( itemsChangedHandler == null )
{
throw new ArgumentNullException( "itemsChangedHandler" );
}
if( groupsChangedHandler == null )
{
throw new ArgumentNullException( "groupsChangedHandler" );
}
if( expansionStateChangedHandler == null )
{
throw new ArgumentNullException( "expansionStateChangedHandler" );
}
if( isExpandedChangingHandler == null )
{
throw new ArgumentNullException( "isExpandedChangingHandler" );
}
if( isExpandedChangedHandler == null )
{
throw new ArgumentNullException( "isExpandedChangedHandler" );
}
m_itemsChangedHandler = itemsChangedHandler;
m_groupsChangedHandler = groupsChangedHandler;
m_expansionStateChangedHandler = expansionStateChangedHandler;
m_isExpandedChangingHandler = isExpandedChangingHandler;
m_isExpandedChangedHandler = isExpandedChangedHandler;
if( dataGridControl != null )
{
m_dataGridControl = new WeakReference( dataGridControl );
}
}
#region IWeakEventListener Members
#region DataGridControl Private Property
public bool ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
private DataGridControl DataGridControl
{
if( managerType == typeof( CollectionChangedEventManager ) )
get
{
NotifyCollectionChangedEventHandler handler;
m_nodesCollectionChangedEventHandlers.TryGetValue( sender, out handler );
if( handler != null )
{
handler.Invoke( sender, ( NotifyCollectionChangedEventArgs )e );
}
if( m_dataGridControl == null )
return null;
return true;
return m_dataGridControl.Target as DataGridControl;
}
return false;
}
#endregion IWeakEventListener Members
//For exception purposes only.
private readonly WeakReference m_dataGridControl; //null
#endregion
public GeneratorNode CreateGroupGeneratorNode(
CollectionViewGroup collectionViewGroup,
@ -114,12 +104,10 @@ namespace Xceed.Wpf.DataGrid
node.IsExpanded = groupConfig.InitiallyExpanded;
if( collectionViewGroup.IsBottomLevel == false )
if( !collectionViewGroup.IsBottomLevel )
{
IList<object> subItems = collectionViewGroup.GetItems();
this.RegisterNodeCollectionChanged(
( INotifyCollectionChanged )subItems,
( INotifyCollectionChanged )collectionViewGroup.GetItems(),
new NotifyCollectionChangedEventHandler( node.OnCollectionChanged ) );
node.CollectionChanged += m_groupsChangedHandler;
@ -151,10 +139,6 @@ namespace Xceed.Wpf.DataGrid
Debug.Assert( notifyCollection != null, "collection must be a INotifyCollectionChanged for CreateItemsGeneratorNode()" );
//case 113904: If the item source for the ItemsGeneratorNode is an ItemCollection, then
//check if the underlying SourceCollection is a DataGridCollectionView.
//This particular exception case is there to handle messaging quirks in the case
//of Master Detail edition. Refer to case for more details.
ItemCollection itemCollection = collection as ItemCollection;
if( itemCollection != null )
{
@ -299,9 +283,7 @@ namespace Xceed.Wpf.DataGrid
}
newNode.Next = next;
this.RegisterNodeCollectionChanged(
( INotifyCollectionChanged )newNode.Items,
new NotifyCollectionChangedEventHandler( newNode.OnCollectionChanged ) );
this.RegisterNodeCollectionChanged( ( INotifyCollectionChanged )newNode.Items, new NotifyCollectionChangedEventHandler( newNode.OnCollectionChanged ) );
newNode.CollectionChanged += m_itemsChangedHandler;
newNode.ExpansionStateChanged += m_expansionStateChangedHandler;
@ -312,18 +294,15 @@ namespace Xceed.Wpf.DataGrid
}
}
private void ConfigureHeadersFootersNotification( INotifyCollectionChanged notifyCollection, HeadersFootersGeneratorNode node )
private void ConfigureHeadersFootersNotification( INotifyCollectionChanged collection, HeadersFootersGeneratorNode node )
{
List<HeadersFootersGeneratorNode> nodeList;
bool keyFound = m_headersFootersMapping.TryGetValue( notifyCollection, out nodeList );
if( keyFound == false )
ICollection<HeadersFootersGeneratorNode> nodeList;
if( !m_headersFootersMapping.TryGetValue( collection, out nodeList ) )
{
nodeList = new List<HeadersFootersGeneratorNode>();
nodeList = new HashSet<HeadersFootersGeneratorNode>();
notifyCollection.CollectionChanged += OnHeadersFootersCollectionChanged;
m_headersFootersMapping.Add( notifyCollection, nodeList );
m_headersFootersMapping.Add( collection, nodeList );
CollectionChangedEventManager.AddListener( collection, this );
}
nodeList.Add( node );
@ -331,47 +310,24 @@ namespace Xceed.Wpf.DataGrid
private void CleanHeadersFootersNotification( HeadersFootersGeneratorNode node )
{
INotifyCollectionChanged notifyCollection = node.Items as INotifyCollectionChanged;
if( notifyCollection != null )
{
try
{
List<HeadersFootersGeneratorNode> nodeList = m_headersFootersMapping[ notifyCollection ];
var collection = node.Items as INotifyCollectionChanged;
if( collection == null )
return;
nodeList.Remove( node );
try
{
var nodeList = m_headersFootersMapping[ collection ];
nodeList.Remove( node );
if( nodeList.Count == 0 )
{
notifyCollection.CollectionChanged -= OnHeadersFootersCollectionChanged;
m_headersFootersMapping.Remove( notifyCollection );
}
}
catch( Exception e )
if( nodeList.Count == 0 )
{
throw new DataGridInternalException( e );
CollectionChangedEventManager.RemoveListener( collection, this );
m_headersFootersMapping.Remove( collection );
}
}
}
private void OnHeadersFootersCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
INotifyCollectionChanged collectionChanged = sender as INotifyCollectionChanged;
if( collectionChanged != null )
catch( Exception e )
{
try
{
List<HeadersFootersGeneratorNode> nodeList = m_headersFootersMapping[ collectionChanged ];
foreach( HeadersFootersGeneratorNode node in nodeList )
{
m_itemsChangedHandler.Invoke( node, e );
}
}
catch( Exception ex )
{
throw new DataGridInternalException( ex );
}
throw new DataGridInternalException( e.Message, e, this.DataGridControl );
}
}
@ -391,14 +347,57 @@ namespace Xceed.Wpf.DataGrid
}
}
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( managerType == typeof( CollectionChangedEventManager ) )
{
this.OnCollectionChanged( ( INotifyCollectionChanged )sender, ( NotifyCollectionChangedEventArgs )e );
return true;
}
return false;
}
private void OnCollectionChanged( INotifyCollectionChanged source, NotifyCollectionChangedEventArgs e )
{
NotifyCollectionChangedEventHandler handler;
ICollection<HeadersFootersGeneratorNode> nodeList;
if( m_nodesCollectionChangedEventHandlers.TryGetValue( source, out handler ) )
{
handler.Invoke( source, e );
}
else if( m_headersFootersMapping.TryGetValue( source, out nodeList ) )
{
try
{
foreach( var node in nodeList )
{
m_itemsChangedHandler.Invoke( node, e );
}
}
catch( Exception ex )
{
throw new DataGridInternalException( ex.Message, ex, this.DataGridControl );
}
}
}
#endregion
#region Private Fields
private readonly NotifyCollectionChangedEventHandler m_itemsChangedHandler; // = null
private readonly NotifyCollectionChangedEventHandler m_groupsChangedHandler; // = null
private readonly EventHandler<ExpansionStateChangedEventArgs> m_expansionStateChangedHandler; // = null
private readonly EventHandler m_isExpandedChangedHandler; // = null
private readonly EventHandler m_isExpandedChangingHandler; // = null
private readonly Dictionary<INotifyCollectionChanged, List<HeadersFootersGeneratorNode>> m_headersFootersMapping = new Dictionary<INotifyCollectionChanged, List<HeadersFootersGeneratorNode>>(32);
private readonly Dictionary<INotifyCollectionChanged, ICollection<HeadersFootersGeneratorNode>> m_headersFootersMapping = new Dictionary<INotifyCollectionChanged, ICollection<HeadersFootersGeneratorNode>>( 32 );
private readonly Dictionary<object, NotifyCollectionChangedEventHandler> m_nodesCollectionChangedEventHandlers = new Dictionary<object, NotifyCollectionChangedEventHandler>( 32 );
private readonly Dictionary<object, NotifyCollectionChangedEventHandler> m_nodesCollectionChangedEventHandlers = new Dictionary<object, NotifyCollectionChangedEventHandler>(32);
#endregion
}
}

27
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GeneratorNodeHelper.cs

@ -15,11 +15,9 @@
***********************************************************************************/
using System;
using System.Windows.Data;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Collections;
using System.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
@ -221,7 +219,7 @@ namespace Xceed.Wpf.DataGrid
public bool InsertAfter( GeneratorNode insert )
{
if( insert == null )
throw new DataGridInternalException();
throw new DataGridInternalException( "GeneratorNode is null." );
int insertionCount;
int chainLength;
@ -238,7 +236,7 @@ namespace Xceed.Wpf.DataGrid
// Move the current node to the last node inserted
if( !this.MoveToNextBy( chainLength ) )
throw new DataGridInternalException();
throw new DataGridInternalException( "Unable to move to the requested generator index." );
return true;
}
@ -246,7 +244,7 @@ namespace Xceed.Wpf.DataGrid
public bool InsertBefore( GeneratorNode insert )
{
if( insert == null )
throw new DataGridInternalException();
throw new DataGridInternalException( "GeneratorNode is null" );
int insertionCount;
int chainLength;
@ -779,7 +777,10 @@ namespace Xceed.Wpf.DataGrid
int endSourceDataItemIndex = -1;
if( minIndex < 0 )
throw new ArgumentException( "The minimum index must be greater than or equal to zero." );
{
DataGridException.ThrowSystemException( "The minimum index must be greater than or equal to zero.",
typeof( ArgumentException ), sourceContext.DataGridControl.Name, "minIndex" );
}
if( ( visitorType & DataGridContextVisitorType.DataGridContext ) == DataGridContextVisitorType.DataGridContext )
{
@ -893,7 +894,7 @@ namespace Xceed.Wpf.DataGrid
}
if( !processed )
throw new DataGridInternalException();
throw new DataGridInternalException( "Unable to process the visit.", sourceContext.DataGridControl );
if( visitWasStopped )
break;
@ -915,7 +916,7 @@ namespace Xceed.Wpf.DataGrid
{
bool stopVisit = false;
visitor.Visit( sourceContext, startSourceDataItemIndex, endSourceDataItemIndex, ref stopVisit );
visitWasStopped |= stopVisit;
visitWasStopped = visitWasStopped || stopVisit;
}
}
}
@ -981,7 +982,7 @@ namespace Xceed.Wpf.DataGrid
( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor(
detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped );
stopVisit |= visitWasStopped;
stopVisit = stopVisit || visitWasStopped;
if( stopVisit )
break;
@ -1049,10 +1050,10 @@ namespace Xceed.Wpf.DataGrid
{
bool visitWasStopped;
( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor(
( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor(
detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped );
stopVisit |= visitWasStopped;
stopVisit = stopVisit || visitWasStopped;
if( stopVisit )
break;

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/GroupGeneratorNode.cs

@ -230,7 +230,7 @@ namespace Xceed.Wpf.DataGrid
if( this.TotalLeafCountChanged != null )
{
this.TotalLeafCountChanged( this, new EventArgs() );
this.TotalLeafCountChanged( this, EventArgs.Empty );
}
}

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/NotifyCollectionChangedGeneratorNode.cs

@ -19,7 +19,7 @@ using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
public class NotifyCollectionChangedGeneratorNode : GeneratorNode, INotifyCollectionChanged
internal class NotifyCollectionChangedGeneratorNode : GeneratorNode, INotifyCollectionChanged
{
internal NotifyCollectionChangedGeneratorNode( GeneratorNode parent )
: base( parent )

41
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/RangeSelectionVisitor.cs

@ -23,9 +23,10 @@ namespace Xceed.Wpf.DataGrid
{
internal class RangeSelectionVisitor : IDataGridContextVisitor
{
public RangeSelectionVisitor( SelectionRange[] selectedColumns )
public RangeSelectionVisitor( SelectionRange[] selectedColumns, bool unselect )
{
m_selectedColumns = selectedColumns;
m_unselect = unselect;
}
#region IDataGridContextVisitor Members
@ -56,21 +57,40 @@ namespace Xceed.Wpf.DataGrid
if( intersectionSelectionRange.IsEmpty )
continue;
Debug.WriteLine( "Selection : Adding cell : (" + startSourceDataItemIndex.ToString() + " - " + endSourceDataItemIndex.ToString() + ") - ("
#if DEBUG
string action = ( m_unselect ) ? "Removing" : "Adding";
Debug.WriteLine( "Selection : " + action + " cell : (" + startSourceDataItemIndex.ToString() + " - " + endSourceDataItemIndex.ToString() + ") - ("
+ intersectionSelectionRange.StartIndex.ToString() + " - " + intersectionSelectionRange.EndIndex.ToString() + ")" );
selectionChangerManager.SelectCells(
sourceContext,
new SelectionCellRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null, intersectionSelectionRange ) );
#endif
var cellRange = new SelectionCellRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null, intersectionSelectionRange );
if( m_unselect )
{
selectionChangerManager.UnselectCells( sourceContext, cellRange );
}
else
{
selectionChangerManager.SelectCells( sourceContext, cellRange );
}
}
}
else
{
Debug.WriteLine( "Selection : Adding item : " + startSourceDataItemIndex.ToString() + " - " + endSourceDataItemIndex.ToString() );
#if DEBUG
string action = ( m_unselect ) ? "Removing" : "Adding";
Debug.WriteLine( "Selection : " + action + " Adding item : " + startSourceDataItemIndex.ToString() + " - " + endSourceDataItemIndex.ToString() );
#endif
var itemRange = new SelectionRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null );
selectionChangerManager.SelectItems(
sourceContext,
new SelectionRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null ) );
if( m_unselect )
{
selectionChangerManager.UnselectItems( sourceContext, itemRange );
}
else
{
selectionChangerManager.SelectItems( sourceContext, itemRange );
}
}
}
@ -97,5 +117,6 @@ namespace Xceed.Wpf.DataGrid
#endregion
private SelectionRange[] m_selectedColumns;
private bool m_unselect;
}
}

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/SelectAllVisitor.cs

@ -67,7 +67,7 @@ namespace Xceed.Wpf.DataGrid
else
{
HashedLinkedList<ColumnBase> columnsByVisiblePosition = sourceContext.ColumnsByVisiblePosition;
SelectedItemsStorage selectedColumnStore = new SelectedItemsStorage( null, 8 );
SelectedItemsStorage selectedColumnStore = new SelectedItemsStorage( null );
SelectionRange fullColumnRange = new SelectionRange( 0, columnsByVisiblePosition.Count - 1 );
selectedColumnStore.Add( new SelectionRangeWithItems( fullColumnRange, null ) );
int index = 0;

72
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(Generator)/VisibilityChangingEventManager.cs

@ -0,0 +1,72 @@
/*************************************************************************************
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 class VisibilityChangingEventManager : WeakEventManager
{
private VisibilityChangingEventManager()
{
}
public static void AddListener( ColumnCollection source, IWeakEventListener listener )
{
CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( ColumnCollection source, IWeakEventListener listener )
{
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var columnCollection = ( ColumnCollection )source;
columnCollection.ColumnVisibilityChanging += new EventHandler( this.OnColumnVisibilityChanging );
}
protected override void StopListening( object source )
{
var columnCollection = ( ColumnCollection )source;
columnCollection.ColumnVisibilityChanging -= new EventHandler( this.OnColumnVisibilityChanging );
}
private static VisibilityChangingEventManager CurrentManager
{
get
{
var managerType = typeof( VisibilityChangingEventManager );
var currentManager = ( VisibilityChangingEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new VisibilityChangingEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
private void OnColumnVisibilityChanging( object sender, EventArgs args )
{
this.DeliverEvent( sender, args );
}
}
}

39
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(enums)/AutoScrollCurrentItemSourceTriggersEnum.cs

@ -0,0 +1,39 @@
/*************************************************************************************
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
{
[Flags]
internal enum AutoScrollCurrentItemSourceTriggers
{
None = 0x0000,
Navigation = 0x0001,
Editing = 0x0002,
FocusChanged = 0x0004,
SelectionChanged = 0x0008,
SortChanged = 0x0010,
GroupChanged = 0x0020,
CurrentItemChanged = 0x0040,
CurrentColumnChanged = 0x0080,
CollectionViewCurrentItemChanged = 0x0100,
ColumnsCollectionChanged = 0x0200,
ItemsSourceChanged = 0x0400,
ViewChanged = 0x0800,
ThemeChanged = 0x1000,
}
}

37
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(enums)/AutoScrollCurrentItemTriggersEnum.cs

@ -0,0 +1,37 @@
/*************************************************************************************
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
{
// Defines the events that trigger the bring into view for the current item.
[Flags]
public enum AutoScrollCurrentItemTriggers
{
None = 0x00,
CurrentChanged = 0x01,
ItemsSourceChanged = 0x02,
FocusChanged = 0x04,
SortChanged = 0x08,
GroupChanged = 0x10,
ViewChanged = 0x20,
ThemeChanged = 0x40,
All = ~0x00
}
}

3
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(enums)/DistinctValuesConstraintEnum.cs

@ -23,6 +23,7 @@ namespace Xceed.Wpf.DataGrid
public enum DistinctValuesConstraint
{
All,
Filtered
Filtered,
FilteredWithAllFilters
}
}

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AssemblyVersionInfo.cs

@ -19,7 +19,7 @@
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "2.3";
public const string BaseVersion = "2.4";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion + ".0.0";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]

34
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AutoResetFlag.cs

@ -0,0 +1,34 @@
/*************************************************************************************
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
{
internal abstract class AutoResetFlag
{
#region IsSet Property
public abstract bool IsSet
{
get;
}
#endregion
public abstract IDisposable Set();
}
}

156
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AutoResetFlagFactory.cs

@ -0,0 +1,156 @@
/*************************************************************************************
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.Threading;
namespace Xceed.Wpf.DataGrid
{
internal static class AutoResetFlagFactory
{
public static AutoResetFlag Create()
{
return AutoResetFlagFactory.Create( true );
}
public static AutoResetFlag Create( bool singleSet )
{
if( singleSet )
return new SingleAutoResetFlag();
return new MultiAutoResetFlag();
}
#region IAutoResetFlag Private Interface
private interface IAutoResetFlag
{
void Set();
void Unset();
}
#endregion
#region ResetFlagDisposable Private Class
private sealed class ResetFlagDisposable : IDisposable
{
internal ResetFlagDisposable( IAutoResetFlag target )
{
Debug.Assert( target != null );
m_target = target;
m_target.Set();
}
private void Dispose( bool disposing )
{
var target = m_target;
// The disposed method has already been called at least once.
if( Interlocked.CompareExchange<IAutoResetFlag>( ref m_target, null, target ) == null )
return;
Debug.Assert( m_target == null );
Debug.Assert( target != null );
// We can only get here if this is the first call to Dispose.
target.Unset();
}
void IDisposable.Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
~ResetFlagDisposable()
{
this.Dispose( false );
}
private IAutoResetFlag m_target;
}
#endregion
#region SingleAutoResetFlag Private Class
private sealed class SingleAutoResetFlag : AutoResetFlag, IAutoResetFlag
{
public override bool IsSet
{
get
{
return ( Interlocked.CompareExchange( ref m_isSet, null, null ) == this );
}
}
public override IDisposable Set()
{
return new ResetFlagDisposable( this );
}
void IAutoResetFlag.Set()
{
if( Interlocked.CompareExchange( ref m_isSet, this, null ) != null )
throw new InvalidOperationException( "The flag is already set." );
}
void IAutoResetFlag.Unset()
{
Interlocked.CompareExchange( ref m_isSet, null, this );
}
private object m_isSet; //null
}
#endregion
#region MultiAutoResetFlag Private Class
private sealed class MultiAutoResetFlag : AutoResetFlag, IAutoResetFlag
{
public override bool IsSet
{
get
{
return ( m_count > 0 );
}
}
public override IDisposable Set()
{
return new ResetFlagDisposable( this );
}
void IAutoResetFlag.Set()
{
Interlocked.Increment( ref m_count );
}
void IAutoResetFlag.Unset()
{
Interlocked.Decrement( ref m_count );
}
private int m_count; //0
}
#endregion
}
}

105
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/AutoScrollCurrentItemSourceTriggersRestrictions.cs

@ -0,0 +1,105 @@
/*************************************************************************************
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;
namespace Xceed.Wpf.DataGrid
{
internal sealed class AutoScrollCurrentItemSourceTriggersRestrictions
{
#region Restrictions Property
internal AutoScrollCurrentItemSourceTriggers Restrictions
{
get
{
var result = AutoScrollCurrentItemSourceTriggers.None;
for( int i = m_restrictions.Count - 1; i >= 0; i-- )
{
var item = m_restrictions[ i ].Target as SingleRestriction;
if( item != null )
{
result |= item.Value;
}
else
{
m_restrictions.RemoveAt( i );
}
}
return result;
}
}
#endregion
internal IDisposable SetRestriction( AutoScrollCurrentItemSourceTriggers value )
{
var disposable = new SingleRestriction( value );
m_restrictions.Add( new WeakReference( disposable ) );
return disposable;
}
#region Private Fields
private readonly List<WeakReference> m_restrictions = new List<WeakReference>();
#endregion
#region SingleRestriction Private Class
private sealed class SingleRestriction : IDisposable
{
internal SingleRestriction( AutoScrollCurrentItemSourceTriggers value )
{
m_value = value;
}
internal AutoScrollCurrentItemSourceTriggers Value
{
get
{
return m_value;
}
}
void IDisposable.Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
private void Dispose( bool disposing )
{
m_value = AutoScrollCurrentItemSourceTriggers.None;
}
~SingleRestriction()
{
this.Dispose( false );
}
private AutoScrollCurrentItemSourceTriggers m_value;
}
#endregion
}
}

6
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Automation/ColumnManagerCellAutomationPeer.cs

@ -141,7 +141,11 @@ namespace Xceed.Wpf.DataGrid.Automation
void ITransformProvider.Resize( double width, double height )
{
this.Owner.DoResize( width );
ColumnBase parentColumn = this.Owner.ParentColumn;
if( parentColumn == null )
return;
this.Owner.DoResize( width, parentColumn );
}
void ITransformProvider.Rotate( double degrees )

78
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Automation/DataGridGroupAutomationPeer.cs

@ -15,24 +15,28 @@
***********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Data;
using System.Windows;
using System.Windows.Controls;
using System.Collections;
using System.Collections.ObjectModel;
using System.Windows.Automation;
using System.Globalization;
using System.Diagnostics;
using Xceed.Wpf.DataGrid.Utils;
namespace Xceed.Wpf.DataGrid.Automation
{
public class DataGridGroupAutomationPeer : AutomationPeer, IExpandCollapseProvider, IItemContainerProvider
public class DataGridGroupAutomationPeer : AutomationPeer, IExpandCollapseProvider, IItemContainerProvider, IWeakEventListener
{
#region Static Fields
private static readonly string GroupIsExpandedPropertyName = PropertyHelper.GetPropertyName( ( Group g ) => g.IsExpanded );
#endregion
public DataGridGroupAutomationPeer( Group uiGroupOwner )
{
if( uiGroupOwner == null )
@ -41,6 +45,8 @@ namespace Xceed.Wpf.DataGrid.Automation
m_uiGroupOwner = uiGroupOwner;
m_dataChildren = new Hashtable( 0 );
m_headerFooterChildren = new Hashtable( 0 );
PropertyChangedEventManager.AddListener( uiGroupOwner, this, DataGridGroupAutomationPeer.GroupIsExpandedPropertyName );
}
#region Owner Property
@ -53,6 +59,8 @@ namespace Xceed.Wpf.DataGrid.Automation
}
}
private readonly Group m_uiGroupOwner;
#endregion
public override object GetPattern( PatternInterface patternInterface )
@ -174,7 +182,7 @@ namespace Xceed.Wpf.DataGrid.Automation
for( int i = 0; i < itemsCount; i++ )
{
Object item = items[ i ];
object item = items[ i ];
CollectionViewGroup collectionViewGroup = item as CollectionViewGroup;
if( collectionViewGroup == null )
@ -372,7 +380,27 @@ namespace Xceed.Wpf.DataGrid.Automation
throw new NotSupportedException();
}
static internal void AddHeaderPeer(
private void OnOwnerPropertyChanged( object sender, PropertyChangedEventArgs e )
{
if( !AutomationPeer.ListenerExists( AutomationEvents.PropertyChanged ) )
return;
Debug.Assert( sender == this.Owner );
if( string.IsNullOrEmpty( e.PropertyName ) || ( e.PropertyName == DataGridGroupAutomationPeer.GroupIsExpandedPropertyName ) )
{
if( this.Owner.IsExpanded )
{
this.RaisePropertyChangedEvent( ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, ExpandCollapseState.Collapsed, ExpandCollapseState.Expanded );
}
else
{
this.RaisePropertyChangedEvent( ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, ExpandCollapseState.Expanded, ExpandCollapseState.Collapsed );
}
}
}
internal static void AddHeaderPeer(
DataGridContext dataGridContext,
HeadersFootersGeneratorNode node,
List<AutomationPeer> list,
@ -411,7 +439,7 @@ namespace Xceed.Wpf.DataGrid.Automation
}
}
static internal void AddFooterPeer(
internal static void AddFooterPeer(
DataGridContext dataGridContext,
HeadersFootersGeneratorNode node,
List<AutomationPeer> list,
@ -648,8 +676,30 @@ namespace Xceed.Wpf.DataGrid.Automation
#endregion
private Group m_uiGroupOwner;
#region IWeakEventListener Members
bool IWeakEventListener.ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( typeof( PropertyChangedEventManager ) == managerType )
{
if( sender == this.Owner )
{
this.OnOwnerPropertyChanged( sender, ( PropertyChangedEventArgs )e );
}
return true;
}
return false;
}
#endregion
#region Private Fields
private Hashtable m_dataChildren;
private Hashtable m_headerFooterChildren;
#endregion
}
}

20
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Automation/HeaderFooterItemAutomationPeer.cs

@ -16,13 +16,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Automation.Peers;
using System.Windows;
using System.Globalization;
using System.Diagnostics;
using System.Windows.Media;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;
@ -312,21 +310,17 @@ namespace Xceed.Wpf.DataGrid.Automation
internal UIElement GetWrapper()
{
HeaderFooterItem headerFooterItem = m_owner as HeaderFooterItem;
if( headerFooterItem == null )
{
headerFooterItem =
m_dataGridContext.GetContainerFromItem( m_owner ) as HeaderFooterItem;
headerFooterItem = m_dataGridContext.GetContainerFromItem( m_owner ) as HeaderFooterItem;
}
if( headerFooterItem == null )
return null;
IDataGridItemContainer dataGridItemContainer = HeaderFooterItem.FindIDataGridItemContainerInChildren(
headerFooterItem, headerFooterItem.AsVisual() );
if( dataGridItemContainer != null )
return dataGridItemContainer as UIElement;
var container = headerFooterItem.GetTemplatedDescendantDataGridItemContainers().FirstOrDefault();
if( container != null )
return container as UIElement;
return headerFooterItem;
}

975
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Cell.cs

File diff suppressed because it is too large

74
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/CellContentStringFormatChangedEventManager.cs

@ -0,0 +1,74 @@
/*************************************************************************************
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 class CellContentStringFormatChangedEventManager : WeakEventManager
{
private CellContentStringFormatChangedEventManager()
{
}
public static void AddListener( ColumnBase source, IWeakEventListener listener )
{
CellContentStringFormatChangedEventManager.CurrentManager.ProtectedAddListener( source, listener );
}
public static void RemoveListener( ColumnBase source, IWeakEventListener listener )
{
CellContentStringFormatChangedEventManager.CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var column = ( ColumnBase )source;
column.CellContentStringFormatChanged += new EventHandler( this.OnCellContentStringFormatChanged );
}
protected override void StopListening( object source )
{
var column = ( ColumnBase )source;
column.CellContentStringFormatChanged -= new EventHandler( this.OnCellContentStringFormatChanged );
}
private static CellContentStringFormatChangedEventManager CurrentManager
{
get
{
var managerType = typeof( CellContentStringFormatChangedEventManager );
var currentManager = ( CellContentStringFormatChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new CellContentStringFormatChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
private void OnCellContentStringFormatChanged( object sender, EventArgs args )
{
this.DeliverEvent( sender, args );
}
}
}

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridCheckBox.cs → ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/CheckBox.cs

@ -83,6 +83,8 @@ namespace Xceed.Wpf.DataGrid
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
ChildCheckBox.Background = new System.Windows.Media.SolidColorBrush( System.Windows.Media.Colors.Blue );
}
public static readonly RoutedEvent CheckedEvent;

75
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ChildColumnVisibilityChangedEventManager.cs

@ -0,0 +1,75 @@
/*************************************************************************************
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 class ChildColumnVisibilityChangedEventManager : WeakEventManager
{
private ChildColumnVisibilityChangedEventManager()
{
}
internal static void AddListener( ObservableColumnCollection source, IWeakEventListener listener )
{
CurrentManager.ProtectedAddListener( source, listener );
}
internal static void RemoveListener( ObservableColumnCollection source, IWeakEventListener listener )
{
CurrentManager.ProtectedRemoveListener( source, listener );
}
protected override void StartListening( object source )
{
var columnCollection = ( ObservableColumnCollection )source;
columnCollection.ColumnVisibilityChanged += new EventHandler( this.OnColumnVisibilityChanged );
}
protected override void StopListening( object source )
{
var columnCollection = ( ObservableColumnCollection )source;
columnCollection.ColumnVisibilityChanged -= new EventHandler( this.OnColumnVisibilityChanged );
}
private static ChildColumnVisibilityChangedEventManager CurrentManager
{
get
{
Type managerType = typeof( ChildColumnVisibilityChangedEventManager );
ChildColumnVisibilityChangedEventManager currentManager = ( ChildColumnVisibilityChangedEventManager )WeakEventManager.GetCurrentManager( managerType );
if( currentManager == null )
{
currentManager = new ChildColumnVisibilityChangedEventManager();
WeakEventManager.SetCurrentManager( managerType, currentManager );
}
return currentManager;
}
}
private void OnColumnVisibilityChanged( object sender, EventArgs args )
{
this.DeliverEvent( sender, args );
}
}
}

9
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Column.GenericContentTemplateSelectorResources.xaml

@ -20,9 +20,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.DataGrid"
xmlns:conv="clr-namespace:Xceed.Wpf.DataGrid.Converters"
xmlns:markup="clr-namespace:Xceed.Wpf.DataGrid.Markup"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:sxml="clr-namespace:System.Xml;assembly=System.Xml">
xmlns:s="clr-namespace:System;assembly=mscorlib">
<conv:ImageConverter x:Key="imageConverter" />
<conv:NullToBooleanConverter x:Key="nullToBooleanConverter" />
@ -64,7 +62,10 @@
</DataTemplate>
<DataTemplate x:Key="foreignKeyDistinctValueItemDefaultContentTemplate">
<DataTemplate x:Key="commonDefaultContentTemplate">
<TextBlock Text="{Binding Mode=OneWay}" />
</DataTemplate>
</ResourceDictionary>

132
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Column.cs

@ -15,20 +15,11 @@
***********************************************************************************/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Media;
using Xceed.Wpf.DataGrid.ValidationRules;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;
using Xceed.Utils.Collections;
using System.Collections.Specialized;
using Xceed.Wpf.DataGrid.Converters;
using System.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
@ -42,13 +33,18 @@ namespace Xceed.Wpf.DataGrid
[Obsolete( "The DisplayMemberBinding property is obsolete and has been replaced by the DisplayMemberBindingInfo property.", false )]
public Column( string fieldName, object title, BindingBase displayMemberBinding )
: base( fieldName, title )
{
this.SetDisplayMemberBinding( displayMemberBinding );
}
internal static Column Create( string fieldName, object title, BindingBase displayMemberBinding )
{
// Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618
this.DisplayMemberBinding = displayMemberBinding;
var column = new Column( fieldName, title, displayMemberBinding );
#pragma warning restore 618
return column;
}
#region DisplayMemberBinding Property
@ -67,14 +63,33 @@ namespace Xceed.Wpf.DataGrid
set
{
if( value != m_displayMemberBinding )
{
m_displayMemberBinding = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "DisplayMemberBinding" ) );
}
if( value == m_displayMemberBinding )
return;
m_displayMemberBinding = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "DisplayMemberBinding" ) );
}
}
internal BindingBase GetDisplayMemberBinding()
{
// Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618
var value = this.DisplayMemberBinding;
#pragma warning restore 618
return value;
}
internal void SetDisplayMemberBinding( BindingBase value )
{
// Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618
this.DisplayMemberBinding = value;
#pragma warning restore 618
}
#endregion DisplayMemberBinding Property
#region DisplayMemberBindingInfo Property
@ -93,7 +108,6 @@ namespace Xceed.Wpf.DataGrid
if( value != m_displayMemberBindingInfo )
{
m_displayMemberBindingInfo = value;
m_displayMemberBinding = m_displayMemberBindingInfo.GetBinding();
this.OnPropertyChanged( new PropertyChangedEventArgs( "DisplayMemberBindingInfo" ) );
@ -195,7 +209,9 @@ namespace Xceed.Wpf.DataGrid
"ForeignKeyConfiguration",
typeof( ForeignKeyConfiguration ),
typeof( Column ),
new FrameworkPropertyMetadata( null, new PropertyChangedCallback( Column.OnForeignKeyConfigurationChanged ) ) );
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( Column.OnForeignKeyConfigurationChanged ) ) );
public ForeignKeyConfiguration ForeignKeyConfiguration
{
@ -228,10 +244,10 @@ namespace Xceed.Wpf.DataGrid
private void RaiseForeignKeyConfigurationChanged()
{
var handler = this.ForeignKeyConfigurationChanged;
if( handler != null )
{
handler( this, EventArgs.Empty );
}
if( handler == null )
return;
handler.Invoke( this, EventArgs.Empty );
}
#endregion
@ -242,24 +258,38 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return m_bindingAutoCreated;
return m_isBindingAutoCreated;
}
set
{
m_bindingAutoCreated = value;
m_isBindingAutoCreated = value;
}
}
private bool m_isBindingAutoCreated; //false
#endregion
#region IsBoundToDataGridUnboundItemProperty Property
internal bool IsBoundToDataGridUnboundItemProperty
{
get;
set;
get
{
return m_isBoundToDataGridUnboundItemProperty;
}
set
{
if( value == m_isBoundToDataGridUnboundItemProperty )
return;
m_isBoundToDataGridUnboundItemProperty = value;
this.ResetDefaultCellRecyclingGroup();
}
}
private bool m_isBoundToDataGridUnboundItemProperty; //false
#endregion
#if DEBUG
@ -274,6 +304,48 @@ namespace Xceed.Wpf.DataGrid
}
#endif
private bool m_bindingAutoCreated; // = false
internal override object CreateDefaultCellRecyclingGroup()
{
var key = base.CreateDefaultCellRecyclingGroup();
if( !this.IsBoundToDataGridUnboundItemProperty )
return key;
return new UnboundColumnCellRecyclingGroupKey( key );
}
#region UnboundColumnCellRecyclingGroupKey Private Nested Type
private sealed class UnboundColumnCellRecyclingGroupKey
{
internal UnboundColumnCellRecyclingGroupKey( object key )
{
m_key = key;
}
public override int GetHashCode()
{
if( m_key != null )
return m_key.GetHashCode();
return 0;
}
public override bool Equals( object obj )
{
UnboundColumnCellRecyclingGroupKey key = obj as UnboundColumnCellRecyclingGroupKey;
if( key == null )
return false;
if( key == this )
return true;
return object.Equals( key.m_key, m_key );
}
private readonly object m_key;
}
#endregion
}
}

116
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnAddGroupCommand.cs

@ -0,0 +1,116 @@
/*************************************************************************************
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.ObjectModel;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
internal abstract class ColumnAddGroupCommand : ColumnGroupCommand
{
#region GroupDescriptions Protected Property
protected abstract ObservableCollection<GroupDescription> GroupDescriptions
{
get;
}
#endregion
public bool CanExecute( ColumnBase column )
{
return this.CanExecute( column, -1 );
}
public bool CanExecute( ColumnBase column, int index )
{
return ( column != null )
&& ( this.CanExecuteCore( column, index ) );
}
public void Execute( ColumnBase column )
{
this.Execute( column, -1 );
}
public void Execute( ColumnBase column, int index )
{
if( !this.CanExecute( column, index ) )
return;
this.ExecuteCore( column, index );
}
protected virtual string GetColumnName( ColumnBase column )
{
return column.FieldName;
}
protected virtual GroupDescription GetGroupDescription( ColumnBase column )
{
return column.GroupDescription;
}
protected virtual GroupConfiguration GetGroupConfiguration( ColumnBase column )
{
return column.GroupConfiguration;
}
protected virtual bool CanExecuteCore( ColumnBase column, int index )
{
return ( this.GroupDescriptions != null )
&& ( !string.IsNullOrEmpty( this.GetColumnName( column ) ) );
}
protected virtual void ExecuteCore( ColumnBase column, int index )
{
var groupDescriptions = this.GroupDescriptions;
if( groupDescriptions == null )
return;
GroupDescription groupDescription = this.GetGroupDescription( column );
if( groupDescription == null )
{
groupDescription = new DataGridGroupDescription( this.GetColumnName( column ) );
}
var dataGridGroupDescription = groupDescription as DataGridGroupDescription;
if( ( dataGridGroupDescription != null ) && ( dataGridGroupDescription.GroupConfiguration == null ) )
{
dataGridGroupDescription.GroupConfiguration = this.GetGroupConfiguration( column );
}
if( index < 0 )
{
groupDescriptions.Add( groupDescription );
}
else
{
groupDescriptions.Insert( index, groupDescription );
}
}
protected sealed override bool CanExecuteImpl( object parameter )
{
return this.CanExecute( parameter as ColumnBase );
}
protected sealed override void ExecuteImpl( object parameter )
{
this.Execute( parameter as ColumnBase );
}
}
}

1127
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnBase.cs

File diff suppressed because it is too large

269
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnCollection.cs

@ -15,17 +15,12 @@
***********************************************************************************/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.ComponentModel;
using System.Windows.Threading;
using System.Threading;
namespace Xceed.Wpf.DataGrid
{
@ -39,20 +34,6 @@ namespace Xceed.Wpf.DataGrid
this.ParentDetailConfiguration = parentDetailConfiguration;
}
public ColumnBase this[ string fieldName ]
{
get
{
ColumnBase column = null;
m_fieldNameToColumns.TryGetValue( fieldName, out column );
return column;
}
}
// PUBLIC PROPERTIES
#region MainColumn Property
public ColumnBase MainColumn
@ -75,11 +56,9 @@ namespace Xceed.Wpf.DataGrid
#endregion
// INTERNAL PROPERTIES
#region FieldNameToColumnDictionary Property
internal Dictionary<string,ColumnBase> FieldNameToColumnDictionary
internal Dictionary<string, ColumnBase> FieldNameToColumnDictionary
{
get
{
@ -97,7 +76,6 @@ namespace Xceed.Wpf.DataGrid
{
return m_dataGridControl;
}
set
{
m_dataGridControl = value;
@ -125,86 +103,58 @@ namespace Xceed.Wpf.DataGrid
#region ProcessingVisibleColumnsUpdate Property
internal bool ProcessingVisibleColumnsUpdate
internal AutoResetFlag ProcessingVisibleColumnsUpdate
{
get
{
return m_processingVisibleColumnsUpdate;
}
set
{
m_processingVisibleColumnsUpdate = value;
}
}
private bool m_processingVisibleColumnsUpdate; // = false
private readonly AutoResetFlag m_processingVisibleColumnsUpdate = AutoResetFlagFactory.Create();
#endregion
#region VisibleColumnsUpdateDelayed Property
internal bool VisibleColumnsUpdateDelayed
public ColumnBase this[ string fieldName ]
{
get
{
return m_visibleColumnsUpdateDelayed;
}
set
{
m_visibleColumnsUpdateDelayed = value;
}
}
private bool m_visibleColumnsUpdateDelayed; // = false
#endregion
ColumnBase column = null;
#region Column Event Handlers
m_fieldNameToColumns.TryGetValue( fieldName, out column );
private void RegisterColumnChangedEvent( ColumnBase column )
{
column.TitleChanged += new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged += new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged += new EventHandler( this.OnColumnVisibilityChanged );
column.VisibleChanged += new EventHandler( this.OnColumnVisibilityChanged );
return column;
}
}
private void UnregisterColumnChangedEvent( ColumnBase column )
{
column.TitleChanged -= new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged -= new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged -= new EventHandler( this.OnColumnVisibilityChanged );
column.VisibleChanged -= new EventHandler( this.OnColumnVisibilityChanged );
}
#region IsDeferVisibleColumnsUpdate Internal Property
private void OnColumnVisibilityChanged( object sender, EventArgs e )
internal bool IsDeferVisibleColumnsUpdate
{
if( this.ColumnVisibilityChanged != null )
this.ColumnVisibilityChanged( this, new WrappedEventEventArgs( sender, e ) );
get
{
return ( m_deferVisibleColumnsUpdateCount > 0 );
}
}
internal event EventHandler ColumnVisibilityChanged;
#endregion
private void OnColumnValueChanged( object sender, EventArgs e )
public IDisposable DeferVisibleColumnsUpdate()
{
return new DeferedColumnsVisibleUpdateDisposable( this );
}
#endregion Column Event Handlers
// PROTECTED METHODS
protected override void RemoveItem( int index )
{
ColumnBase column = this[ index ];
if( column != null )
{
m_fieldNameToColumns.Remove( column.FieldName );
this.UnregisterColumnChangedEvent( column );
column.DetachFromContainingCollection();
m_fieldNameToColumns.Remove( column.FieldName );
}
base.RemoveItem( index );
@ -215,17 +165,15 @@ namespace Xceed.Wpf.DataGrid
if( item != null )
{
if( ( string.IsNullOrEmpty( item.FieldName ) == true ) && ( !DesignerProperties.GetIsInDesignMode( item ) ) )
{
throw new ArgumentException( "A column must have a fieldname.", "item" );
}
item.AttachToContainingCollection( this );
if( m_fieldNameToColumns.ContainsKey( item.FieldName ) )
throw new DataGridException( "A column with same field name already exists in collection." );
m_fieldNameToColumns.Add( item.FieldName, item );
item.AttachToContainingCollection( this );
this.RegisterColumnChangedEvent( item );
}
@ -249,37 +197,37 @@ namespace Xceed.Wpf.DataGrid
protected override void SetItem( int index, ColumnBase item )
{
if( ( item != null ) && ( string.IsNullOrEmpty( item.FieldName ) == true ) )
{
throw new ArgumentException( "A column must have a fieldname.", "item" );
}
if( m_fieldNameToColumns.ContainsKey( item.FieldName ) )
throw new DataGridException( "A column with same field name already exists in collection." );
ColumnBase column = this[ index ];
if( ( column != null ) && ( column != item ) )
{
m_fieldNameToColumns.Remove( column.FieldName );
this.UnregisterColumnChangedEvent( column );
column.DetachFromContainingCollection();
m_fieldNameToColumns.Remove( column.FieldName );
}
if( ( item != null ) && ( column != item ) )
{
m_fieldNameToColumns.Add( item.FieldName, item );
item.AttachToContainingCollection( this );
this.RegisterColumnChangedEvent( item );
m_fieldNameToColumns.Add( item.FieldName, item );
}
base.SetItem( index, item );
}
protected override void OnCollectionChanged( System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
protected override void OnCollectionChanged( NotifyCollectionChangedEventArgs e )
{
if( ( m_columnAdditionMessagesDeferedCount > 0 )
&& ( e.Action == NotifyCollectionChangedAction.Add ) && ( e.NewStartingIndex == ( this.Count - e.NewItems.Count ) ) )
if( ( m_columnAdditionMessagesDeferedCount > 0 ) && ( e.Action == NotifyCollectionChangedAction.Add ) && ( e.NewStartingIndex == ( this.Count - e.NewItems.Count ) ) )
{
if( m_deferedColumnAdditionMessageStartIndex == -1 )
{
@ -297,8 +245,6 @@ namespace Xceed.Wpf.DataGrid
}
}
// INTERNAL METHODS
internal IDisposable DeferColumnAdditionMessages()
{
return new DeferedColumnAdditionMessageDisposable( this );
@ -314,11 +260,19 @@ namespace Xceed.Wpf.DataGrid
internal event EventHandler VisibleColumnsUpdating;
internal void NotifyVisibleColumnsUpdated()
internal void DispatchNotifyVisibleColumnsUpdated()
{
if( this.VisibleColumnsUpdated != null )
//In all cases, make sure the ColumnVitualizationManager is flaged as outdate, but prevent to make updates to FixedCellPanels right away.
this.NotifyVisibleColumnsUpdated( true );
//In all cases, make sure we dipatch an operation to update the FixedCellPanels in case the update is not tiggered by other means (e.g. no scrolling, no DataRow in the grid).
if( m_visibleColumnsUpdatedDispatcherOperation == null && m_dataGridControl != null )
{
this.VisibleColumnsUpdated( this, EventArgs.Empty );
////# Will be null at first in the case of a detail, so process directly
//This permits less updates = better performance.
m_visibleColumnsUpdatedDispatcherOperation =
m_dataGridControl.Dispatcher.BeginInvoke( DispatcherPriority.Render, new Action<bool>( this.NotifyVisibleColumnsUpdated ), false );
}
}
@ -354,10 +308,83 @@ namespace Xceed.Wpf.DataGrid
internal event ColumnActualWidthChangedHandler ActualWidthChanged;
internal event EventHandler ColumnVisibilityChanging;
internal event EventHandler ColumnVisibilityChanged;
private void RegisterColumnChangedEvent( ColumnBase column )
{
column.PropertyChanged += new PropertyChangedEventHandler( this.OnColumnPropertyChanged );
column.TitleChanged += new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanging += new EventHandler( this.OnColumnVisibilityChanging );
column.VisiblePositionChanged += new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged += new EventHandler( this.OnColumnVisibilityChanged );
column.VisibleChanged += new EventHandler( this.OnColumnVisibilityChanged );
}
private void UnregisterColumnChangedEvent( ColumnBase column )
{
column.PropertyChanged -= new PropertyChangedEventHandler( this.OnColumnPropertyChanged );
column.TitleChanged -= new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanging -= new EventHandler( this.OnColumnVisibilityChanging );
column.VisiblePositionChanged -= new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged -= new EventHandler( this.OnColumnVisibilityChanged );
column.VisibleChanged -= new EventHandler( this.OnColumnVisibilityChanged );
}
private void OnColumnPropertyChanged( object sender, PropertyChangedEventArgs e )
{
if( string.IsNullOrEmpty( e.PropertyName ) || e.PropertyName == "IsMainColumn" )
{
// The ColumnBase.IsMainColumn property impacts the columns visibility when details are flatten.
var dataGridControl = this.DataGridControl;
if( ( dataGridControl != null ) && ( dataGridControl.AreDetailsFlatten ) )
{
this.OnColumnVisibilityChanged( sender, EventArgs.Empty );
}
}
}
private void OnColumnVisibilityChanging( object sender, EventArgs e )
{
if( this.ColumnVisibilityChanging != null )
{
this.ColumnVisibilityChanging( this, new WrappedEventEventArgs( sender, e ) );
}
}
private void OnColumnVisibilityChanged( object sender, EventArgs e )
{
if( this.ColumnVisibilityChanged != null )
{
this.ColumnVisibilityChanged( this, new WrappedEventEventArgs( sender, e ) );
}
}
private void OnColumnValueChanged( object sender, EventArgs e )
{
ColumnBase column = ( ColumnBase )sender;
}
private void NotifyVisibleColumnsUpdated( bool onlyIncrementFlag )
{
if( this.VisibleColumnsUpdated != null )
{
this.VisibleColumnsUpdated( this, new VisibleColumnsUpdatedEventArgs( onlyIncrementFlag ) );
}
//If only updating the flag, don't reset the DispatcherOperation, since if it is still alive, another call will be made which will reset it.
if( onlyIncrementFlag )
return;
m_visibleColumnsUpdatedDispatcherOperation = null;
}
private int m_columnAdditionMessagesDeferedCount = 0;
private int m_deferVisibleColumnsUpdateCount = 0;
private int m_deferedColumnAdditionMessageStartIndex = -1;
private List<ColumnBase> m_deferedColumns = new List<ColumnBase>();
private Dictionary<string, ColumnBase> m_fieldNameToColumns = new Dictionary<string, ColumnBase>(); // To optimize indexing speed for FieldName
private DispatcherOperation m_visibleColumnsUpdatedDispatcherOperation;
private sealed class DeferedColumnAdditionMessageDisposable : IDisposable
{
@ -374,6 +401,14 @@ namespace Xceed.Wpf.DataGrid
#region IDisposable Members
public void Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
#endregion
private void Dispose( bool disposing )
{
m_columns.m_columnAdditionMessagesDeferedCount--;
@ -389,8 +424,49 @@ namespace Xceed.Wpf.DataGrid
}
}
~DeferedColumnAdditionMessageDisposable()
{
this.Dispose( false );
}
private ColumnCollection m_columns; // = null
}
private sealed class DeferedColumnsVisibleUpdateDisposable : IDisposable
{
public DeferedColumnsVisibleUpdateDisposable( ColumnCollection columns )
{
if( columns == null )
throw new ArgumentNullException( "columns" );
m_columns = columns;
Interlocked.Increment( ref m_columns.m_deferVisibleColumnsUpdateCount );
}
#region IDisposable Members
public void Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
#endregion
private void Dispose( bool disposing )
{
if( Interlocked.Decrement( ref m_columns.m_deferVisibleColumnsUpdateCount ) != 0 )
return;
m_columns.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
~DeferedColumnsVisibleUpdateDisposable()
{
this.Dispose( false );
}
private ColumnCollection m_columns; // = null
}
@ -408,8 +484,17 @@ namespace Xceed.Wpf.DataGrid
this.WrappedEventArgs = eventArgs;
}
public object WrappedSender { get; private set; }
public object WrappedEventArgs { get; private set; }
public object WrappedSender
{
get;
private set;
}
public object WrappedEventArgs
{
get;
private set;
}
}
}
}

62
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnCommand.cs

@ -0,0 +1,62 @@
/*************************************************************************************
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.Input;
namespace Xceed.Wpf.DataGrid
{
internal abstract class ColumnCommand : ICommand
{
#region Validation Methods
protected static void ThrowIfNull( object value, string paramName )
{
if( value == null )
throw new ArgumentNullException( paramName );
}
#endregion
protected abstract bool CanExecuteImpl( object parameter );
protected abstract void ExecuteImpl( object parameter );
#region ICommand Members
event EventHandler ICommand.CanExecuteChanged
{
add
{
}
remove
{
}
}
bool ICommand.CanExecute( object parameter )
{
return this.CanExecuteImpl( parameter );
}
void ICommand.Execute( object parameter )
{
this.ExecuteImpl( parameter );
}
#endregion
}
}

26
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnGroupCommand.cs

@ -0,0 +1,26 @@
/*************************************************************************************
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.Input;
namespace Xceed.Wpf.DataGrid
{
internal abstract class ColumnGroupCommand : ColumnCommand
{
}
}

580
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnManagerCell.cs

@ -17,19 +17,15 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Xceed.Utils.Wpf.DragDrop;
using Xceed.Wpf.DataGrid.Views;
using System.Collections;
using Xceed.Utils.Collections;
using System.Collections.Specialized;
using System;
using System.Windows.Automation.Peers;
using Xceed.Wpf.DataGrid.Automation;
using Xceed.Wpf.DataGrid.Views;
namespace Xceed.Wpf.DataGrid
{
@ -42,11 +38,9 @@ namespace Xceed.Wpf.DataGrid
FocusableProperty.OverrideMetadata( typeof( ColumnManagerCell ), new FrameworkPropertyMetadata( false ) );
ReadOnlyProperty.OverrideMetadata( typeof( ColumnManagerCell ), new FrameworkPropertyMetadata( true ) );
ColumnManagerCell.IsPressedProperty =
ColumnManagerCell.IsPressedPropertyKey.DependencyProperty;
ColumnManagerCell.IsPressedProperty = ColumnManagerCell.IsPressedPropertyKey.DependencyProperty;
ColumnManagerCell.IsBeingDraggedProperty =
ColumnManagerCell.IsBeingDraggedPropertyKey.DependencyProperty;
ColumnManagerCell.IsBeingDraggedProperty = ColumnManagerCell.IsBeingDraggedPropertyKey.DependencyProperty;
}
public ColumnManagerCell()
@ -98,14 +92,12 @@ namespace Xceed.Wpf.DataGrid
#endregion IsBeingDragged Read-Only Property
#region DataGridContext Property
#region DataGridContext Internal Read-Only Property
private DataGridContext DataGridContext
internal DataGridContext DataGridContext
{
get
{
Debug.Assert( m_dataGridContext != null );
return m_dataGridContext;
}
}
@ -126,11 +118,44 @@ namespace Xceed.Wpf.DataGrid
#endregion
#region ShowResizeCursor Property
internal bool ShowResizeCursor
{
get;
set;
}
#endregion
#region AllowResize Internal Read-Only Property
internal virtual bool AllowResize
{
get
{
if( this.ParentColumn == null )
return false;
var dataGridContext = this.DataGridContext;
if( dataGridContext == null )
return false;
// When details are flatten, only the column at the master level may be resized.
if( dataGridContext.IsAFlattenDetail )
return false;
return true;
}
}
#endregion
#region ColumnReordering Internal Event
internal static readonly RoutedEvent ColumnReorderingEvent =
EventManager.RegisterRoutedEvent( "ColumnReordering",
RoutingStrategy.Bubble,
RoutingStrategy.Bubble,
typeof( ColumnReorderingEventHandler ),
typeof( ColumnManagerCell ) );
@ -147,9 +172,9 @@ namespace Xceed.Wpf.DataGrid
{
base.InitializeCore( dataGridContext, parentRow, parentColumn );
this.SetContent( parentColumn );
this.SetContentTemplate( parentColumn );
this.SetContentTemplateSelector( parentColumn );
this.SetColumnBinding( ColumnManagerCell.ContentProperty, parentColumn, ColumnBase.TitleProperty );
this.SetColumnBinding( ColumnManagerCell.ContentTemplateProperty, parentColumn, ColumnBase.TitleTemplateProperty );
this.SetColumnBinding( ColumnManagerCell.ContentTemplateSelectorProperty, parentColumn, ColumnBase.TitleTemplateSelectorProperty );
}
protected override AutomationPeer OnCreateAutomationPeer()
@ -159,12 +184,11 @@ namespace Xceed.Wpf.DataGrid
protected internal override void PrepareDefaultStyleKey( ViewBase view )
{
object currentThemeKey = view.GetDefaultStyleKey( typeof( ColumnManagerCell ) );
var newThemeKey = view.GetDefaultStyleKey( typeof( ColumnManagerCell ) );
if( object.Equals( this.DefaultStyleKey, newThemeKey ) )
return;
if( currentThemeKey.Equals( this.DefaultStyleKey ) == false )
{
this.DefaultStyleKey = currentThemeKey;
}
this.DefaultStyleKey = newThemeKey;
}
protected internal override void PrepareContainer( DataGridContext dataGridContext, object item )
@ -201,9 +225,7 @@ namespace Xceed.Wpf.DataGrid
// Update the DropOutsideCursor since it is defined on the View
UIViewBase uiViewBase = dataGridContext.DataGridControl.GetView() as UIViewBase;
m_dragSourceManager.DropOutsideCursor = ( uiViewBase != null )
? uiViewBase.CannotDropDraggedElementCursor
: UIViewBase.DefaultCannotDropDraggedElementCursor;
m_dragSourceManager.DropOutsideCursor = ( uiViewBase != null ) ? uiViewBase.CannotDropDraggedElementCursor : UIViewBase.DefaultCannotDropDraggedElementCursor;
m_dragSourceManager.ProcessMouseLeftButtonDown( e );
}
@ -242,8 +264,7 @@ namespace Xceed.Wpf.DataGrid
protected override void OnMouseLeftButtonUp( MouseButtonEventArgs e )
{
// m_dragSourceManager.ProcessMouseLeftButtonUp() will release the capture,
// so we need to check the IsMouseCaptured and IsPressed states before calling it.
// m_dragSourceManager.ProcessMouseLeftButtonUp() will release the capture, so we need to check the IsMouseCaptured and IsPressed states before calling it.
bool isMouseCaptured = this.IsMouseCaptured;
bool isPressed = this.IsPressed;
@ -290,7 +311,9 @@ namespace Xceed.Wpf.DataGrid
protected override void OnLostMouseCapture( MouseEventArgs e )
{
if( m_dragSourceManager != null )
{
m_dragSourceManager.ProcessLostMouseCapture( e );
}
if( this.IsPressed )
{
@ -303,7 +326,6 @@ namespace Xceed.Wpf.DataGrid
internal bool CanDoSort()
{
ColumnManagerRow parentRow = this.ParentRow as ColumnManagerRow;
if( parentRow != null )
{
if( !parentRow.AllowSort )
@ -311,10 +333,13 @@ namespace Xceed.Wpf.DataGrid
}
DataGridContext dataGridContext = this.DataGridContext;
if( dataGridContext == null )
return false;
// When details are flatten, only the ColumnManagerCell at the master level may do the sort.
if( dataGridContext.IsAFlattenDetail )
return false;
if( dataGridContext.SourceDetailConfiguration == null )
{
if( !dataGridContext.Items.CanSort )
@ -325,7 +350,6 @@ namespace Xceed.Wpf.DataGrid
return false;
ColumnBase parentColumn = this.ParentColumn;
if( ( parentColumn == null ) || ( !parentColumn.AllowSort ) )
return false;
@ -338,159 +362,83 @@ namespace Xceed.Wpf.DataGrid
return;
DataGridContext dataGridContext = this.DataGridContext;
ColumnBase column = this.ParentColumn;
Debug.Assert( dataGridContext != null );
SortingHelper.ToggleColumnSort(
dataGridContext, dataGridContext.Items.SortDescriptions,
dataGridContext.Columns, this.ParentColumn, shiftUnpressed );
var toggleColumnSortCommand = dataGridContext.ToggleColumnSortCommand;
if( !toggleColumnSortCommand.CanExecute( column, shiftUnpressed ) )
return;
toggleColumnSortCommand.Execute( column, shiftUnpressed );
}
internal void DoResize( double newWidth )
internal void DoResize( double newWidth, ColumnBase parentColumn )
{
if( !this.IsEnabled )
return;
ColumnBase parentColumn = this.ParentColumn;
if( parentColumn == null )
return;
if( !parentColumn.HasFixedWidth )
{
if( newWidth < MIN_WIDTH )
{
newWidth = MIN_WIDTH;
}
if( newWidth < parentColumn.MinWidth )
{
newWidth = parentColumn.MinWidth;
}
if( newWidth > parentColumn.MaxWidth )
{
newWidth = parentColumn.MaxWidth;
}
parentColumn.Width = newWidth;
}
}
private void SetContent( ColumnBase parentColumn )
{
Binding binding = new Binding();
binding.Path = new PropertyPath( ColumnBase.TitleProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = parentColumn;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding( this, ColumnManagerCell.ContentProperty, binding );
}
private void SetContentTemplate( ColumnBase parentColumn )
{
Binding binding = new Binding();
binding.Path = new PropertyPath( ColumnBase.TitleTemplateProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = parentColumn;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding( this, ColumnManagerCell.ContentTemplateProperty, binding );
}
private void SetContentTemplateSelector( ColumnBase parentColumn )
internal virtual void OnColumnResizerThumbDragStarted( DragStartedEventArgs e )
{
Binding binding = new Binding();
binding.Path = new PropertyPath( ColumnBase.TitleTemplateSelectorProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = parentColumn;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
BindingOperations.SetBinding( this, ColumnManagerCell.ContentTemplateSelectorProperty, binding );
}
private void SetupDragManager()
{
DataGridContext dataGridContext = DataGridControl.GetDataGridContext( this );
// We do not support DragDrop when there are no AdornerLayer because there wouldn't
// be any visual feedback for the operation.
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this );
if( adornerLayer == null )
{
// When virtualizing, the Cell is not yet in the VisualTree because it is
// the ParentRow's CellsHost which is reponsible of putting them in the
// VisualTree. We try to get the adorner from the ParentRow instead
if( this.ParentRow != null )
adornerLayer = AdornerLayer.GetAdornerLayer( this.ParentRow );
if( adornerLayer == null )
return;
}
// Can be null in design-time (edition of a style TargetType ColumnManagerCell).
if( dataGridContext == null )
return;
DataGridControl dataGridControl = dataGridContext.DataGridControl;
if( dataGridControl == null )
return;
var parentColumn = this.ParentColumn;
Debug.Assert( parentColumn != null );
var dataGridContext = this.DataGridContext;
Debug.Assert( dataGridContext != null );
if( m_dragSourceManager != null )
{
m_dragSourceManager.PropertyChanged -= this.DragSourceManager_PropertyChanged;
}
m_originalWidth = parentColumn.ActualWidth;
// The DataGridControl's AdornerDecoratorForDragAndDrop must be used for dragging in order to include the
// RenderTransform the DataGridControl may performs. This AdornerDecorator is defined in the ControlTemplate
// as PART_DragDropAdornerDecorator
if( ( dataGridControl.DragDropAdornerDecorator != null )
&& ( dataGridControl.DragDropAdornerDecorator.AdornerLayer != null ) )
{
m_dragSourceManager = new ColumnReorderingDragSourceManager( this,
dataGridControl.DragDropAdornerDecorator.AdornerLayer,
dataGridControl );
}
else
if( TableView.GetRemoveColumnStretchingOnResize( dataGridContext ) )
{
m_dragSourceManager = new ColumnReorderingDragSourceManager( this,
null,
dataGridControl );
dataGridContext.ColumnStretchingManager.DisableColumnStretching();
}
}
m_dragSourceManager.PropertyChanged += this.DragSourceManager_PropertyChanged;
// Create bindings to ViewProperties for AutoScroll Properties
Binding binding = new Binding();
binding.Path = new PropertyPath( "(0).(1)",
DataGridControl.DataGridContextProperty,
TableView.AutoScrollIntervalProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding( m_dragSourceManager, DragSourceManager.AutoScrollIntervalProperty, binding );
binding = new Binding();
binding.Path = new PropertyPath( "(0).(1)", DataGridControl.DataGridContextProperty, TableView.AutoScrollTresholdProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = this;
internal virtual void OnColumnResizerThumbDragDelta( DragDeltaEventArgs e )
{
var parentColumn = this.ParentColumn;
Debug.Assert( parentColumn != null );
BindingOperations.SetBinding( m_dragSourceManager, DragSourceManager.AutoScrollTresholdProperty, binding );
this.DoResize( parentColumn.ActualWidth + e.HorizontalChange, parentColumn );
}
private void DragSourceManager_PropertyChanged( object sender, PropertyChangedEventArgs e )
internal virtual void OnColumnResizerThumbDragCompleted( DragCompletedEventArgs e )
{
if( e.PropertyName == "IsDragging" )
if( e.Canceled )
{
this.SetIsBeingDragged( m_dragSourceManager.IsDragging );
this.ParentColumn.Width = m_originalWidth;
}
m_originalWidth = -1d;
}
private void ShowDropMark( Point mousePosition )
internal void ShowDropMark( Point mousePosition )
{
if( m_dropMarkAdorner == null )
{
DataGridContext dataGridContext = DataGridControl.GetDataGridContext( this );
DataGridControl grid = ( dataGridContext != null )
? dataGridContext.DataGridControl
: null;
var dataGridContext = this.DataGridContext;
var grid = ( dataGridContext != null ) ? dataGridContext.DataGridControl : null;
Pen pen = UIViewBase.GetDropMarkPen( this );
@ -513,20 +461,24 @@ namespace Xceed.Wpf.DataGrid
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this );
if( adornerLayer != null )
{
adornerLayer.Add( m_dropMarkAdorner );
}
}
m_dropMarkAdorner.UpdateAlignment( mousePosition );
}
private void HideDropMark()
internal void HideDropMark()
{
if( m_dropMarkAdorner != null )
{
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this );
if( adornerLayer != null )
{
adornerLayer.Remove( m_dropMarkAdorner );
}
m_dropMarkAdorner = null;
}
@ -536,22 +488,22 @@ namespace Xceed.Wpf.DataGrid
{
if( m_columnResizerThumb != null )
{
m_columnResizerThumb.DragStarted -= new DragStartedEventHandler( ColumnResizerThumb_DragStarted );
m_columnResizerThumb.DragDelta -= new DragDeltaEventHandler( ColumnResizerThumb_DragDelta );
m_columnResizerThumb.DragCompleted -= new DragCompletedEventHandler( ColumnResizerThumb_DragCompleted );
m_columnResizerThumb.QueryCursor -= new QueryCursorEventHandler( ColumnResizerThumb_QueryCursor );
m_columnResizerThumb.MouseDoubleClick -= new MouseButtonEventHandler( ColumnResizerThumb_MouseDoubleClick );
m_columnResizerThumb.DragStarted -= new DragStartedEventHandler( this.ColumnResizerThumb_DragStarted );
m_columnResizerThumb.DragDelta -= new DragDeltaEventHandler( this.ColumnResizerThumb_DragDelta );
m_columnResizerThumb.DragCompleted -= new DragCompletedEventHandler( this.ColumnResizerThumb_DragCompleted );
m_columnResizerThumb.QueryCursor -= new QueryCursorEventHandler( this.ColumnResizerThumb_QueryCursor );
m_columnResizerThumb.MouseDoubleClick -= new MouseButtonEventHandler( this.ColumnResizerThumb_MouseDoubleClick );
m_columnResizerThumb = null;
}
if( m_columnResizerThumbLeft != null )
{
m_columnResizerThumbLeft.DragStarted -= new DragStartedEventHandler( ColumnResizerThumbLeft_DragStarted );
m_columnResizerThumbLeft.DragDelta -= new DragDeltaEventHandler( ColumnResizerThumbLeft_DragDelta );
m_columnResizerThumbLeft.DragCompleted -= new DragCompletedEventHandler( ColumnResizerThumbLeft_DragCompleted );
m_columnResizerThumbLeft.QueryCursor -= new QueryCursorEventHandler( ColumnResizerThumbLeft_QueryCursor );
m_columnResizerThumbLeft.MouseDoubleClick -= new MouseButtonEventHandler( ColumnResizerThumbLeft_MouseDoubleClick );
m_columnResizerThumbLeft.DragStarted -= new DragStartedEventHandler( this.ColumnResizerThumbLeft_DragStarted );
m_columnResizerThumbLeft.DragDelta -= new DragDeltaEventHandler( this.ColumnResizerThumbLeft_DragDelta );
m_columnResizerThumbLeft.DragCompleted -= new DragCompletedEventHandler( this.ColumnResizerThumbLeft_DragCompleted );
m_columnResizerThumbLeft.QueryCursor -= new QueryCursorEventHandler( this.ColumnResizerThumbLeft_QueryCursor );
m_columnResizerThumbLeft.MouseDoubleClick -= new MouseButtonEventHandler( this.ColumnResizerThumbLeft_MouseDoubleClick );
m_columnResizerThumbLeft = null;
}
@ -561,120 +513,157 @@ namespace Xceed.Wpf.DataGrid
if( m_columnResizerThumb != null )
{
m_columnResizerThumb.DragStarted += new DragStartedEventHandler( ColumnResizerThumb_DragStarted );
m_columnResizerThumb.DragDelta += new DragDeltaEventHandler( ColumnResizerThumb_DragDelta );
m_columnResizerThumb.DragCompleted += new DragCompletedEventHandler( ColumnResizerThumb_DragCompleted );
m_columnResizerThumb.QueryCursor += new QueryCursorEventHandler( ColumnResizerThumb_QueryCursor );
m_columnResizerThumb.MouseDoubleClick += new MouseButtonEventHandler( ColumnResizerThumb_MouseDoubleClick );
m_columnResizerThumb.DragStarted += new DragStartedEventHandler( this.ColumnResizerThumb_DragStarted );
m_columnResizerThumb.DragDelta += new DragDeltaEventHandler( this.ColumnResizerThumb_DragDelta );
m_columnResizerThumb.DragCompleted += new DragCompletedEventHandler( this.ColumnResizerThumb_DragCompleted );
m_columnResizerThumb.QueryCursor += new QueryCursorEventHandler( this.ColumnResizerThumb_QueryCursor );
m_columnResizerThumb.MouseDoubleClick += new MouseButtonEventHandler( this.ColumnResizerThumb_MouseDoubleClick );
}
if( m_columnResizerThumbLeft != null )
{
m_columnResizerThumbLeft.DragStarted += new DragStartedEventHandler( ColumnResizerThumbLeft_DragStarted );
m_columnResizerThumbLeft.DragDelta += new DragDeltaEventHandler( ColumnResizerThumbLeft_DragDelta );
m_columnResizerThumbLeft.DragCompleted += new DragCompletedEventHandler( ColumnResizerThumbLeft_DragCompleted );
m_columnResizerThumbLeft.QueryCursor += new QueryCursorEventHandler( ColumnResizerThumbLeft_QueryCursor );
m_columnResizerThumbLeft.MouseDoubleClick += new MouseButtonEventHandler( ColumnResizerThumbLeft_MouseDoubleClick );
m_columnResizerThumbLeft.DragStarted += new DragStartedEventHandler( this.ColumnResizerThumbLeft_DragStarted );
m_columnResizerThumbLeft.DragDelta += new DragDeltaEventHandler( this.ColumnResizerThumbLeft_DragDelta );
m_columnResizerThumbLeft.DragCompleted += new DragCompletedEventHandler( this.ColumnResizerThumbLeft_DragCompleted );
m_columnResizerThumbLeft.QueryCursor += new QueryCursorEventHandler( this.ColumnResizerThumbLeft_QueryCursor );
m_columnResizerThumbLeft.MouseDoubleClick += new MouseButtonEventHandler( this.ColumnResizerThumbLeft_MouseDoubleClick );
}
}
private void ColumnResizerThumb_MouseDoubleClick( object sender, MouseButtonEventArgs e )
private void SetupDragManager()
{
ColumnBase parentColumn = this.ParentColumn;
if( parentColumn == null )
var dataGridContext = this.DataGridContext;
// Can be null in design-time (edition of a style TargetType ColumnManagerCell).
if( dataGridContext == null )
return;
e.Handled = true;
double fittedWidth = parentColumn.GetFittedWidth();
if( fittedWidth != -1 )
// We do not support DragDrop when there are no AdornerLayer because there wouldn't be any visual feedback for the operation.
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this );
if( adornerLayer == null )
{
parentColumn.Width = fittedWidth;
}
}
// When virtualizing, the Cell is not yet in the VisualTree because it is the ParentRow's CellsHost which
// is reponsible of putting them in the VisualTree. We try to get the adorner from the ParentRow instead
if( this.ParentRow != null )
{
adornerLayer = AdornerLayer.GetAdornerLayer( this.ParentRow );
}
private void ColumnResizerThumb_QueryCursor( object sender, QueryCursorEventArgs e )
{
ColumnBase parentColumn = this.ParentColumn;
if( adornerLayer == null )
return;
}
if( parentColumn == null )
var dataGridControl = dataGridContext.DataGridControl;
if( dataGridControl == null )
return;
DataGridContext dataGridContext = this.DataGridContext;
bool showResizeCursor = !parentColumn.HasFixedWidth;
if( !showResizeCursor )
if( m_dragSourceManager != null )
{
// Don't disable resizing if ColumnStretching can be disabled by an end-user resize.
showResizeCursor = ( dataGridContext != null ) && ( TableView.GetRemoveColumnStretchingOnResize( dataGridContext ) );
m_dragSourceManager.PropertyChanged -= this.DragSourceManager_PropertyChanged;
}
if( showResizeCursor )
// The DataGridControl's AdornerDecoratorForDragAndDrop must be used for dragging in order to include the RenderTransform
// the DataGridControl may performs. This AdornerDecorator is defined in the ControlTemplate as PART_DragDropAdornerDecorator
if( ( dataGridControl.DragDropAdornerDecorator != null ) && ( dataGridControl.DragDropAdornerDecorator.AdornerLayer != null ) )
{
if( dataGridContext != null )
{
UIViewBase uiViewBase = dataGridContext.DataGridControl.GetView() as UIViewBase;
m_dragSourceManager = new ColumnReorderingDragSourceManager( this, dataGridControl.DragDropAdornerDecorator.AdornerLayer, dataGridControl, this.ParentRow.LevelCache );
}
else
{
m_dragSourceManager = new ColumnReorderingDragSourceManager( this, null, dataGridControl, this.ParentRow.LevelCache );
}
e.Cursor = ( uiViewBase != null )
? uiViewBase.ColumnResizeWestEastCursor
: UIViewBase.DefaultColumnResizeWestEastCursor;
}
else
{
e.Cursor = UIViewBase.DefaultColumnResizeWestEastCursor;
}
m_dragSourceManager.PropertyChanged += this.DragSourceManager_PropertyChanged;
e.Handled = true;
// Create bindings to ViewProperties for AutoScroll Properties
Binding binding = new Binding();
binding.Path = new PropertyPath( "(0).(1)", DataGridControl.DataGridContextProperty, TableView.AutoScrollIntervalProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding( m_dragSourceManager, DragSourceManager.AutoScrollIntervalProperty, binding );
binding = new Binding();
binding.Path = new PropertyPath( "(0).(1)", DataGridControl.DataGridContextProperty, TableView.AutoScrollTresholdProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = this;
BindingOperations.SetBinding( m_dragSourceManager, DragSourceManager.AutoScrollTresholdProperty, binding );
}
private void DragSourceManager_PropertyChanged( object sender, PropertyChangedEventArgs e )
{
if( e.PropertyName == "IsDragging" )
{
this.SetIsBeingDragged( m_dragSourceManager.IsDragging );
}
}
private void ColumnResizerThumb_DragStarted( object sender, DragStartedEventArgs e )
{
ColumnBase parentColumn = this.ParentColumn;
if( !this.ShowResizeCursor || !this.AllowResize )
return;
if( parentColumn == null )
this.OnColumnResizerThumbDragStarted( e );
}
private void ColumnResizerThumb_DragDelta( object sender, DragDeltaEventArgs e )
{
if( !this.ShowResizeCursor || !this.AllowResize )
return;
m_originalWidth = parentColumn.ActualWidth;
this.OnColumnResizerThumbDragDelta( e );
}
DataGridContext dataGridContext = DataGridControl.GetDataGridContext( this );
private void ColumnResizerThumb_DragCompleted( object sender, DragCompletedEventArgs e )
{
if( !this.ShowResizeCursor || !this.AllowResize )
return;
if( ( dataGridContext != null ) && ( TableView.GetRemoveColumnStretchingOnResize( dataGridContext ) ) )
{
dataGridContext.ColumnStretchingManager.DisableColumnStretching();
}
this.OnColumnResizerThumbDragCompleted( e );
}
private void ColumnResizerThumb_DragDelta( object sender, DragDeltaEventArgs e )
private void ColumnResizerThumb_MouseDoubleClick( object sender, MouseButtonEventArgs e )
{
ColumnBase parentColumn = this.ParentColumn;
var parentColumn = this.ParentColumn;
if( ( parentColumn == null ) || !this.ShowResizeCursor || !this.AllowResize )
return;
e.Handled = true;
if( parentColumn != null )
double fittedWidth = parentColumn.GetFittedWidth();
if( fittedWidth != -1 )
{
this.DoResize( parentColumn.ActualWidth + e.HorizontalChange );
parentColumn.Width = fittedWidth;
}
}
private void ColumnResizerThumb_DragCompleted( object sender, DragCompletedEventArgs e )
private void ColumnResizerThumb_QueryCursor( object sender, QueryCursorEventArgs e )
{
ColumnBase parentColumn = this.ParentColumn;
var parentColumn = this.ParentColumn;
if( parentColumn == null )
return;
if( e.Canceled || parentColumn.HasFixedWidth )
parentColumn.Width = m_originalWidth;
var dataGridContext = this.DataGridContext;
m_originalWidth = -1d;
bool showResizeCursor = false;
if( this.AllowResize )
{
// Don't disable resizing if ColumnStretching can be disabled by an end-user resize.
showResizeCursor = ( !parentColumn.HasFixedWidth )
|| ( ( dataGridContext != null ) && TableView.GetRemoveColumnStretchingOnResize( dataGridContext ) );
}
this.ShowResizeCursor = showResizeCursor;
if( this.ShowResizeCursor )
{
UIViewBase viewBase = ( dataGridContext != null ) ? dataGridContext.DataGridControl.GetView() as UIViewBase : null;
e.Cursor = ( viewBase != null ) ? viewBase.ColumnResizeWestEastCursor : UIViewBase.DefaultColumnResizeWestEastCursor;
e.Handled = true;
}
}
private ColumnManagerCell GetPreviousVisibleColumnManagerCell()
{
var previousVisibleColumn = this.ParentColumn.PreviousVisibleColumn;
if( previousVisibleColumn == null )
return null;
@ -684,69 +673,119 @@ namespace Xceed.Wpf.DataGrid
private void ColumnResizerThumbLeft_QueryCursor( object sender, QueryCursorEventArgs e )
{
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell();
if( previousColumnManagerCell == null )
return;
if( previousColumnManagerCell != null )
previousColumnManagerCell.ColumnResizerThumb_QueryCursor( previousColumnManagerCell, e );
previousColumnManagerCell.ColumnResizerThumb_QueryCursor( previousColumnManagerCell, e );
}
private void ColumnResizerThumbLeft_DragStarted( object sender, DragStartedEventArgs e )
{
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell();
if( previousColumnManagerCell == null )
return;
if( previousColumnManagerCell != null )
previousColumnManagerCell.ColumnResizerThumb_DragStarted( previousColumnManagerCell, e );
previousColumnManagerCell.ColumnResizerThumb_DragStarted( previousColumnManagerCell, e );
}
private void ColumnResizerThumbLeft_MouseDoubleClick( object sender, MouseButtonEventArgs e )
{
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell();
if( previousColumnManagerCell == null )
return;
if( previousColumnManagerCell != null )
previousColumnManagerCell.ColumnResizerThumb_MouseDoubleClick( previousColumnManagerCell, e );
previousColumnManagerCell.ColumnResizerThumb_MouseDoubleClick( previousColumnManagerCell, e );
}
private void ColumnResizerThumbLeft_DragDelta( object sender, DragDeltaEventArgs e )
{
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell();
if( previousColumnManagerCell == null )
return;
if( previousColumnManagerCell != null )
previousColumnManagerCell.ColumnResizerThumb_DragDelta( previousColumnManagerCell, e );
previousColumnManagerCell.ColumnResizerThumb_DragDelta( previousColumnManagerCell, e );
}
private void ColumnResizerThumbLeft_DragCompleted( object sender, DragCompletedEventArgs e )
{
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell();
if( previousColumnManagerCell == null )
return;
previousColumnManagerCell.ColumnResizerThumb_DragCompleted( previousColumnManagerCell, e );
}
private void SetColumnBinding( DependencyProperty targetProperty, ColumnBase parentColumn, DependencyProperty sourceProperty )
{
if( this.HasColumnBinding( targetProperty, parentColumn, sourceProperty ) )
return;
var binding = ColumnManagerCell.CreateColumnBinding( parentColumn, sourceProperty );
if( binding != null )
{
BindingOperations.SetBinding( this, targetProperty, binding );
}
else
{
BindingOperations.ClearBinding( this, targetProperty );
}
}
private bool HasColumnBinding( DependencyProperty targetProperty, ColumnBase parentColumn, DependencyProperty sourceProperty )
{
if( parentColumn == null )
return false;
var binding = BindingOperations.GetBinding( this, targetProperty );
if( binding == null )
return false;
var path = binding.Path;
if( path == null )
return false;
var pathParameters = path.PathParameters;
if( previousColumnManagerCell != null )
previousColumnManagerCell.ColumnResizerThumb_DragCompleted( previousColumnManagerCell, e );
return ( binding.Source == parentColumn )
&& ( pathParameters.Count == 1 )
&& ( pathParameters[ 0 ] == sourceProperty );
}
private static Binding CreateColumnBinding( ColumnBase parentColumn, DependencyProperty sourceProperty )
{
if( parentColumn == null )
return null;
var binding = new Binding();
binding.Path = new PropertyPath( sourceProperty );
binding.Mode = BindingMode.OneWay;
binding.Source = parentColumn;
binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
return binding;
}
#region IDropTarget Members
bool IDropTarget.CanDropElement( UIElement draggedElement )
{
bool allowColumnReorder = true;
ColumnManagerCell draggedCell = draggedElement as ColumnManagerCell;
if( ( draggedCell == null ) || ( this == draggedCell ) )
return false;
ColumnManagerRow parentRow = this.ParentRow as ColumnManagerRow;
if( ( parentRow == null ) || !parentRow.AllowColumnReorder )
return false;
if( parentRow != null )
allowColumnReorder = parentRow.AllowColumnReorder;
if( !ColumnManagerCell.CanMove( draggedCell ) || !ColumnManagerCell.CanMove( this ) )
return false;
DataGridContext draggedDetailContext = draggedCell.DataGridContext;
DataGridContext sourceDetailContext = this.DataGridContext;
Debug.Assert( sourceDetailContext != null );
DetailConfiguration sourceDetailConfig = ( sourceDetailContext != null ) ? sourceDetailContext.SourceDetailConfiguration : null;
DataGridContext draggedDetailContext = DataGridControl.GetDataGridContext( draggedElement );
Debug.Assert( draggedDetailContext != null );
DetailConfiguration draggedDetailConfig = ( draggedDetailContext != null ) ? draggedDetailContext.SourceDetailConfiguration : null;
Debug.Assert( ( draggedDetailContext != null ) && ( sourceDetailContext != null ) );
return ( ( sourceDetailConfig == draggedDetailConfig ) &&
( sourceDetailContext != null ) &&
( draggedDetailContext != null ) &&
( sourceDetailContext.GroupLevelDescriptions == draggedDetailContext.GroupLevelDescriptions ) &&
( allowColumnReorder ) &&
( draggedElement is ColumnManagerCell ) &&
( draggedElement != this ) );
return ( sourceDetailContext.SourceDetailConfiguration == draggedDetailContext.SourceDetailConfiguration ) &&
( sourceDetailContext.GroupLevelDescriptions == draggedDetailContext.GroupLevelDescriptions );
}
void IDropTarget.DragEnter( UIElement draggedElement )
@ -759,8 +798,7 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell != null )
{
ColumnReorderingDragSourceManager manager =
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
// No need for drop mark when performing animated Column reordering
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
@ -776,8 +814,7 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell != null )
{
ColumnReorderingDragSourceManager manager =
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
// No need for drop mark when performing animated Column reordering
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
@ -794,6 +831,11 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell == null )
return;
this.ProcessDrop( draggedCell );
}
internal void ProcessDrop( ColumnManagerCell draggedCell )
{
ColumnReorderingDragSourceManager manager = null;
if( draggedCell != null )
@ -816,15 +858,6 @@ namespace Xceed.Wpf.DataGrid
this.HideDropMark();
// This will force every Rows to update there layout
ColumnReorderingEventArgs e = new ColumnReorderingEventArgs(
ColumnManagerCell.ColumnReorderingEvent,
oldPosition,
newPosition );
this.RaiseEvent( e );
if( draggedCell.ParentColumn.VisiblePosition < newPosition )
{
if( alignment == DropMarkAlignment.Near )
@ -847,14 +880,45 @@ namespace Xceed.Wpf.DataGrid
draggedCell.ParentColumn.VisiblePosition = newPosition + 1;
}
}
// This will force every Rows to update there layout
ColumnReorderingEventArgs e = new ColumnReorderingEventArgs( ColumnManagerCell.ColumnReorderingEvent, oldPosition, newPosition );
this.RaiseEvent( e );
}
}
}
private static bool CanMove( ColumnManagerCell cell )
{
if( cell == null )
return false;
var dataGridContext = cell.DataGridContext;
if( dataGridContext == null )
return false;
if( dataGridContext.AreDetailsFlatten )
{
// Column reordering is not allowed for a ColumnManagerCell that is located at a detail level
// when details are flatten.
if( dataGridContext.SourceDetailConfiguration != null )
return false;
// The main column is not allowed to be reordered when details are flatten.
var parentColumn = cell.ParentColumn;
if( ( parentColumn == null ) || ( parentColumn.IsMainColumn ) )
return false;
}
return true;
}
#endregion IDropTarget Members
// Will remain null when no AdornerLayer is found.
private ColumnReorderingDragSourceManager m_dragSourceManager;
private DropMarkAdorner m_dropMarkAdorner;
private DataGridContext m_dataGridContext; // = null;

19
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnManagerRow.cs

@ -14,12 +14,13 @@
***********************************************************************************/
using System.Collections;
using System.Diagnostics;
using System.Windows;
using Xceed.Wpf.DataGrid.Views;
using System.Windows.Automation.Peers;
using Xceed.Wpf.DataGrid.Automation;
using Xceed.Wpf.DataGrid.Views;
using Xceed.Utils.Wpf.DragDrop;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid
{
@ -36,7 +37,7 @@ namespace Xceed.Wpf.DataGrid
this.ReadOnly = true; //This is safe to perform since there is nowhere a callback installed on the DP...
//ensure that all ColumnManagerRows are not navigable
this.NavigationBehavior = NavigationBehavior.None; //This is safe to perform since there is nowhere a callback installed on the DP...
this.NavigationBehavior = NavigationBehavior.None; //This is safe to perform since there is nowhere a callback installed on the DP...
}
#region AllowColumnReorder Property
@ -138,20 +139,17 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell == null )
return false;
ColumnReorderingDragSourceManager manager =
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
{
ColumnManagerCell cell = draggedElement as ColumnManagerCell;
if( ( cell != null )
&& ( cell.IsBeingDragged ) )
if( ( cell != null ) && ( cell.IsBeingDragged ) )
{
DataGridContext rowDataGridContext = DataGridControl.GetDataGridContext( this );
if( ( rowDataGridContext != null )
&& ( rowDataGridContext.Columns.Contains( cell.ParentColumn ) ) )
if( ( rowDataGridContext != null ) && ( rowDataGridContext.Columns.Contains( cell.ParentColumn ) ) )
{
canDrop = true;
}
@ -180,8 +178,7 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell == null )
return;
ColumnReorderingDragSourceManager manager =
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
{

5
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnReorderingEvent.cs

@ -17,7 +17,6 @@
using System;
using System.Windows;
// TODO (case 117282) : Renommer ce fichier.
namespace Xceed.Wpf.DataGrid
{
internal delegate void ColumnReorderingEventHandler( object sender, ColumnReorderingEventArgs e );
@ -26,12 +25,12 @@ namespace Xceed.Wpf.DataGrid
{
#region Constructors
public ColumnReorderingEventArgs(RoutedEvent routedEvent, int oldVisiblePosition, int newVisiblePosition )
public ColumnReorderingEventArgs( RoutedEvent routedEvent, int oldVisiblePosition, int newVisiblePosition )
: base( routedEvent )
{
m_oldVisiblePosition = oldVisiblePosition;
m_newVisiblePosition = newVisiblePosition;
}
}
#endregion

261
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnSortCommand.cs

@ -0,0 +1,261 @@
/*************************************************************************************
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.ComponentModel;
using System.Diagnostics;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid
{
internal abstract class ColumnSortCommand : ColumnCommand
{
protected SynchronizationContext StartSynchronizing( SortDescriptionsSyncContext context )
{
return new SynchronizationContext( context );
}
protected bool TryDeferResort( DetailConfiguration detailConfiguration, out IDisposable defer )
{
defer = null;
return ( detailConfiguration != null )
&& ( this.TryDeferResort( detailConfiguration.SortDescriptions, out defer ) );
}
protected bool TryDeferResort( SortDescriptionCollection sortDescriptions, out IDisposable defer )
{
var dataGridSortDescriptions = sortDescriptions as DataGridSortDescriptionCollection;
if( dataGridSortDescriptions != null )
{
defer = dataGridSortDescriptions.DeferResort();
}
else
{
defer = null;
}
return ( defer != null );
}
protected IDisposable DeferResortHelper(
IEnumerable itemsSourceCollection,
CollectionView collectionView )
{
var dataGridCollectionView = itemsSourceCollection as DataGridCollectionViewBase;
if( dataGridCollectionView != null )
return dataGridCollectionView.DataGridSortDescriptions.DeferResort();
ColumnSortCommand.ThrowIfNull( collectionView, "collectionView" );
return collectionView.DeferRefresh();
}
#region SynchronizationContext Protected Class
protected sealed class SynchronizationContext : IDisposable
{
#region Constructor
internal SynchronizationContext( SortDescriptionsSyncContext context )
{
if( context == null )
throw new ArgumentNullException( "context" );
m_context = context;
m_isOwner = !context.ProcessingSortSynchronization;
context.ProcessingSortSynchronization = true;
}
#endregion
#region Own Property
public bool Own
{
get
{
var context = m_context;
return ( m_isOwner )
&& ( context != null )
&& ( context.ProcessingSortSynchronization );
}
}
#endregion
#region IDisposable Members
public void Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
private void Dispose( bool disposing )
{
var context = m_context;
if( context == null )
return;
m_context = null;
if( m_isOwner )
{
context.ProcessingSortSynchronization = false;
}
}
~SynchronizationContext()
{
this.Dispose( false );
}
#endregion
#region Private Fields
private SortDescriptionsSyncContext m_context;
private bool m_isOwner;
#endregion
}
#endregion
#region Disposer Protected Class
protected sealed class Disposer : IDisposable
{
#region Constants
private static readonly int DisposableTypeCount = Enum.GetValues( typeof( DisposableType ) ).Length;
#endregion
public Disposer()
{
m_disposable = new Stack<IDisposable>[ Disposer.DisposableTypeCount ];
}
public void Add( IDisposable disposable, DisposableType disposableType )
{
if( m_disposed )
throw new ObjectDisposedException( "Disposer" );
if( !Enum.IsDefined( typeof( DisposableType ), disposableType ) )
throw new ArgumentException( "disposableType" );
if( disposable == null )
return;
int index = Disposer.GetIndex( disposableType );
var collection = m_disposable[ index ];
if( collection == null )
{
collection = new Stack<IDisposable>();
m_disposable[ index ] = collection;
}
collection.Push( disposable );
}
private static int GetIndex( DisposableType value )
{
int index = System.Convert.ToInt32( value );
Debug.Assert( ( index >= 0 ) && ( index < Disposer.DisposableTypeCount ) );
return index;
}
#region IDisposable Members
public void Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
private void Dispose( bool disposing )
{
if( m_disposed )
return;
m_disposed = true;
Exception exception = null;
for( int i = m_disposable.Length - 1; i >= 0; i-- )
{
var disposable = m_disposable[ i ];
if( disposable == null )
continue;
while( disposable.Count > 0 )
{
try
{
disposable.Pop().Dispose();
}
catch( Exception e )
{
if( exception == null )
{
exception = e;
}
}
}
m_disposable[ i ] = null;
}
if( exception != null )
throw new DataGridInternalException( exception );
}
~Disposer()
{
this.Dispose( false );
}
#endregion
#region Private Fields
private readonly Stack<IDisposable>[] m_disposable;
private bool m_disposed;
#endregion
}
#endregion
#region DisposableType Protected Nested Type
protected enum DisposableType
{
DeferRestoreState = 0,
DeferResort = 1,
}
#endregion
}
}

1097
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/ColumnSynchronizationManager.cs

File diff suppressed because it is too large

59
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/FilterCriterionToNullableBoolConverter.cs

@ -1,59 +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.Globalization;
using System.Windows.Data;
using Xceed.Wpf.DataGrid.FilterCriteria;
namespace Xceed.Wpf.DataGrid.Converters
{
[ValueConversion( typeof( FilterCriterion ), typeof( Nullable<bool> ) )]
internal class FilterCriterionToNullableBoolConverter : IValueConverter
{
#region IValueConverter Members
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
Nullable<bool> boolValue = null;
EqualToFilterCriterion filterCriterion = value as EqualToFilterCriterion;
if( ( filterCriterion != null ) && ( filterCriterion.Value is bool ) )
{
boolValue = ( bool )filterCriterion.Value;
}
return boolValue;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
Nullable<bool> boolValue = value as Nullable<bool>;
if( boolValue.HasValue )
{
return new EqualToFilterCriterion( value );
}
else
{
return null;
}
}
#endregion
}
}

112
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/StatResultConverter.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;
using System.Globalization;
using System.Text;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid.Converters
{
[ValueConversion( typeof( object ), typeof( string ) )]
public class StatResultConverter : StringFormatConverter
{
#region OverflowMessage Property
private string m_overflowMessage = "#OVER#";
public string OverflowMessage
{
get
{
return m_overflowMessage;
}
set
{
m_overflowMessage = value;
}
}
#endregion OverflowMessage Property
#region DivisionByZeroMessage Property
private string m_divisionByZeroMessage = "#DIV/0#";
public string DivisionByZeroMessage
{
get
{
return m_divisionByZeroMessage;
}
set
{
m_divisionByZeroMessage = value;
}
}
#endregion DivisionByZeroMessage Property
#region InvalidValueMessage Property
private string m_invalidValueMessage = "#VALUE#";
public string InvalidValueMessage
{
get
{
return m_invalidValueMessage;
}
set
{
m_invalidValueMessage = value;
}
}
#endregion InvalidValueMessage Property
#region IValueConverter Members
public override object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( ( value == null ) || ( value is DBNull ) )
return null;
if( value is DivideByZeroException )
return m_divisionByZeroMessage;
if( value is OverflowException )
return m_overflowMessage;
if( value is Stats.InvalidValueException )
return m_invalidValueMessage;
Stats.InvalidSourcePropertyNameException invalidSourcePropertyNameException = value as Stats.InvalidSourcePropertyNameException;
if( invalidSourcePropertyNameException != null )
return "#" + invalidSourcePropertyNameException.SourcePropertyName + "#";
Exception exception = value as Exception;
if( exception != null )
return exception.Message;
return base.Convert( value, targetType, parameter, culture );
}
#endregion
}
}

2
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/StringFormatConverter.cs

@ -60,7 +60,7 @@ namespace Xceed.Wpf.DataGrid.Converters
{
if( m_formatProvider == null )
{
return string.Format( format, value );
return string.Format( culture, format, value );
}
else
{

50
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/Converters/StringFormatMultiConverter.cs

@ -0,0 +1,50 @@
/*************************************************************************************
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.Globalization;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid.Converters
{
public class StringFormatMultiConverter : IMultiValueConverter
{
public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
{
if( ( values == null ) || ( values.Length <= 0 ) )
return null;
var data = values[ 0 ];
var format = ( values.Length > 1 ) ? values[ 1 ] as string : null;
if( string.IsNullOrEmpty( format ) )
return data;
var currentCulture = ( values.Length > 2 ) ? values[ 2 ] as CultureInfo : null;
if( currentCulture == null )
{
currentCulture = culture ?? CultureInfo.CurrentCulture;
}
return string.Format( currentCulture, format, data );
}
public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
}
}

28
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/CurrencyManager.cs

@ -147,8 +147,14 @@ namespace Xceed.Wpf.DataGrid
// Synchronize the CurrentItem of the DataGridContext
// with the one of the CollecitonView.
m_dataGridContext.SetCurrent(
m_collectionView.CurrentItem, null, m_collectionView.CurrentPosition,
m_dataGridContext.CurrentColumn, false, false, this.ShouldSynchronizeSelectionWithCurrent );
m_collectionView.CurrentItem,
null,
m_collectionView.CurrentPosition,
m_dataGridContext.CurrentColumn,
false,
false,
this.ShouldSynchronizeSelectionWithCurrent,
AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
if( m_collectionView.CurrentItem == null )
this.ChangeCurrentDataGridContext();
@ -163,8 +169,14 @@ namespace Xceed.Wpf.DataGrid
m_dataGridContext.CancelEdit();
m_dataGridContext.SetCurrent(
m_collectionView.CurrentItem, null, m_collectionView.CurrentPosition,
m_dataGridContext.CurrentColumn, false, false, this.ShouldSynchronizeSelectionWithCurrent );
m_collectionView.CurrentItem,
null,
m_collectionView.CurrentPosition,
m_dataGridContext.CurrentColumn,
false,
false,
this.ShouldSynchronizeSelectionWithCurrent,
AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
if( m_collectionView.CurrentItem == null )
this.ChangeCurrentDataGridContext();
@ -180,9 +192,7 @@ namespace Xceed.Wpf.DataGrid
{
if( ( m_dataGridContext.ParentDataGridContext == null )
|| ( m_dataGridContext.ParentItem == null ) )
{
return;
}
List<DataGridContext> childContexts = this.GetParentItemChildContexts();
int currentContextIndex = childContexts.IndexOf( m_dataGridContext );
@ -200,7 +210,7 @@ namespace Xceed.Wpf.DataGrid
if( childContext.Items.Count == 0 )
continue;
childContext.SetCurrentItemCore( childContext.Items.GetItemAt( 0 ), false, this.ShouldSynchronizeSelectionWithCurrent );
childContext.SetCurrentItemCore( childContext.Items.GetItemAt( 0 ), false, this.ShouldSynchronizeSelectionWithCurrent, AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
return;
}
}
@ -216,13 +226,13 @@ namespace Xceed.Wpf.DataGrid
if( count == 0 )
continue;
childContext.SetCurrentItemCore( childContext.Items.GetItemAt( count - 1 ), false, this.ShouldSynchronizeSelectionWithCurrent );
childContext.SetCurrentItemCore( childContext.Items.GetItemAt( count - 1 ), false, this.ShouldSynchronizeSelectionWithCurrent, AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
return;
}
}
// No context after or before us have been found, we will set the CurrentItem to our ParentItem.
m_dataGridContext.ParentDataGridContext.SetCurrentItemCore( m_dataGridContext.ParentItem, false, this.ShouldSynchronizeSelectionWithCurrent );
m_dataGridContext.ParentDataGridContext.SetCurrentItemCore( m_dataGridContext.ParentItem, false, this.ShouldSynchronizeSelectionWithCurrent, AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
}
private List<DataGridContext> GetParentItemChildContexts()

108
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataCell.cs

@ -15,21 +15,15 @@
***********************************************************************************/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Xml;
using System.Windows.Input;
using System.Windows.Media;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Xceed.Wpf.DataGrid.Views;
using Xceed.Wpf.DataGrid.Markup;
using System.Xml;
using Xceed.Wpf.DataGrid.Converters;
namespace Xceed.Wpf.DataGrid
{
@ -55,10 +49,13 @@ namespace Xceed.Wpf.DataGrid
{
get
{
return ( m_canBeRecycled && base.CanBeRecycled );
return ( m_canBeRecycled )
&& ( base.CanBeRecycled );
}
}
private bool m_canBeRecycled; //= false
#endregion
#region OverrideColumnCellContentTemplate Property
@ -73,13 +70,36 @@ namespace Xceed.Wpf.DataGrid
#endregion
protected override void OnMouseEnter( MouseEventArgs e )
{
//If the current CellEditorDisplayConditions requires display when mouse is over the Cell
if( Cell.IsCellEditorDisplayConditionsSet( this, CellEditorDisplayConditions.MouseOverCell ) )
{
//Display the editors for the Row
this.SetDisplayEditorMatchingCondition( CellEditorDisplayConditions.MouseOverCell );
}
base.OnMouseEnter( e );
}
protected override void OnMouseLeave( MouseEventArgs e )
{
//If the current CellEditorDisplayConditions requires display when mouse is over the Cell
if( Cell.IsCellEditorDisplayConditionsSet( this, CellEditorDisplayConditions.MouseOverCell ) )
{
//Display the editors for the Row
this.RemoveDisplayEditorMatchingCondition( CellEditorDisplayConditions.MouseOverCell );
}
base.OnMouseLeave( e );
}
protected override void InitializeCore( DataGridContext dataGridContext, Row parentRow, ColumnBase parentColumn )
{
ColumnBase oldParentColumn = this.ParentColumn;
base.InitializeCore( dataGridContext, parentRow, parentColumn );
// This is a fix for Case 106982 (could not bind to XML datasources that contained namespaces).
//
// For an unknown reason, when a recycled DataCell was added back to the VisualTree (added
// to the CellsHostPanel in its ParentRow), the binding would fail to update when the XPath
@ -122,12 +142,11 @@ namespace Xceed.Wpf.DataGrid
protected internal override void PrepareDefaultStyleKey( Xceed.Wpf.DataGrid.Views.ViewBase view )
{
object currentThemeKey = view.GetDefaultStyleKey( typeof( DataCell ) );
var newThemeKey = view.GetDefaultStyleKey( typeof( DataCell ) );
if( object.Equals( this.DefaultStyleKey, newThemeKey ) )
return;
if( currentThemeKey.Equals( this.DefaultStyleKey ) == false )
{
this.DefaultStyleKey = currentThemeKey;
}
this.DefaultStyleKey = newThemeKey;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )]
@ -145,14 +164,7 @@ namespace Xceed.Wpf.DataGrid
// If the dataContext is our ParentRow, we do not create any binding
if( dataContext != this.ParentRow )
{
// Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618
displayMemberBinding = column.DisplayMemberBinding;
#pragma warning restore 618
displayMemberBinding = column.GetDisplayMemberBinding();
if( displayMemberBinding == null )
{
@ -163,19 +175,13 @@ namespace Xceed.Wpf.DataGrid
{
bool isDataGridUnboundItemProperty;
displayMemberBinding = ItemsSourceHelper.AutoCreateDisplayMemberBinding(
column, dataGridContext, dataContext, out isDataGridUnboundItemProperty );
displayMemberBinding = ItemsSourceHelper.AutoCreateDisplayMemberBinding( column, dataGridContext, dataContext, out isDataGridUnboundItemProperty );
column.IsBoundToDataGridUnboundItemProperty = isDataGridUnboundItemProperty;
}
// Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618
column.DisplayMemberBinding = displayMemberBinding;
#pragma warning restore 618
//mark the Column's Binding as AutoCreated.
column.IsBindingAutoCreated = true;
column.SetDisplayMemberBinding( displayMemberBinding );
}
}
@ -212,6 +218,11 @@ namespace Xceed.Wpf.DataGrid
}
}
internal virtual void ClearDisplayMemberBinding()
{
BindingOperations.ClearBinding( this, Cell.ContentProperty );
}
internal override void ContentCommitted()
{
base.ContentCommitted();
@ -222,6 +233,33 @@ namespace Xceed.Wpf.DataGrid
parentRow.EnsurePosition( dataGridContext, this );
}
internal override DataTemplate GetForeignKeyDataTemplate()
{
var column = this.ParentColumn as Column;
if( column == null )
return null;
// If a foreignKey CellContentTemplate was found by the configuration,
// it must be used even if a CellContentTemplate is defined because the
// CellContentTemplate will be used by this template
var configuration = column.ForeignKeyConfiguration;
if( configuration == null )
return null;
return configuration.DefaultCellContentTemplate;
}
internal override DataTemplate GetCellStringFormatDataTemplate( DataTemplate contentTemplate )
{
var parentColumn = this.ParentColumn;
Debug.Assert( parentColumn != null );
var format = parentColumn.CellContentStringFormat;
Debug.Assert( !string.IsNullOrEmpty( format ) );
return StringFormatDataTemplate.Get( contentTemplate, format, parentColumn.GetCulture() );
}
private static bool VerifyDisplayMemberBinding( BindingBase binding )
{
bool retval = false;
@ -242,7 +280,5 @@ namespace Xceed.Wpf.DataGrid
return retval;
}
private bool m_canBeRecycled; // = false
}
}

19
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridBindingInfo.cs

@ -152,6 +152,23 @@ namespace Xceed.Wpf.DataGrid
#endregion FallbackValue Property
#region IsAsync Property
public bool IsAsync
{
get
{
return m_binding.IsAsync;
}
set
{
m_binding.IsAsync = value;
}
}
#endregion IsAsync Property
#region NotifyOnSourceUpdated Property
public bool NotifyOnSourceUpdated
@ -210,7 +227,6 @@ namespace Xceed.Wpf.DataGrid
#endregion ReadOnly Property
#region UpdateSourceExceptionFilter Property
public UpdateSourceExceptionFilterCallback UpdateSourceExceptionFilter
@ -257,7 +273,6 @@ namespace Xceed.Wpf.DataGrid
#endregion Path Property
#region INTERNAL METHODS
internal Binding GetBinding()

1388
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridContext.cs

File diff suppressed because it is too large

1082
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridControl.cs

File diff suppressed because it is too large

58
ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/DataGridException.cs

@ -34,15 +34,73 @@ namespace Xceed.Wpf.DataGrid
{
}
public DataGridException( string message, DataGridControl dataGridControl )
: base( message )
{
this.DataGridControl = dataGridControl;
}
public DataGridException( string message, Exception innerException )
: base( message, innerException )
{
}
public DataGridException( string message, Exception innerException, DataGridControl dataGridControl )
: base( message, innerException )
{
this.DataGridControl = dataGridControl;
}
protected DataGridException( SerializationInfo info, StreamingContext context )
: base( info, context )
{
}
#region DataGridControl Property
public DataGridControl DataGridControl
{
get;
private set;
}
#endregion
internal static void ThrowSystemException( string message, Type exceptionType, string source, string argument = "" )
{
Exception exception;
if( exceptionType == typeof( ArgumentException ) )
{
exception = new ArgumentException( message, argument );
}
else if( exceptionType == typeof( ArgumentNullException ) )
{
exception = new ArgumentNullException( message );
}
else if( exceptionType == typeof( ArgumentOutOfRangeException ) )
{
exception = new ArgumentOutOfRangeException( argument, message );
}
else if( exceptionType == typeof( IndexOutOfRangeException ) )
{
exception = new IndexOutOfRangeException( message );
}
else if( exceptionType == typeof( InvalidOperationException ) )
{
exception = new InvalidOperationException( message );
}
else if( exceptionType == typeof( NotSupportedException ) )
{
exception = new NotSupportedException( message );
}
else
{
exception = new Exception( message );
}
exception.Source = source;
throw exception;
}
}
}

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

Loading…
Cancel
Save