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 internal static class _XceedVersionInfo
{ {
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] [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" )] [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion + public const string Version = BaseVersion +
".0.0"; ".0.0";

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

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

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

@ -54,19 +54,6 @@
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </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>
<Style x:Key="AvalonDock_ThemeMetro_ButtonStyle" TargetType="Button"> <Style x:Key="AvalonDock_ThemeMetro_ButtonStyle" TargetType="Button">
@ -85,19 +72,10 @@
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </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> </Style>
<!--DocumentPaneControlStyle--> <!--DocumentPaneControlStyle-->
<Style x:Key="AvalonDock_ThemeMetro_DocumentPaneControlStyle" TargetType="{x:Type avalonDockControls:LayoutDocumentPaneControl}"> <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="BorderBrush" Value="{x:Null}"/>
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
@ -171,22 +149,6 @@
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Trigger> </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"> <Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger> </Trigger>
@ -377,8 +339,6 @@
<Setter Property="Panel.ZIndex" Value="0" /> <Setter Property="Panel.ZIndex" Value="0" />
</MultiTrigger> </MultiTrigger>
<Trigger Property="IsEnabled" Value="false"> <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}}"/> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger> </Trigger>
</ControlTemplate.Triggers> </ControlTemplate.Triggers>
@ -969,8 +929,7 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Border x:Name="Header" <Border x:Name="Header">
Background="{DynamicResource AvalonDock_ThemeMetro_BaseColor16}">
<avalonDockControls:AnchorablePaneTitle <avalonDockControls:AnchorablePaneTitle
Model="{Binding Model, RelativeSource={RelativeSource TemplatedParent}}"/> Model="{Binding Model, RelativeSource={RelativeSource TemplatedParent}}"/>
</Border> </Border>
@ -1437,7 +1396,6 @@
</Grid> </Grid>
<Border Grid.Row="1" <Border Grid.Row="1"
BorderBrush="{DynamicResource AvalonDock_ThemeMetro_BaseColor11}"
BorderThickness="0,1,0,0" BorderThickness="0,1,0,0"
Background="{DynamicResource AvalonDock_ThemeMetro_BaseColor7}" Background="{DynamicResource AvalonDock_ThemeMetro_BaseColor7}"
MinHeight="200" > MinHeight="200" >

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

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

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

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

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

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

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

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

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

@ -171,7 +171,11 @@
<!--AnchorablePaneControlStyle--> <!--AnchorablePaneControlStyle-->
<Style x:Key="AnchorablePaneControlStyle" TargetType="{x:Type avalonDockControls:LayoutAnchorablePaneControl}"> <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 Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type avalonDockControls:LayoutAnchorablePaneControl}"> <ControlTemplate TargetType="{x:Type avalonDockControls:LayoutAnchorablePaneControl}">

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

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

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

@ -15,10 +15,9 @@
***********************************************************************************/ ***********************************************************************************/
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Collections;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -95,7 +94,7 @@ namespace Xceed.Wpf.DataGrid
public bool MoveNext() public bool MoveNext()
{ {
if( m_version != m_virtualList.PagingManager.Version ) if( m_version != m_virtualList.PagingManager.Version )
throw new InvalidOperationException( "TODO: Collection was modified." ); throw new InvalidOperationException( "Collection was modified." );
if( m_beforeStart ) if( m_beforeStart )
m_beforeStart = false; 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 ) 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.ParentVirtualList.PagingManager.OnBuiltInAbort( this, queryInfo );
this.IsAborting = false; this.IsAborting = false;
} }
private void AsyncQueryInfo_BeginQueryItems( AsyncQueryInfo queryInfo ) 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 ); this.ParentVirtualList.PagingManager.OnQueryItems( this, queryInfo );
} }
@ -322,6 +332,8 @@ namespace Xceed.Wpf.DataGrid
if( this.IsDisposed ) if( this.IsDisposed )
return; return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
this.ParentVirtualList.PagingManager.OnAbortQueryItems( this, queryInfo ); this.ParentVirtualList.PagingManager.OnAbortQueryItems( this, queryInfo );
this.IsAborting = false; this.IsAborting = false;
@ -337,6 +349,7 @@ namespace Xceed.Wpf.DataGrid
if( this.IsDisposed ) if( this.IsDisposed )
return; return;
Debug.Assert( ( this.ParentVirtualList != null ) || ( this.ParentVirtualList.PagingManager != null ) );
Debug.Assert( !this.IsAborting ); Debug.Assert( !this.IsAborting );
this.ParentVirtualList.PagingManager.OnQueryItemsCompleted( this, queryInfo, fetchedItems ); this.ParentVirtualList.PagingManager.OnQueryItemsCompleted( this, queryInfo, fetchedItems );
@ -346,6 +359,11 @@ namespace Xceed.Wpf.DataGrid
private void AsyncQueryInfo_QueryErrorChanged( AsyncQueryInfo queryInfo ) 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 ); this.ParentVirtualList.PagingManager.OnQueryErrorChanged( this, queryInfo );
if( this.ParentVirtualList.IsRestarting ) if( this.ParentVirtualList.IsRestarting )
@ -354,11 +372,21 @@ namespace Xceed.Wpf.DataGrid
private void AsyncCommitInfo_BeginCommitItems( AsyncCommitInfo commitInfo ) 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 ); this.ParentVirtualList.PagingManager.OnCommitItems( this, commitInfo );
} }
private void AsyncCommitInfo_EndCommitItems( AsyncCommitInfo 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 ); this.ParentVirtualList.PagingManager.OnCommitItemsCompleted( this, commitInfo );
if( this.ParentVirtualList.IsRestarting ) if( this.ParentVirtualList.IsRestarting )
@ -367,6 +395,11 @@ namespace Xceed.Wpf.DataGrid
private void AsyncCommitInfo_CommitErrorChanged( AsyncCommitInfo commitInfo ) 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 ); this.ParentVirtualList.PagingManager.OnCommitErrorChanged( this, commitInfo );
if( this.ParentVirtualList.IsRestarting ) 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.Collections;
using System.Windows.Data;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
public class DataGridForeignKeyDescription : DependencyObject public class DataGridForeignKeyDescription : DependencyObject
{ {
#region Constructors
public DataGridForeignKeyDescription() public DataGridForeignKeyDescription()
{ {
} }
#endregion
#region ForeignKeyConverter Property #region ForeignKeyConverter Property
public static readonly DependencyProperty ForeignKeyConverterProperty = DependencyProperty.Register( public static readonly DependencyProperty ForeignKeyConverterProperty = DependencyProperty.Register(
@ -64,15 +53,13 @@ namespace Xceed.Wpf.DataGrid
"ItemsSource", "ItemsSource",
typeof( IEnumerable ), typeof( IEnumerable ),
typeof( DataGridForeignKeyDescription ), typeof( DataGridForeignKeyDescription ),
new FrameworkPropertyMetadata( new FrameworkPropertyMetadata( null ) );
null,
new PropertyChangedCallback( DataGridForeignKeyDescription.OnItemsSourceChanged ) ) );
public IEnumerable ItemsSource public IEnumerable ItemsSource
{ {
get get
{ {
return m_itemsSource; return ( IEnumerable )this.GetValue( DataGridForeignKeyDescription.ItemsSourceProperty );
} }
set 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 #endregion
#region IsAutoCreated Internal Property #region IsAutoCreated Internal Property
@ -125,5 +100,27 @@ namespace Xceed.Wpf.DataGrid
} }
#endregion #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.Data;
using System.Collections;
using System.Windows; using System.Windows;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -56,7 +50,7 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_foreignKeyConstraint; return ( ForeignKeyConstraint )this.GetValue( DataTableForeignKeyDescription.ForeignKeyConstraintProperty );
} }
set set
{ {
@ -66,18 +60,14 @@ namespace Xceed.Wpf.DataGrid
private static void OnForeignKeyConstraintChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) private static void OnForeignKeyConstraintChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{ {
DataTableForeignKeyDescription foreignKeyDescription = sender as DataTableForeignKeyDescription; var foreignKeyDescription = sender as DataTableForeignKeyDescription;
if( foreignKeyDescription != null ) if( foreignKeyDescription != null )
{ {
foreignKeyDescription.m_foreignKeyConstraint = e.NewValue as ForeignKeyConstraint;
foreignKeyDescription.UpdateValuePath(); foreignKeyDescription.UpdateValuePath();
foreignKeyDescription.UpdateItemsSource(); foreignKeyDescription.UpdateItemsSource();
} }
} }
private ForeignKeyConstraint m_foreignKeyConstraint;
#endregion #endregion
#region PRIVATE METHODS #region PRIVATE METHODS
@ -85,19 +75,21 @@ namespace Xceed.Wpf.DataGrid
private void UpdateValuePath() private void UpdateValuePath()
{ {
// Affect the ValuePath if it was not explicitly set or bound // 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 ) if( string.IsNullOrEmpty( this.ValuePath )
&& ( ( valuePath == DependencyProperty.UnsetValue ) && ( ( valuePath == DependencyProperty.UnsetValue )
|| ( valuePath == null ) ) ) || ( valuePath == null ) ) )
{ {
var foreignKeyConstraint = this.ForeignKeyConstraint;
// Affect the FieldName to the first RelatedColumn's name // Affect the FieldName to the first RelatedColumn's name
// if there is only one DataColumn in the RelatedColumns Collection // if there is only one DataColumn in the RelatedColumns Collection
if( ( m_foreignKeyConstraint != null ) if( ( foreignKeyConstraint != null )
&& ( m_foreignKeyConstraint.RelatedColumns != null ) && ( foreignKeyConstraint.RelatedColumns != null )
&& ( m_foreignKeyConstraint.RelatedColumns.Length == 1 ) ) && ( foreignKeyConstraint.RelatedColumns.Length == 1 ) )
{ {
string foreignFieldName = m_foreignKeyConstraint.RelatedColumns[ 0 ].ColumnName; var foreignFieldName = foreignKeyConstraint.RelatedColumns[ 0 ].ColumnName;
if( !string.IsNullOrEmpty( foreignFieldName ) ) if( !string.IsNullOrEmpty( foreignFieldName ) )
{ {
@ -109,11 +101,15 @@ namespace Xceed.Wpf.DataGrid
private void UpdateItemsSource() private void UpdateItemsSource()
{ {
if( ( m_foreignKeyConstraint != null ) var foreignKeyConstraint = this.ForeignKeyConstraint;
&& ( m_foreignKeyConstraint.RelatedTable != null ) ) if( foreignKeyConstraint == null )
{ return;
this.ItemsSource = m_foreignKeyConstraint.RelatedTable.DefaultView;
} var relatedTable = foreignKeyConstraint.RelatedTable;
if( relatedTable == null )
return;
this.ItemsSource = relatedTable.DefaultView;
} }
#endregion #endregion

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

@ -27,33 +27,136 @@ namespace Xceed.Wpf.DataGrid
{ {
public static class CollectionViewGroupExtensions 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; DataGridVirtualizingCollectionViewGroupBase dataGridVirtualizingCollectionViewGroupBase = collectionViewGroup as DataGridVirtualizingCollectionViewGroupBase;
DataGridCollectionViewGroup dataGridCollectionViewGroup = collectionViewGroup as DataGridCollectionViewGroup;
if( dataGridVirtualizingCollectionViewGroupBase != null ) 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 ) 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 dataGridCollectionViewGroup.Items;
}
return collectionViewGroup.Items; return collectionViewGroup.Items;
} }
public static int GetItemCount( this CollectionViewGroup collectionViewGroup ) public static int GetItemCount( this CollectionViewGroup collectionViewGroup )
{ {
if( collectionViewGroup is DataGridVirtualizingCollectionViewGroupBase ) var dataGridVirtualizingCollectionViewGroupBase = collectionViewGroup as DataGridVirtualizingCollectionViewGroupBase;
return ( ( DataGridVirtualizingCollectionViewGroupBase )collectionViewGroup ).VirtualItemCount; if( dataGridVirtualizingCollectionViewGroupBase != null )
return dataGridVirtualizingCollectionViewGroupBase.VirtualItemCount;
return collectionViewGroup.ItemCount; 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; 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 should only occur if the first leaf group encountered after the Reset call was empty.
this.MoveToNextNonEmptyLeafGroup(); this.MoveToNextNonEmptyLeafGroup();
@ -71,14 +71,14 @@ namespace Xceed.Wpf.DataGrid
} }
else else
{ {
if( ( m_currentGroup == null ) || ( m_currentGroup.RawItems == null ) ) if( ( m_currentGroup == null ) || ( m_currentGroup.RawItems.Count == 0 ) )
{ {
m_afterEnd = true; m_afterEnd = true;
} }
else else
{ {
//check indexes //check indexes
if( m_currentItemIndex < m_currentGroup.RawItems.Count ) if( m_currentItemIndex < m_currentGroup.RawItems.Count )
{ {
m_current = m_currentGroup.RawItems[ m_currentItemIndex ]; m_current = m_currentGroup.RawItems[ m_currentItemIndex ];
m_currentItemIndex++; m_currentItemIndex++;
@ -114,7 +114,7 @@ namespace Xceed.Wpf.DataGrid
{ {
m_currentGroup = this.MoveToFirstLeafGroup( m_currentGroup, index ); 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_currentItemIndex = 0;
m_currentGroupIndex.Clear(); m_currentGroupIndex.Clear();
m_currentGroup = ( m_collectionView.Count == 0 ) ? m_currentGroup = ( m_collectionView.Count == 0 ) ? null : this.MoveToFirstLeafGroup( m_collectionView.RootGroup, 0 );
null : this.MoveToFirstLeafGroup( m_collectionView.RootGroup, 0 );
} }
#endregion #endregion

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

@ -18,36 +18,46 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Text; using System.Collections.Specialized;
using System.Windows.Data;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using System.Windows.Data;
using Xceed.Wpf.DataGrid.Stats;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
internal class DataGridCollectionViewGroup : CollectionViewGroup, ICustomTypeDescriptor internal class DataGridCollectionViewGroup : CollectionViewGroup, ICustomTypeDescriptor
{ {
public DataGridCollectionViewGroup( object name, DataGridCollectionViewGroup parent, int unsortedIndex ) protected DataGridCollectionViewGroup( int capacity )
: base( name ) : this( null, null, 0, capacity, 4 )
{ {
m_parent = parent;
m_unsortedIndex = unsortedIndex;
} }
internal DataGridCollectionViewGroup( protected DataGridCollectionViewGroup( DataGridCollectionViewGroup template, DataGridCollectionViewGroup parent )
DataGridCollectionViewGroup template, : this( template.Name, parent, template.m_unsortedIndex, template.m_sortedRawItems.Count, template.m_subGroups.Count )
DataGridCollectionViewGroup parent )
: this( template.Name, parent, template.m_unsortedIndex )
{ {
m_nextSubGroupUnsortedIndex = template.m_nextSubGroupUnsortedIndex; m_nextSubGroupUnsortedIndex = template.m_nextSubGroupUnsortedIndex;
m_subGroupBy = template.m_subGroupBy; m_subGroupBy = template.m_subGroupBy;
}
if( template.m_groupsDictionary != null ) private DataGridCollectionViewGroup( object name, DataGridCollectionViewGroup parent, int unsortedIndex )
m_groupsDictionary = new Hashtable(); : this( name, parent, unsortedIndex, 4, 4 )
{
}
if( template.m_sortedRawItems != null ) private DataGridCollectionViewGroup( object name, DataGridCollectionViewGroup parent, int unsortedIndex, int rawCapacity, int groupCapacity )
m_sortedRawItems = new List<RawItem>( template.m_sortedRawItems.Count ); : 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 #region IsBottomLevel Property
@ -56,40 +66,24 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
// return true if .Items contain DataItem // returns true if .Items contain DataItem
return ( m_subGroupBy == null ); return ( m_subGroupBy == null );
} }
} }
#endregion IsBottomLevel Property #endregion
#region Items Property #region Items Property
public new ReadOnlyObservableCollection<object> Items internal new ReadOnlyObservableCollection<object> Items
{ {
get get
{ {
// The optimized list is only able to handle Items. When we are not at the bottom level, return m_optimizedItems;
// 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;
} }
} }
#endregion Items Property #endregion
#region ProtectedItems Property #region ProtectedItems Property
@ -101,7 +95,7 @@ namespace Xceed.Wpf.DataGrid
} }
} }
#endregion ProtectedItems Property #endregion
#region UnsortedIndex Property #region UnsortedIndex Property
@ -113,7 +107,7 @@ namespace Xceed.Wpf.DataGrid
} }
} }
#endregion UnsortedIndex Property #endregion
#region SubGroupBy Property #region SubGroupBy Property
@ -125,7 +119,7 @@ namespace Xceed.Wpf.DataGrid
} }
} }
#endregion SubGroupBy Property #endregion
#region Parent Property #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() protected virtual DataGridCollectionView GetCollectionView()
{ {
@ -147,34 +175,43 @@ namespace Xceed.Wpf.DataGrid
return null; 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(); DataGridCollectionView collectionView = this.GetCollectionView();
if( collectionView != null ) if( collectionView != null )
{ {
RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( dataItem ); RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( item );
if( rawItem != null ) if( rawItem != null )
{
return ( rawItem.ParentGroup == this ); return ( rawItem.ParentGroup == this );
}
} }
return false; 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(); DataGridCollectionView collectionView = this.GetCollectionView();
if( collectionView != null ) if( collectionView != null )
{ {
RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( dataItem ); RawItem rawItem = collectionView.GetFirstRawItemFromDataItem( item );
if( ( rawItem != null ) if( ( rawItem != null ) && ( rawItem.ParentGroup == this ) )
&& ( rawItem.ParentGroup == this ) )
{
return rawItem.SortedIndex; return rawItem.SortedIndex;
}
} }
return -1; return -1;
@ -184,24 +221,18 @@ namespace Xceed.Wpf.DataGrid
{ {
int index = 0; int index = 0;
DataGridCollectionViewGroup group = this; DataGridCollectionViewGroup group = this;
DataGridCollectionViewGroup parent = group; DataGridCollectionViewGroup parent = this.Parent;
DataGridCollectionViewGroup currentGroup = null;
if( parent != null )
parent = parent.Parent;
while( parent != null ) while( parent != null )
{ {
ReadOnlyObservableCollection<object> subGroups = parent.Items; foreach( object value in parent.ProtectedItems )
int subGroupCount = subGroups.Count;
DataGridCollectionViewGroup currentGroup = null;
for( int i = 0; i < subGroupCount; i++ )
{ {
currentGroup = subGroups[ i ] as DataGridCollectionViewGroup; if( value == group )
if( currentGroup == group )
break; break;
currentGroup = value as DataGridCollectionViewGroup;
index += currentGroup.GlobalRawItemCount; index += currentGroup.GlobalRawItemCount;
} }
@ -217,14 +248,10 @@ namespace Xceed.Wpf.DataGrid
bool oldIsBottomLevel = this.IsBottomLevel; bool oldIsBottomLevel = this.IsBottomLevel;
m_subGroupBy = groupBy; m_subGroupBy = groupBy;
if( m_subGroupBy != null )
{
if( m_groupsDictionary == null )
m_groupsDictionary = new Hashtable();
}
if( oldIsBottomLevel != this.IsBottomLevel ) if( oldIsBottomLevel != this.IsBottomLevel )
{
this.OnPropertyChanged( new PropertyChangedEventArgs( "IsBottomLevel" ) ); this.OnPropertyChanged( new PropertyChangedEventArgs( "IsBottomLevel" ) );
}
} }
internal DataGridCollectionViewGroup GetGroup( internal DataGridCollectionViewGroup GetGroup(
@ -232,7 +259,7 @@ namespace Xceed.Wpf.DataGrid
int level, int level,
CultureInfo culture, CultureInfo culture,
ObservableCollection<GroupDescription> groupByList, ObservableCollection<GroupDescription> groupByList,
GroupSortComparer[] groupSortComparers ) List<GroupSortComparer> groupSortComparers )
{ {
// If sortComparers is null, we are in massive group creation, no order check. // 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." ); 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 ); object groupName = m_subGroupBy.GroupNameFromItem( rawItem.DataItem, level, culture );
DataGridGroupDescription dataGridGroupDescription = m_subGroupBy as DataGridGroupDescription;
DataGridCollectionViewGroup group; DataGridCollectionViewGroup group;
if( dataGridGroupDescription != null ) if( ( m_subGroupBy is DataGridGroupDescription ) || ( m_subGroupBy is PropertyGroupDescription ) )
{ {
group = m_groupsDictionary[ DataGridCollectionViewGroup.GetHashKeyFromName( groupName ) ] m_subGroups.TryGetValue( DataGridCollectionViewGroup.GetHashKeyFromName( groupName ), out group );
as DataGridCollectionViewGroup;
} }
else 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; 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 ) ) if( m_subGroupBy.NamesMatch( tempGroup.Name, groupName ) )
{ {
group = tempGroup; group = tempGroup;
@ -267,8 +290,7 @@ namespace Xceed.Wpf.DataGrid
if( group == null ) if( group == null )
{ {
group = this.CreateSubGroup( group = this.CreateSubGroup( groupName, level, groupByList, groupSortComparers );
groupName, level, groupByList, groupSortComparers );
} }
return group; return group;
@ -276,32 +298,27 @@ namespace Xceed.Wpf.DataGrid
internal void SortItems( internal void SortItems(
SortDescriptionInfo[] sortDescriptionInfos, SortDescriptionInfo[] sortDescriptionInfos,
GroupSortComparer[] groupSortComparers, List<GroupSortComparer> groupSortComparers,
int level, int level,
List<RawItem> globalRawItems, List<RawItem> globalRawItems,
DataGridCollectionViewGroup newSortedGroup ) DataGridCollectionViewGroup newSortedGroup )
{ {
int itemCount = this.ItemCount; int itemCount = this.ProtectedItemCount;
if( itemCount == 0 ) if( itemCount == 0 )
return; return;
ObservableCollection<object> groupItems = this.ProtectedItems;
if( this.IsBottomLevel ) if( this.IsBottomLevel )
{ {
int[] indexes; int[] indexes;
indexes = new int[ itemCount + 1 ]; indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ ) for( int i = 0; i < itemCount; i++ )
{ {
indexes[ i ] = m_sortedRawItems[ i ].Index; indexes[ i ] = m_sortedRawItems[ i ].Index;
} }
// "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS] // "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
DataGridCollectionViewSort collectionViewSort = DataGridCollectionViewSort collectionViewSort = new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
collectionViewSort.Sort( itemCount ); collectionViewSort.Sort( itemCount );
int index = 0; int index = 0;
@ -315,17 +332,17 @@ namespace Xceed.Wpf.DataGrid
else else
{ {
int[] indexes; int[] indexes;
indexes = new int[ itemCount + 1 ]; indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ ) for( int i = 0; i < itemCount; i++ )
{ {
indexes[ i ] = 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] // "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
DataGridCollectionViewGroupSort collectionViewSort = DataGridCollectionViewGroupSort collectionViewSort = new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], subGroupsArray );
new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], this );
collectionViewSort.Sort( itemCount ); collectionViewSort.Sort( itemCount );
int index = 0; int index = 0;
@ -333,7 +350,7 @@ namespace Xceed.Wpf.DataGrid
for( int i = 1; i <= itemCount; i++ ) for( int i = 1; i <= itemCount; i++ )
{ {
DataGridCollectionViewGroup oldGroup = ( DataGridCollectionViewGroup )groupItems[ indexes[ i ] ]; DataGridCollectionViewGroup oldGroup = subGroupsArray[ indexes[ i ] ];
DataGridCollectionViewGroup newGroup = new DataGridCollectionViewGroup( oldGroup, newSortedGroup ); DataGridCollectionViewGroup newGroup = new DataGridCollectionViewGroup( oldGroup, newSortedGroup );
// Sort sub items // 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 ) int itemCount = this.ProtectedItemCount;
throw new ArgumentNullException( "comparer" );
ObservableCollection<object> items = this.ProtectedItems;
Debug.Assert( items.Count == this.ItemCount );
int low = 0; if( itemCount == 0 )
int hi = ( items.Count ) - 1; return;
while( low <= hi ) int[] indexes;
indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ )
{ {
int compareResult; indexes[ i ] = i;
int median = ( low + ( ( hi - low ) >> 1 ) ); }
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 // "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
if( medianGroup == value ) DataGridCollectionViewGroupSort collectionViewSort = new DataGridCollectionViewGroupSort( indexes, groupSortComparers[ level ], subGroupsArray );
{
if( low == hi )
return low;
median++; collectionViewSort.Sort( itemCount );
medianGroup = items[ median ] as DataGridCollectionViewGroup; level++;
} m_protectedItems.Clear();
try for( int i = 1; i <= itemCount; i++ )
{ {
compareResult = comparer.Compare( medianGroup, value ); DataGridCollectionViewGroup group = subGroupsArray[ indexes[ i ] ];
}
catch( Exception exception )
{
throw new InvalidOperationException( "IComparer has failed to compare the values.", exception );
}
if( compareResult == 0 ) // Sort sub groups
{ if( !group.IsBottomLevel )
return median;
}
if( compareResult < 0 )
{ {
low = median + 1; group.SortGroups( groupSortComparers, level );
}
else
{
hi = median - 1;
} }
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; 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 ) internal RawItem GetRawItemAtGlobalSortedIndex( int index )
{ {
if( this.IsBottomLevel ) if( this.IsBottomLevel )
@ -464,19 +430,14 @@ namespace Xceed.Wpf.DataGrid
} }
else else
{ {
int count = this.ItemCount; foreach( object value in this.ProtectedItems )
for( int i = 0; i < count; i++ )
{ {
DataGridCollectionViewGroup subGroups = this.ProtectedItems[ i ] as DataGridCollectionViewGroup; DataGridCollectionViewGroup subGroup = value as DataGridCollectionViewGroup;
if( subGroups == null )
throw new InvalidOperationException( "Sub-groups cannot be null (Nothing in Visual Basic)." );
int subGroupCount = subGroups.GlobalRawItemCount; int subGroupCount = subGroup.GlobalRawItemCount;
if( index < subGroupCount ) if( index < subGroupCount )
return subGroups.GetRawItemAtGlobalSortedIndex( index ); return subGroup.GetRawItemAtGlobalSortedIndex( index );
index -= subGroupCount; index -= subGroupCount;
} }
@ -499,9 +460,6 @@ namespace Xceed.Wpf.DataGrid
{ {
Debug.Assert( this.IsBottomLevel ); Debug.Assert( this.IsBottomLevel );
if( m_sortedRawItems == null )
m_sortedRawItems = new List<RawItem>( 4 );
m_globalRawItemCount++; m_globalRawItemCount++;
DataGridCollectionViewGroup parent = m_parent; DataGridCollectionViewGroup parent = m_parent;
@ -526,21 +484,13 @@ namespace Xceed.Wpf.DataGrid
this.ProtectedItems.Insert( index, rawItem.DataItem ); 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 ) internal virtual void RemoveRawItemAt( int index )
{ {
Debug.Assert( this.IsBottomLevel ); 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; return;
if( index != -1 ) if( index != -1 )
@ -554,8 +504,6 @@ namespace Xceed.Wpf.DataGrid
parent = parent.Parent; parent = parent.Parent;
} }
int count = m_sortedRawItems.Count;
for( int i = index + 1; i < count; i++ ) for( int i = index + 1; i < count; i++ )
{ {
m_sortedRawItems[ i ].SetSortedIndex( i - 1 ); m_sortedRawItems[ i ].SetSortedIndex( i - 1 );
@ -570,7 +518,9 @@ namespace Xceed.Wpf.DataGrid
this.ProtectedItems.RemoveAt( index ); this.ProtectedItems.RemoveAt( index );
if( ( this.ProtectedItemCount == 0 ) && ( m_parent != null ) ) if( ( this.ProtectedItemCount == 0 ) && ( m_parent != null ) )
{
m_parent.RemoveGroup( this ); m_parent.RemoveGroup( this );
}
} }
} }
@ -606,7 +556,7 @@ namespace Xceed.Wpf.DataGrid
if( m_sortedRawItems == null ) if( m_sortedRawItems == null )
return -1; // ~0 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 low = 0;
int hi = ( m_sortedRawItems.Count ) - 1; int hi = ( m_sortedRawItems.Count ) - 1;
@ -664,7 +614,7 @@ namespace Xceed.Wpf.DataGrid
if( view == null ) if( view == null )
return null; return null;
Stats.StatFunction statFunction = view.StatFunctions[ propertyName ]; StatFunction statFunction = view.StatFunctions[ propertyName ];
Debug.Assert( view != null ); Debug.Assert( view != null );
@ -674,12 +624,17 @@ namespace Xceed.Wpf.DataGrid
return this.GetStatFunctionResult( statFunction, view ).Value; 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 ) ) StatResult result;
this.CalculateStatFunctionValue( statFunction, view );
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. // 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(); 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
else
{
foreach( PropertyDescriptor statFunctionPropertyDescriptor in view.GetStatFunctionProperties() )
{ {
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( if( comparer == null )
new InvalidOperationException( Log.NotToolkitStr( "Statistical functions" ) ) 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 ) private static object GetHashKeyFromName( object groupName )
@ -723,7 +727,8 @@ namespace Xceed.Wpf.DataGrid
return groupName; 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. // If sortComparers is null, we are in massive group creation, no order check.
DataGridCollectionViewGroup group = new DataGridCollectionViewGroup( groupName, this, m_nextSubGroupUnsortedIndex ); DataGridCollectionViewGroup group = new DataGridCollectionViewGroup( groupName, this, m_nextSubGroupUnsortedIndex );
@ -745,7 +750,9 @@ namespace Xceed.Wpf.DataGrid
index = this.BinarySearchGroup( group, groupSortComparers[ level ] ); index = this.BinarySearchGroup( group, groupSortComparers[ level ] );
if( index < 0 ) if( index < 0 )
{
index = ~index; index = ~index;
}
} }
level++; level++;
@ -764,7 +771,7 @@ namespace Xceed.Wpf.DataGrid
{ {
Debug.Assert( !this.IsBottomLevel ); Debug.Assert( !this.IsBottomLevel );
m_groupsDictionary.Add( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ), group ); m_subGroups.Add( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ), group );
this.ProtectedItemCount++; this.ProtectedItemCount++;
this.ProtectedItems.Insert( index, group ); this.ProtectedItems.Insert( index, group );
} }
@ -783,12 +790,15 @@ namespace Xceed.Wpf.DataGrid
Debug.Assert( !this.IsBottomLevel ); Debug.Assert( !this.IsBottomLevel );
Debug.Assert( ( group.m_globalRawItemCount == 0 ) && ( group.ProtectedItemCount == 0 ) ); Debug.Assert( ( group.m_globalRawItemCount == 0 ) && ( group.ProtectedItemCount == 0 ) );
m_subGroups.Remove( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ) );
this.ProtectedItemCount--; this.ProtectedItemCount--;
m_groupsDictionary.Remove( DataGridCollectionViewGroup.GetHashKeyFromName( group.Name ) );
this.ProtectedItems.Remove( group ); this.ProtectedItems.Remove( group );
if( ( this.ProtectedItemCount == 0 ) && ( m_parent != null ) ) if( ( m_subGroups.Count == 0 ) && ( m_parent != null ) )
{
m_parent.RemoveGroup( this ); m_parent.RemoveGroup( this );
}
} }
#region ICustomTypeDescriptor Members #region ICustomTypeDescriptor Members
@ -893,20 +903,211 @@ namespace Xceed.Wpf.DataGrid
#endregion #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 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 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 GroupDescription m_subGroupBy;
private DataGridCollectionViewGroup m_parent; private readonly DataGridCollectionViewGroup m_parent;
private int m_unsortedIndex; private readonly int m_unsortedIndex;
private int m_nextSubGroupUnsortedIndex; 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.Diagnostics; using System.Diagnostics;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
internal class DataGridCollectionViewGroupRoot : DataGridCollectionViewGroup internal class DataGridCollectionViewGroupRoot : DataGridCollectionViewGroup
{ {
#region CONSTRUCTORS internal DataGridCollectionViewGroupRoot( DataGridCollectionView parentCollectionView )
: base( 128 )
public DataGridCollectionViewGroupRoot( DataGridCollectionView parentCollectionView )
: base( null, null, 0 )
{ {
if( parentCollectionView == null )
throw new ArgumentNullException( "parentCollectionView" );
m_parentCollectionView = parentCollectionView; m_parentCollectionView = parentCollectionView;
} }
@ -41,44 +34,28 @@ namespace Xceed.Wpf.DataGrid
m_parentCollectionView = template.m_parentCollectionView; m_parentCollectionView = template.m_parentCollectionView;
} }
#endregion CONSTRUCTORS
#region PROTECTED METHODS
protected override DataGridCollectionView GetCollectionView() protected override DataGridCollectionView GetCollectionView()
{ {
return m_parentCollectionView; return m_parentCollectionView;
} }
#endregion PROTECTED METHODS
#region INTERNAL METHODS
internal void SortRootRawItems( SortDescriptionInfo[] sortDescriptionInfos, List<RawItem> globalRawItems ) internal void SortRootRawItems( SortDescriptionInfo[] sortDescriptionInfos, List<RawItem> globalRawItems )
{ {
Debug.Assert( this.IsBottomLevel ); 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 ) if( itemCount == 0 )
return; return;
int[] indexes; int[] indexes;
indexes = new int[ itemCount + 1 ]; indexes = new int[ itemCount + 1 ];
for( int i = 0; i < itemCount; i++ ) 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] // "Weak heap sort" sort array[0..NUM_ELEMENTS-1] to array[1..NUM_ELEMENTS]
DataGridCollectionViewSort collectionViewSort = DataGridCollectionViewSort collectionViewSort = new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
new DataGridCollectionViewSort( indexes, sortDescriptionInfos );
collectionViewSort.Sort( itemCount ); collectionViewSort.Sort( itemCount );
int index = 0; int index = 0;
@ -87,22 +64,15 @@ namespace Xceed.Wpf.DataGrid
{ {
RawItem newRawItem = globalRawItems[ indexes[ i ] ]; RawItem newRawItem = globalRawItems[ indexes[ i ] ];
newRawItem.SetSortedIndex( index ); newRawItem.SetSortedIndex( index );
rawItems[ index ] = newRawItem; m_sortedRawItems[ index ] = newRawItem;
index++; index++;
} }
} }
#endregion INTERNAL METHODS
#region RawItem management for BottomLevel
internal override void InsertRawItem( int index, RawItem rawItem ) internal override void InsertRawItem( int index, RawItem rawItem )
{ {
Debug.Assert( this.IsBottomLevel ); Debug.Assert( this.IsBottomLevel );
if( m_sortedRawItems == null )
m_sortedRawItems = new List<RawItem>( 128 );
m_globalRawItemCount++; m_globalRawItemCount++;
int count = m_sortedRawItems.Count; int count = m_sortedRawItems.Count;
@ -119,11 +89,15 @@ namespace Xceed.Wpf.DataGrid
internal override void RemoveRawItemAt( int index ) internal override void RemoveRawItemAt( int index )
{ {
Debug.Assert( this.IsBottomLevel ); Debug.Assert( this.IsBottomLevel );
Debug.Assert( m_sortedRawItems.Count > 0 );
int count = m_sortedRawItems.Count;
if( count == 0 )
return;
if( index != -1 ) if( index != -1 )
{ {
m_globalRawItemCount--; m_globalRawItemCount--;
int count = m_sortedRawItems.Count;
for( int i = index + 1; i < count; i++ ) 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; 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 internal class DataGridCollectionViewGroupSort : IndexWeakHeapSort
{ {
public DataGridCollectionViewGroupSort( public DataGridCollectionViewGroupSort( int[] dataIndexArray, GroupSortComparer groupSortedComparer, DataGridCollectionViewGroup[] protectedItems )
int[] dataIndexArray,
GroupSortComparer groupSortedComparer,
DataGridCollectionViewGroup parentGroup )
: base( dataIndexArray ) : base( dataIndexArray )
{ {
if( parentGroup == null )
throw new ArgumentNullException( "parentGroup" );
if( groupSortedComparer == null ) if( groupSortedComparer == null )
throw new ArgumentNullException( "groupSortedComparer" ); throw new ArgumentNullException( "groupSortedComparer" );
m_groupSortedComparer = groupSortedComparer; m_groupSortedComparer = groupSortedComparer;
m_groups = parentGroup.ProtectedItems; m_groups = protectedItems;
} }
public override int Compare( int xDataIndex, int yDataIndex ) public override int Compare( int xDataIndex, int yDataIndex )
{ {
DataGridCollectionViewGroup xGroup = m_groups[ xDataIndex ] as DataGridCollectionViewGroup; DataGridCollectionViewGroup xGroup = m_groups[ xDataIndex ];
DataGridCollectionViewGroup yGroup = m_groups[ yDataIndex ] as DataGridCollectionViewGroup; DataGridCollectionViewGroup yGroup = m_groups[ yDataIndex ];
return m_groupSortedComparer.Compare( xGroup, yGroup ); return m_groupSortedComparer.Compare( xGroup, yGroup );
} }
private GroupSortComparer m_groupSortedComparer; 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;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Data; 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; using Xceed.Wpf.DataGrid.Stats;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
@ -64,7 +60,7 @@ namespace Xceed.Wpf.DataGrid
#region StatFunctions Property #region StatFunctions Property
internal ObservableCollection<Stats.StatFunction> StatFunctions internal ObservableCollection<StatFunction> StatFunctions
{ {
get get
{ {
@ -72,7 +68,7 @@ namespace Xceed.Wpf.DataGrid
} }
} }
private ObservableCollection<Stats.StatFunction> m_statFunctions; private StatFunctionCollection m_statFunctions;
#endregion StatFunctions Property #endregion StatFunctions Property
@ -115,11 +111,10 @@ namespace Xceed.Wpf.DataGrid
DataGridCollectionView dataGridCollectionView = currentView as DataGridCollectionView; DataGridCollectionView dataGridCollectionView = currentView as DataGridCollectionView;
dataGridCollectionView.StatFunctions.Clear(); 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; 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 ) internal void OnEditCanceled( DataGridItemEventArgs e )
{ {
if( this.EditCanceled != null ) if( this.EditCanceled != null )
{
this.EditCanceled( this, e ); this.EditCanceled( this, e );
}
} }
public event EventHandler<DataGridItemCancelEventArgs> CommittingEdit; public event EventHandler<DataGridItemCancelEventArgs> CommittingEdit;

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

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

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

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

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

@ -15,15 +15,12 @@
***********************************************************************************/ ***********************************************************************************/
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections; using System.Collections;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using Xceed.Wpf.DataGrid.Converters;
using System.Windows.Data; using System.Windows.Data;
using Xceed.Wpf.DataGrid.Converters;
using Xceed.Wpf.DataGrid.FilterCriteria; using Xceed.Wpf.DataGrid.FilterCriteria;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
@ -31,22 +28,25 @@ namespace Xceed.Wpf.DataGrid
public abstract partial class DataGridItemPropertyBase : INotifyPropertyChanged, ICloneable public abstract partial class DataGridItemPropertyBase : INotifyPropertyChanged, ICloneable
{ {
#region CONSTRUCTORS
protected DataGridItemPropertyBase() protected DataGridItemPropertyBase()
{ {
this.Browsable = true;
} }
protected DataGridItemPropertyBase( DataGridItemPropertyBase template ) protected DataGridItemPropertyBase( DataGridItemPropertyBase template )
: this()
{ {
m_name = template.m_name; m_name = template.m_name;
m_dataType = template.m_dataType; m_dataType = template.m_dataType;
m_title = template.m_title; m_title = template.m_title;
m_readOnly = template.m_readOnly; m_synonym = template.m_synonym;
m_overrideReadOnlyForInsertion = template.m_overrideReadOnlyForInsertion; m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ];
m_isASubRelationship = template.m_isASubRelationship; m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ];
m_browsable = template.m_browsable; m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ] = template.m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ];
m_calculateDistinctValues = template.m_calculateDistinctValues; 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_converter = template.m_converter;
m_converterCulture = template.m_converterCulture; m_converterCulture = template.m_converterCulture;
m_converterParameter = template.m_converterParameter; m_converterParameter = template.m_converterParameter;
@ -86,20 +86,18 @@ namespace Xceed.Wpf.DataGrid
if( isReadOnly.HasValue ) if( isReadOnly.HasValue )
{ {
m_readOnly = isReadOnly.Value; this.SetIsReadOnly( isReadOnly.Value );
} }
m_overrideReadOnlyForInsertion = overrideReadOnlyForInsertion; this.SetOverrideReadOnlyForInsertion( overrideReadOnlyForInsertion );
m_dataType = dataType; m_dataType = dataType;
if( isASubRelationship != null ) if( isASubRelationship != null )
{ {
m_isASubRelationship = isASubRelationship; this.SetIsASubRelationship( isASubRelationship );
} }
} }
#endregion CONSTRUCTORS
#region Name Property #region Name Property
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )] [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Usage", "CA2208:InstantiateArgumentExceptionsCorrectly" )]
@ -114,7 +112,7 @@ namespace Xceed.Wpf.DataGrid
if( string.IsNullOrEmpty( value ) ) if( string.IsNullOrEmpty( value ) )
throw new ArgumentException( "Name is null (Nothing in Visual Basic) or empty.", "Name" ); 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." ); throw new InvalidOperationException( "An attempt was made to change the name of a property already added to a containing collection." );
m_name = value; m_name = value;
@ -136,7 +134,7 @@ namespace Xceed.Wpf.DataGrid
} }
set 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." ); throw new InvalidOperationException( "An attempt was made to change the DataType of a property already added to a containing collection." );
this.SetDataType( value ); this.SetDataType( value );
@ -161,11 +159,11 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_readOnly; return m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ];
} }
set 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." ); throw new InvalidOperationException( "An attempt was made to change the IsReadOnly property of a DataGridItemProperty already added to a containing collection." );
this.SetIsReadOnly( value ); this.SetIsReadOnly( value );
@ -174,11 +172,9 @@ namespace Xceed.Wpf.DataGrid
internal void SetIsReadOnly( bool isReadOnly ) internal void SetIsReadOnly( bool isReadOnly )
{ {
m_readOnly = isReadOnly; m_flags[ DataGridItemPropertyBaseFlags.IsReadOnly ] = isReadOnly;
} }
private bool m_readOnly;
#endregion IsReadOnly Property #endregion IsReadOnly Property
#region OverrideReadOnlyForInsertion Property #region OverrideReadOnlyForInsertion Property
@ -187,11 +183,14 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_overrideReadOnlyForInsertion; if( !m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertionSet ] )
return null;
return m_flags[ DataGridItemPropertyBaseFlags.IsOverrideReadOnlyForInsertion ];
} }
set 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." ); throw new InvalidOperationException( "An attempt was made to change the OverrideReadOnlyForInsertion property of a DataGridItemProperty already added to a containing collection." );
this.SetOverrideReadOnlyForInsertion( value ); this.SetOverrideReadOnlyForInsertion( value );
@ -200,11 +199,18 @@ namespace Xceed.Wpf.DataGrid
internal void SetOverrideReadOnlyForInsertion( Nullable<bool> overrideReadOnlyForInsertion ) 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 #endregion OverrideReadOnlyForInsertion Property
#region IsASubRelationship Property #region IsASubRelationship Property
@ -213,24 +219,37 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
if( m_isASubRelationship == null ) if( m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationshipSet ] )
{ return m_flags[ DataGridItemPropertyBaseFlags.IsASubRelationship ];
if( m_dataType == null )
return false;
bool isASubRelationship = ItemsSourceHelper.IsASubRelationship( m_dataType ); if( m_dataType == null )
return false;
if( m_initialized ) bool isASubRelationship = ItemsSourceHelper.IsASubRelationship( m_dataType );
m_isASubRelationship = isASubRelationship;
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 #endregion IsASubRelationship Property
@ -256,6 +275,33 @@ namespace Xceed.Wpf.DataGrid
#endregion Title Property #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 #region SortComparer Property
public IComparer SortComparer public IComparer SortComparer
@ -284,7 +330,7 @@ namespace Xceed.Wpf.DataGrid
} }
set 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." ); throw new InvalidOperationException( "An attempt was made to change the Converter property of a DataGridItemProperty already added to a containing collection." );
m_converter = value; m_converter = value;
@ -293,7 +339,7 @@ namespace Xceed.Wpf.DataGrid
internal IValueConverter GetBindingConverter( object sourceItem ) 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." ); throw new InvalidOperationException( "An attempt was made to apply a binding to a DataGridItemProperty that has not be added to the ItemProperties collection." );
if( m_bindingConverter == null ) if( m_bindingConverter == null )
@ -328,7 +374,7 @@ namespace Xceed.Wpf.DataGrid
} }
set 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." ); throw new InvalidOperationException( "An attempt was made to change the ConverterCulture property of a DataGridItemProperty already added to a containing collection." );
m_converterCulture = value; m_converterCulture = value;
@ -349,7 +395,7 @@ namespace Xceed.Wpf.DataGrid
} }
set 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." ); throw new InvalidOperationException( "An attempt was made to change the ConverterParameter property of a DataGridItemProperty already added to a containing collection." );
m_converterParameter = value; m_converterParameter = value;
@ -409,18 +455,6 @@ namespace Xceed.Wpf.DataGrid
#endregion FilterCriterion Property #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 #region CalculateDistinctValues Property
public bool CalculateDistinctValues public bool CalculateDistinctValues
@ -428,20 +462,20 @@ namespace Xceed.Wpf.DataGrid
get get
{ {
// Always activate DistinctValues if not explicitly specified // Always activate DistinctValues if not explicitly specified
if( !m_isCalculateDistinctValuesInitialized ) if( !this.IsCalculateDistinctValuesInitialized )
return true; return true;
return m_calculateDistinctValues; return m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ];
} }
set set
{ {
if( m_calculateDistinctValues != value ) if( value != m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] )
{ {
m_calculateDistinctValues = value; m_flags[ DataGridItemPropertyBaseFlags.CalculateDistinctValues ] = value;
this.OnPropertyChanged( "CalculateDistinctValues" ); this.OnPropertyChanged( "CalculateDistinctValues" );
} }
m_isCalculateDistinctValuesInitialized = true; this.IsCalculateDistinctValuesInitialized = true;
} }
} }
@ -449,17 +483,14 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_isCalculateDistinctValuesInitialized; return m_flags[ DataGridItemPropertyBaseFlags.IsCalculateDistinctValuesInitialized ];
} }
set set
{ {
m_isCalculateDistinctValuesInitialized = value; m_flags[ DataGridItemPropertyBaseFlags.IsCalculateDistinctValuesInitialized ] = value;
} }
} }
private bool m_calculateDistinctValues; // = null;
private bool m_isCalculateDistinctValuesInitialized;
#endregion CalculateDistinctValues Property #endregion CalculateDistinctValues Property
#region MaxDistinctValues Property #region MaxDistinctValues Property
@ -484,7 +515,7 @@ namespace Xceed.Wpf.DataGrid
#endregion MaxDistinctValues Property #endregion MaxDistinctValues Property
#region DistinctValuesSortComparer #region DistinctValuesSortComparer Property
public IComparer DistinctValuesSortComparer public IComparer DistinctValuesSortComparer
{ {
@ -494,7 +525,7 @@ namespace Xceed.Wpf.DataGrid
#endregion #endregion
#region DistinctValuesEqualityComparer #region DistinctValuesEqualityComparer Property
public IEqualityComparer DistinctValuesEqualityComparer public IEqualityComparer DistinctValuesEqualityComparer
{ {
@ -510,18 +541,16 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_initialized; return m_flags[ DataGridItemPropertyBaseFlags.IsInitialized ];
} }
set set
{ {
Debug.Assert( value ); Debug.Assert( value );
m_initialized = value; m_flags[ DataGridItemPropertyBaseFlags.IsInitialized ] = value;
} }
} }
private bool m_initialized;
#endregion Initialized Property #endregion Initialized Property
#region Browsable Property #region Browsable Property
@ -532,48 +561,16 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_browsable; return m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ];
} }
set set
{ {
m_browsable = value; m_flags[ DataGridItemPropertyBaseFlags.IsBrowsable ] = value;
} }
} }
private bool m_browsable = true;
#endregion Browsable Property #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 #region ForeignKeyDescription Property
public DataGridForeignKeyDescription ForeignKeyDescription public DataGridForeignKeyDescription ForeignKeyDescription
@ -614,6 +611,8 @@ namespace Xceed.Wpf.DataGrid
if( m_groupSortStatResultPropertyName != value ) if( m_groupSortStatResultPropertyName != value )
{ {
m_groupSortStatResultPropertyName = value; m_groupSortStatResultPropertyName = value;
this.OnPropertyChanged( "GroupSortStatResultPropertyName" );
} }
} }
} }
@ -632,7 +631,49 @@ namespace Xceed.Wpf.DataGrid
#endregion GroupSortStatResultComparer Property #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 ) public object GetValue( object component )
{ {
@ -661,11 +702,11 @@ namespace Xceed.Wpf.DataGrid
UnboundDataItem unboundDataItem = component as UnboundDataItem; UnboundDataItem unboundDataItem = component as UnboundDataItem;
if( unboundDataItem != null ) if( unboundDataItem != null )
{
component = unboundDataItem.DataItem; component = unboundDataItem.DataItem;
}
bool isReadOnly = ( this.OverrideReadOnlyForInsertion.HasValue && this.OverrideReadOnlyForInsertion.Value ) bool isReadOnly = ( this.OverrideReadOnlyForInsertion.HasValue && this.OverrideReadOnlyForInsertion.Value ) ? false : this.IsReadOnly;
? false
: this.IsReadOnly;
if( isReadOnly ) if( isReadOnly )
throw new InvalidOperationException( "An attempt was made to set a read-only property." ); throw new InvalidOperationException( "An attempt was made to set a read-only property." );
@ -699,10 +740,6 @@ namespace Xceed.Wpf.DataGrid
} }
#endif #endif
#endregion PUBLIC METHODS
#region PROTECTED METHODS
protected abstract object GetValueCore( object component ); protected abstract object GetValueCore( object component );
protected virtual void SetValueCore( object component, object value ) protected virtual void SetValueCore( object component, object value )
@ -710,10 +747,6 @@ namespace Xceed.Wpf.DataGrid
this.OnValueChanged( new ValueChangedEventArgs( component ) ); this.OnValueChanged( new ValueChangedEventArgs( component ) );
} }
#endregion PROTECTED METHODS
#region INTERNAL METHODS
internal PropertyDescriptorFromItemPropertyBase GetPropertyDescriptorForBinding() internal PropertyDescriptorFromItemPropertyBase GetPropertyDescriptorForBinding()
{ {
if( m_propertyDescriptorFromItemProperty == null ) if( m_propertyDescriptorFromItemProperty == null )
@ -731,8 +764,6 @@ namespace Xceed.Wpf.DataGrid
{ {
} }
#endregion INTERNAL METHODS
#region INotifyPropertyChanged Members #region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
@ -745,11 +776,8 @@ namespace Xceed.Wpf.DataGrid
#endregion #endregion
#region PRIVATE FIELDS
private PropertyDescriptorFromItemPropertyBase m_propertyDescriptorFromItemProperty; private PropertyDescriptorFromItemPropertyBase m_propertyDescriptorFromItemProperty;
private BitFlags m_flags;
#endregion PRIVATE FIELDS
internal class ValueChangedEventArgs : EventArgs internal class ValueChangedEventArgs : EventArgs
{ {
@ -764,5 +792,67 @@ namespace Xceed.Wpf.DataGrid
private set; 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.FilterCriterionChanged -= new EventHandler( DataGridItemProperty_FilterCriterionChanged );
oldItem.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged ); 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.ValueChanged += new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged += new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
item.SetUnspecifiedPropertiesValues( this ); item.SetUnspecifiedPropertiesValues( this );
try try
@ -127,6 +129,7 @@ namespace Xceed.Wpf.DataGrid
catch catch
{ {
item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged ); item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
throw; throw;
} }
@ -144,6 +147,7 @@ namespace Xceed.Wpf.DataGrid
oldItem.FilterCriterionChanged -= new EventHandler( DataGridItemProperty_FilterCriterionChanged ); oldItem.FilterCriterionChanged -= new EventHandler( DataGridItemProperty_FilterCriterionChanged );
oldItem.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged ); oldItem.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
oldItem.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
} }
item.FilterCriterionChanged += new EventHandler( DataGridItemProperty_FilterCriterionChanged ); item.FilterCriterionChanged += new EventHandler( DataGridItemProperty_FilterCriterionChanged );
@ -165,6 +169,7 @@ namespace Xceed.Wpf.DataGrid
} }
item.ValueChanged += new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged ); item.ValueChanged += new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged += new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
item.SetUnspecifiedPropertiesValues( this ); item.SetUnspecifiedPropertiesValues( this );
item.Initialized = true; item.Initialized = true;
@ -180,6 +185,7 @@ namespace Xceed.Wpf.DataGrid
catch catch
{ {
item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged ); item.ValueChanged -= new EventHandler<DataGridItemPropertyBase.ValueChangedEventArgs>( DataGridItemProperty_ValueChanged );
item.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
item.Initialized = false; item.Initialized = false;
if( item is DataGridUnboundItemProperty ) if( item is DataGridUnboundItemProperty )
@ -255,6 +261,7 @@ namespace Xceed.Wpf.DataGrid
item.FilterCriterionChanged -= this.DataGridItemProperty_FilterCriterionChanged; item.FilterCriterionChanged -= this.DataGridItemProperty_FilterCriterionChanged;
item.ValueChanged -= this.DataGridItemProperty_ValueChanged; item.ValueChanged -= this.DataGridItemProperty_ValueChanged;
item.PropertyChanged -= new PropertyChangedEventHandler( OnDataGridItemProperty_PropertyChanged );
} }
} }
@ -308,7 +315,9 @@ namespace Xceed.Wpf.DataGrid
internal void SuspendUnboundItemPropertyChanged( object component ) internal void SuspendUnboundItemPropertyChanged( object component )
{ {
if( m_unboundItemPropertyChangedSuspended == null ) if( m_unboundItemPropertyChangedSuspended == null )
{
m_unboundItemPropertyChangedSuspended = new Hashtable( 1 ); m_unboundItemPropertyChangedSuspended = new Hashtable( 1 );
}
m_unboundItemPropertyChangedSuspended[ component ] = DBNull.Value; m_unboundItemPropertyChangedSuspended[ component ] = DBNull.Value;
} }
@ -324,7 +333,9 @@ namespace Xceed.Wpf.DataGrid
m_unboundItemPropertyChangedSuspended.Remove( component ); m_unboundItemPropertyChangedSuspended.Remove( component );
if( m_unboundItemPropertyChangedSuspended.Count == 0 ) if( m_unboundItemPropertyChangedSuspended.Count == 0 )
{
m_unboundItemPropertyChangedSuspended = null; m_unboundItemPropertyChangedSuspended = null;
}
this.RefreshUnboundItemProperty( component ); 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 List<DataGridItemPropertyBase> m_defaultItemProperties;
private Type m_itemType; private Type m_itemType;
private int m_unboundItemPropertyCount; 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 internal class DataGridLINQPageManager : DataGridPageManagerBase
{ {
#region CONSTRUCTORS
public DataGridLINQPageManager( DataGridVirtualizingQueryableCollectionView collectionView, object syncRoot, bool supportsPrimaryKeyOptimizations ) public DataGridLINQPageManager( DataGridVirtualizingQueryableCollectionView collectionView, object syncRoot, bool supportsPrimaryKeyOptimizations )
: base( collectionView ) : base( collectionView )
{ {
@ -33,9 +31,11 @@ namespace Xceed.Wpf.DataGrid
m_syncRoot = syncRoot; m_syncRoot = syncRoot;
} }
#endregion CONSTRUCTORS protected override void DisposeCore()
{
#region DATA VIRTUALIZATION m_syncRoot = null;
base.DisposeCore();
}
protected override int OnQueryItemCountCore( VirtualList virtualList ) 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 } ); 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 ) private void AsyncGatherItems( object workItem )
{ {
@ -91,8 +104,8 @@ namespace Xceed.Wpf.DataGrid
return; return;
IQueryable queryable = ( IQueryable )parameters[ 1 ]; IQueryable queryable = ( IQueryable )parameters[ 1 ];
int requestedItemCount = queryInfo.RequestedItemCount;
object[] items = new object[ queryInfo.RequestedItemCount ]; object[] items = new object[ requestedItemCount ];
System.Collections.IEnumerator enumerator; System.Collections.IEnumerator enumerator;
@ -104,22 +117,23 @@ namespace Xceed.Wpf.DataGrid
try 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(); 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; int i = 0;
while( enumerator.MoveNext() ) while( enumerator.MoveNext() && ( i < requestedItemCount ) )
{ {
object current = enumerator.Current; object current = enumerator.Current;
if( current != null ) if( current != null )
{
items[ i ] = enumerator.Current; items[ i ] = enumerator.Current;
i++;
i++; }
} }
} }
catch( Exception exception ) 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 ]; bool queryableWasReversed = ( bool )parameters[ 2 ];
if( queryableWasReversed ) if( queryableWasReversed )
@ -139,33 +165,7 @@ namespace Xceed.Wpf.DataGrid
queryInfo.EndQuery( items ); 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 object m_syncRoot;
private bool m_supportsPrimaryKeyOptimizations; 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++; m_parentCollection.m_deferResortCount++;
} }
#region IDisposable Members #region IDisposable Members
public void Dispose() public void Dispose()

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

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

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

@ -15,20 +15,10 @@
***********************************************************************************/ ***********************************************************************************/
using System; 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;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Data;
using Xceed.Utils.Collections;
using Xceed.Utils.Data;
using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -47,7 +37,6 @@ namespace Xceed.Wpf.DataGrid
internal DataGridVirtualizingCollectionViewBase( object sourceModel, Type itemType, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount ) internal DataGridVirtualizingCollectionViewBase( object sourceModel, Type itemType, bool autoCreateItemProperties, int pageSize, int maxRealizedItemCount )
: base( sourceModel, null, itemType, autoCreateItemProperties, false, false ) : base( sourceModel, null, itemType, autoCreateItemProperties, false, false )
{ {
if( itemType == null ) if( itemType == null )
itemType = typeof( object ); itemType = typeof( object );
@ -68,7 +57,7 @@ namespace Xceed.Wpf.DataGrid
internal override DataGridCollectionViewBase CreateDetailDataGridCollectionViewBase( internal override DataGridCollectionViewBase CreateDetailDataGridCollectionViewBase(
IEnumerable detailDataSource, IEnumerable detailDataSource,
DataGridDetailDescription parentDetailDescription, DataGridDetailDescription parentDetailDescription,
DataGridCollectionViewBase rootDataGridCollectionViewBase ) DataGridCollectionViewBase parentDataGridCollectionViewBase )
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -82,7 +71,6 @@ namespace Xceed.Wpf.DataGrid
get get
{ {
bool canGroup = true; bool canGroup = true;
return canGroup; return canGroup;
} }
} }
@ -368,7 +356,9 @@ namespace Xceed.Wpf.DataGrid
m_maxRealizedItemCount = value; m_maxRealizedItemCount = value;
if( value < this.PageSize ) if( value < this.PageSize )
{
value = this.PageSize; value = this.PageSize;
}
// Cannot modify this PageManager property. Must Refresh which will recreate the CollectionViewGroupRoot // Cannot modify this PageManager property. Must Refresh which will recreate the CollectionViewGroupRoot
// and the DataGridVirtualPageManagerBase taking the new pageSize into account. // and the DataGridVirtualPageManagerBase taking the new pageSize into account.
@ -925,7 +915,11 @@ namespace Xceed.Wpf.DataGrid
} }
if( sendResetNotification ) if( sendResetNotification )
{
this.OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) ); 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 internal class DeferredOperation
{ {
#region CONSTRUCTORS internal static DeferredOperation RefreshDistinctValuesOperation = new DeferredOperation( DeferredOperationAction.RefreshDistincValues, false );
public DeferredOperation( internal static DeferredOperation RefreshDistinctValuesOperationWithFilteredItemsChanged = new DeferredOperation( DeferredOperationAction.RefreshDistincValues, true );
DeferredOperationAction action,
bool filteredItemsChanged ) public DeferredOperation( DeferredOperationAction action, bool filteredItemsChanged )
: this( action, -1, -1, null ) : this( action, -1, -1, null )
{ {
m_filteredItemsChanged = filteredItemsChanged; m_filteredItemsChanged = filteredItemsChanged;
} }
public DeferredOperation( public DeferredOperation( DeferredOperationAction action, object dataItem )
DeferredOperationAction action, {
int startingIndex, m_action = action;
IList items ) 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 ) : this( action, -1, startingIndex, items )
{ {
} }
public DeferredOperation( public DeferredOperation( DeferredOperationAction action, int newSourceItemCount, int startingIndex, IList items )
DeferredOperationAction action,
int newSourceItemCount,
int startingIndex,
IList items )
{ {
// newSourceItemCount is for when we are adding item in a IBindingList // 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. // 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( public DeferredOperation( DeferredOperationAction action, int newSourceItemCount, int newStartingIndex, IList newItems, int oldStartingIndex, IList oldItems )
DeferredOperationAction action,
int newSourceItemCount,
int newStartingIndex,
IList newItems,
int oldStartingIndex,
IList oldItems )
{ {
// newSourceItemCount is for when we are adding item in a IBindingList // 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. // 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; m_oldStartingIndex = oldStartingIndex;
} }
#endregion CONSTRUCTORS
#region Action Property #region Action Property
public DeferredOperationAction Action public DeferredOperationAction Action
@ -186,6 +183,20 @@ namespace Xceed.Wpf.DataGrid
#endregion OldItems Property #endregion OldItems Property
#region DataItem Property
public object DataItem
{
get
{
return m_dataItem;
}
}
private object m_dataItem;
#endregion
#region FilteredItemsChanged Property #region FilteredItemsChanged Property
public bool FilteredItemsChanged public bool FilteredItemsChanged
@ -210,7 +221,9 @@ namespace Xceed.Wpf.DataGrid
Refresh = 5, Refresh = 5,
Resort = 6, Resort = 6,
Regroup = 7, 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Windows.Threading;
using System.Diagnostics; using System.Diagnostics;
using System.Collections.ObjectModel; using System.Windows.Threading;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
internal sealed class DeferredOperationManager
internal class DeferredOperationManager
{ {
public DeferredOperationManager( #region Static Fields
DataGridCollectionViewBase collectionViewToUpdate,
Dispatcher dispatcher, private static readonly TimeSpan MaxProcessDuration = TimeSpan.FromMilliseconds( 100d );
bool postPendingRefreshWithoutDispatching ) 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 ) if( postPendingRefreshWithoutDispatching )
{
this.Add( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ) ); this.Add( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ) );
}
m_dispatcher = dispatcher; m_dispatcher = dispatcher;
} }
@ -49,7 +53,7 @@ namespace Xceed.Wpf.DataGrid
{ {
lock( this ) 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 #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() public void ClearInvalidatedGroups()
{ {
lock( this ) lock( this )
@ -144,9 +174,11 @@ namespace Xceed.Wpf.DataGrid
{ {
m_dispatcherOperation.Abort(); m_dispatcherOperation.Abort();
m_dispatcherOperation = null; 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 ) lock( this )
{ {
if( ( m_dispatcherOperation != null ) && ( m_invalidatedGroups == null ) ) if( ( m_dispatcherOperation != null ) && ( m_invalidatedGroups.Count == 0 ) )
{ {
m_dispatcherOperation.Abort(); m_dispatcherOperation.Abort();
m_dispatcherOperation = null; m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
} }
m_pendingFlags[ -1 ] = false; m_pendingFlags[ -1 ] = false;
m_deferredOperations = null; m_deferredOperations.Clear();
} }
} }
public void PurgeAddWithRemoveOrReplace() public void PurgeAddWithRemoveOrReplace()
{ {
if( m_deferredOperations == null )
return;
if( m_deferredOperations.Count >= 2 ) if( m_deferredOperations.Count >= 2 )
{ {
DeferredOperation addOperation = m_deferredOperations[ 0 ]; DeferredOperation addOperation = m_deferredOperations[ 0 ];
@ -205,7 +236,9 @@ namespace Xceed.Wpf.DataGrid
lastIndexToRemove = i; lastIndexToRemove = i;
if( removed ) if( removed )
{
firstIndexToRemove = 0; firstIndexToRemove = 0;
}
} }
else else
{ {
@ -223,9 +256,7 @@ namespace Xceed.Wpf.DataGrid
if( lastIndexToRemove > -1 ) if( lastIndexToRemove > -1 )
{ {
m_deferredOperations.RemoveRange( m_deferredOperations.RemoveRange( firstIndexToRemove, ( lastIndexToRemove - firstIndexToRemove ) + 1 );
firstIndexToRemove,
( lastIndexToRemove - firstIndexToRemove ) + 1 );
} }
} }
} }
@ -242,7 +273,7 @@ namespace Xceed.Wpf.DataGrid
case DeferredOperation.DeferredOperationAction.Refresh: case DeferredOperation.DeferredOperationAction.Refresh:
{ {
this.RefreshPending = true; this.RefreshPending = true;
m_deferredOperations = null; m_deferredOperations.Clear();
break; break;
} }
@ -274,22 +305,25 @@ namespace Xceed.Wpf.DataGrid
default: default:
{ {
if( m_deferredOperations == null )
m_deferredOperations = new List<DeferredOperation>();
m_deferredOperations.Add( operation ); m_deferredOperations.Add( operation );
m_hasNewOperationsSinceStartTime = true;
if( this.DeferProcessOfInvalidatedGroupStats )
{
m_deferredOperationsToProcess++;
}
break; break;
} }
} }
if( ( m_dispatcher != null ) && ( m_dispatcherOperation == null ) ) if( ( m_dispatcher != null ) && ( m_dispatcherOperation == null ) )
{ {
Debug.Assert( m_collectionViewToUpdate.Loaded ); Debug.Assert( m_collectionView.Loaded );
m_dispatcherOperation = m_dispatcher.BeginInvoke( m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.DataBind, new DispatcherOperationCallback( this.Dispatched_Process ), null );
DispatcherPriority.DataBind, m_dispatcherOperationStartTime = DateTime.UtcNow;
new DispatcherOperationCallback( this.Dispatched_Process ), m_hasNewOperationsSinceStartTime = false;
null );
} }
} }
} }
@ -298,29 +332,23 @@ namespace Xceed.Wpf.DataGrid
{ {
lock( this ) lock( this )
{ {
this.RefreshPending |= sourceDeferredOperationManager.RefreshPending; this.RefreshPending = this.RefreshPending || sourceDeferredOperationManager.RefreshPending;
this.RegroupPending |= sourceDeferredOperationManager.RegroupPending; this.RegroupPending = this.RegroupPending || sourceDeferredOperationManager.RegroupPending;
this.ResortPending |= sourceDeferredOperationManager.ResortPending; this.ResortPending = this.ResortPending || sourceDeferredOperationManager.ResortPending;
this.RefreshDistincValuesPending = this.RefreshDistincValuesPending || sourceDeferredOperationManager.RefreshDistincValuesPending;
this.RefreshDistincValuesPending |= sourceDeferredOperationManager.RefreshDistincValuesPending; this.RefreshDistincValuesWithFilteredItemChangedPending = this.RefreshDistincValuesWithFilteredItemChangedPending || sourceDeferredOperationManager.RefreshDistincValuesWithFilteredItemChangedPending;
this.RefreshDistincValuesWithFilteredItemChangedPending |=
sourceDeferredOperationManager.RefreshDistincValuesWithFilteredItemChangedPending;
if( this.RefreshPending ) if( this.RefreshPending )
{ {
m_deferredOperations = null; m_deferredOperations.Clear();
return; return;
} }
List<DeferredOperation> sourceOperations = sourceDeferredOperationManager.m_deferredOperations; List<DeferredOperation> sourceOperations = sourceDeferredOperationManager.m_deferredOperations;
if( ( sourceOperations == null ) || ( sourceOperations.Count == 0 ) ) if( sourceOperations.Count == 0 )
return; return;
if( m_deferredOperations == null )
m_deferredOperations = new List<DeferredOperation>();
m_deferredOperations.InsertRange( 0, sourceOperations ); m_deferredOperations.InsertRange( 0, sourceOperations );
} }
} }
@ -330,7 +358,7 @@ namespace Xceed.Wpf.DataGrid
this.Process( true ); this.Process( true );
} }
internal void InvalidateGroupStats( DataGridCollectionViewGroup group ) public void InvalidateGroupStats( DataGridCollectionViewGroup group, bool calculateAllStats = false )
{ {
if( group == null ) if( group == null )
return; return;
@ -340,28 +368,31 @@ namespace Xceed.Wpf.DataGrid
if( this.RefreshPending ) if( this.RefreshPending )
return; return;
if( m_invalidatedGroups == null )
m_invalidatedGroups = new List<DataGridCollectionViewGroup>( 64 );
DataGridCollectionViewGroup parent = group; DataGridCollectionViewGroup parent = group;
while( parent != null ) while( parent != null )
{ {
if( !m_invalidatedGroups.Contains( parent ) ) if( !m_invalidatedGroups.Contains( parent ) )
{ {
parent.ClearStatFunctionsResult();
m_invalidatedGroups.Add( parent ); m_invalidatedGroups.Add( parent );
} }
parent.ClearStatFunctionsResult();
parent.CalculateAllStats = calculateAllStats;
parent = parent.Parent; parent = parent.Parent;
} }
if( ( m_dispatcherOperation == null ) && ( m_dispatcher != null ) ) if( m_dispatcher != null )
{ {
m_dispatcherOperation = m_dispatcher.BeginInvoke( if( m_dispatcherOperation == null )
DispatcherPriority.DataBind, {
new DispatcherOperationCallback( this.Dispatched_Process ), m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.DataBind, new DispatcherOperationCallback( this.Dispatched_Process ), null );
null ); m_dispatcherOperationStartTime = DateTime.UtcNow;
}
else
{
m_hasNewOperationsSinceStartTime = true;
}
} }
} }
} }
@ -371,7 +402,7 @@ namespace Xceed.Wpf.DataGrid
if( item == null ) if( item == null )
throw new ArgumentNullException( "item" ); throw new ArgumentNullException( "item" );
if( m_deferredOperations == null ) if( m_deferredOperations.Count == 0 )
return false; return false;
int deferredOperationsCount = m_deferredOperations.Count; int deferredOperationsCount = m_deferredOperations.Count;
@ -388,7 +419,7 @@ namespace Xceed.Wpf.DataGrid
{ {
object oldItem = deferredOperation.OldItems[ j ]; object oldItem = deferredOperation.OldItems[ j ];
if( Object.Equals( oldItem, item ) ) if( object.Equals( oldItem, item ) )
return true; return true;
} }
} }
@ -406,14 +437,29 @@ namespace Xceed.Wpf.DataGrid
private void Process( bool processAll ) private void Process( bool processAll )
{ {
//This method will be called again when Dispose() is called on the DeferRefreshHelper of the CollectionView. //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; 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 // 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. // while we are trying to process the DeferredOperation.
lock( m_collectionViewToUpdate.SyncRoot ) lock( m_collectionView.SyncRoot )
{ {
lock( this ) lock( this )
{ {
@ -422,18 +468,13 @@ namespace Xceed.Wpf.DataGrid
{ {
m_dispatcherOperation.Abort(); m_dispatcherOperation.Abort();
m_dispatcherOperation = null; m_dispatcherOperation = null;
m_dispatcherOperationStartTime = DateTime.MinValue;
m_hasNewOperationsSinceStartTime = false;
} }
int operationIndex = 0; // 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.
long startTicks = DateTime.Now.Ticks; m_isProcessingOperations = true;
// 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;
bool refreshDistincValuesWithFilteredItemChangedPending = this.RefreshDistincValuesWithFilteredItemChangedPending; bool refreshDistincValuesWithFilteredItemChangedPending = this.RefreshDistincValuesWithFilteredItemChangedPending;
this.RefreshDistincValuesWithFilteredItemChangedPending = false; this.RefreshDistincValuesWithFilteredItemChangedPending = false;
bool refreshDistincValuesPending = this.RefreshDistincValuesPending; bool refreshDistincValuesPending = this.RefreshDistincValuesPending;
@ -444,85 +485,86 @@ namespace Xceed.Wpf.DataGrid
this.RegroupPending = false; this.RegroupPending = false;
bool resortPending = this.ResortPending; bool resortPending = this.ResortPending;
this.ResortPending = false; this.ResortPending = false;
List<DataGridCollectionViewGroup> invalidatedGroups = m_invalidatedGroups; bool refreshForced = false;
m_invalidatedGroups = null;
bool ensureGroupPosition = true; m_collectionView.RaisePreBatchCollectionChanged();
DateTime startTime = DateTime.UtcNow;
if( refreshPending ) if( refreshPending )
{ {
Debug.Assert( deferredOperations == null ); m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Refresh, -1, null ), out refreshForced );
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation(
DeferredOperation.DeferredOperationAction.Refresh, -1, null ), out refreshForced );
} }
else if( regroupPending ) else if( regroupPending )
{ {
ensureGroupPosition = false; m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Regroup, -1, null ), out refreshForced );
// Regrouping also do resorting
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation(
DeferredOperation.DeferredOperationAction.Regroup, -1, null ), out refreshForced );
} }
else if( resortPending ) else if( resortPending )
{ {
ensureGroupPosition = false; m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.Resort, -1, null ), out refreshForced );
m_collectionViewToUpdate.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++; operationIndex++;
} }
if( ( operationIndex < count ) && ( !refreshForced ) ) if( ( operationIndex < count ) && ( !refreshForced ) )
{ {
deferredOperations.RemoveRange( 0, operationIndex ); m_deferredOperations.RemoveRange( 0, operationIndex );
m_deferredOperationsToProcess -= operationIndex;
if( m_deferredOperations == null ) }
{ else
m_deferredOperations = deferredOperations; {
} m_deferredOperations.Clear();
else m_deferredOperationsToProcess = 0;
{
Debug.Assert( false, "Should never get there." );
m_deferredOperations.InsertRange( 0, deferredOperations );
}
} }
} }
m_isProcessingOperations = false;
// The recalculation of the StatFunctions is performed last. // The recalculation of the StatFunctions is performed last.
if( invalidatedGroups != null ) if( ( m_deferredOperationsToProcess <= 0 || m_forceProcessOfInvalidatedGroupStats ) && ( m_invalidatedGroups.Count != 0 ) )
m_collectionViewToUpdate.ProcessInvalidatedGroupStats( invalidatedGroups, ensureGroupPosition ); {
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. // Since a refresh has been forced, we don't want to process anything else.
if( !refreshForced ) if( !refreshForced )
{ {
if( ( ( processAll ) || ( DateTime.Now.Ticks - startTicks ) < 1000000 ) ) if( processAll || ( DateTime.UtcNow.Subtract( startTime ) < DeferredOperationManager.MaxProcessDuration ) )
{ {
if( refreshDistincValuesWithFilteredItemChangedPending || refreshDistincValuesPending ) if( refreshDistincValuesWithFilteredItemChangedPending || refreshDistincValuesPending )
{ {
m_collectionViewToUpdate.ExecuteSourceItemOperation( new DeferredOperation( m_collectionView.ExecuteSourceItemOperation( new DeferredOperation( DeferredOperation.DeferredOperationAction.RefreshDistincValues,
DeferredOperation.DeferredOperationAction.RefreshDistincValues, refreshDistincValuesWithFilteredItemChangedPending ), out refreshForced ); refreshDistincValuesWithFilteredItemChangedPending ), out refreshForced );
} }
} }
else else
{ {
if( refreshDistincValuesWithFilteredItemChangedPending ) if( refreshDistincValuesWithFilteredItemChangedPending )
{
this.RefreshDistincValuesWithFilteredItemChangedPending = true; this.RefreshDistincValuesWithFilteredItemChangedPending = true;
}
if( refreshDistincValuesPending ) if( refreshDistincValuesPending )
{
this.RefreshDistincValuesPending = true; this.RefreshDistincValuesPending = true;
}
} }
} }
if( this.HasPendingOperations ) m_collectionView.RaisePostBatchCollectionChanged();
if( this.HasPendingOperations || m_invalidatedGroups.Count != 0 )
{ {
Debug.Assert( !processAll ); Debug.Assert( !processAll );
Debug.Assert( m_dispatcher != null ); Debug.Assert( m_dispatcher != null );
@ -532,29 +574,33 @@ namespace Xceed.Wpf.DataGrid
{ {
if( m_dispatcher != null ) if( m_dispatcher != null )
{ {
m_dispatcherOperation = m_dispatcher.BeginInvoke( m_dispatcherOperation = m_dispatcher.BeginInvoke( DispatcherPriority.Input, new DispatcherOperationCallback( this.Dispatched_Process ), null );
DispatcherPriority.Input, m_dispatcherOperationStartTime = DateTime.UtcNow;
new DispatcherOperationCallback( this.Dispatched_Process ), m_hasNewOperationsSinceStartTime = false;
null );
} }
} }
else else
{ {
m_dispatcherOperation.Priority = DispatcherPriority.Input; m_dispatcherOperation.Priority = DispatcherPriority.Input;
m_dispatcherOperationStartTime = DateTime.UtcNow;
} }
} }
} }
} }
} }
private DataGridCollectionViewBase m_collectionViewToUpdate; private readonly DataGridCollectionViewBase m_collectionView;
private List<DeferredOperation> m_deferredOperations; private List<DeferredOperation> m_deferredOperations;
private HashSet<DataGridCollectionViewGroup> m_invalidatedGroups;
private int m_deferredOperationsToProcess;
private BitVector32 m_pendingFlags; 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 DispatcherOperation m_dispatcherOperation;
private DateTime m_dispatcherOperationStartTime;
private List<DataGridCollectionViewGroup> m_invalidatedGroups; private bool m_hasNewOperationsSinceStartTime;
[Flags] [Flags]
private enum DeferredOperationManagerPendingFlags 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.Diagnostics;
using System.Collections; using Xceed.Utils.Collections;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -28,7 +24,7 @@ namespace Xceed.Wpf.DataGrid
public DistinctValuesDictionary( DataGridCollectionViewBase dataGridCollectionViewBase ) public DistinctValuesDictionary( DataGridCollectionViewBase dataGridCollectionViewBase )
{ {
if( dataGridCollectionViewBase == null ) if( dataGridCollectionViewBase == null )
throw new DataGridInternalException(); throw new DataGridInternalException( "dataGridCollectionView is null." );
m_dataGridCollectionViewBase = dataGridCollectionViewBase; m_dataGridCollectionViewBase = dataGridCollectionViewBase;
} }
@ -66,7 +62,7 @@ namespace Xceed.Wpf.DataGrid
{ {
value = new ReadOnlyObservableHashList(); value = new ReadOnlyObservableHashList();
this.InternalAdd( key, value ); this.InternalAdd( key, value );
m_dataGridCollectionViewBase.ForceRefreshDistinctValuesForFieldName( key, value.InnerObservableHashList ); m_dataGridCollectionViewBase.ForceRefreshDistinctValuesForFieldName( key );
} }
Debug.Assert( value != null ); 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; ListSortDirection sortDirection = ListSortDirection.Ascending;
int result; 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; string statResultPropertyName = sortInfo.StatResultPropertyName;
IComparer sortComparer = sortInfo.SortComparer; IComparer sortComparer = sortInfo.SortComparer;
sortDirection = sortInfo.SortDirection; sortDirection = sortInfo.SortDirection;
@ -97,12 +96,12 @@ namespace Xceed.Wpf.DataGrid
public class SortInfo public class SortInfo
{ {
public SortInfo( string name, ListSortDirection sortDirection, IComparer sortComparer ) public SortInfo( string statResultPropertyName, ListSortDirection sortDirection, IComparer sortComparer )
{ {
if( sortComparer == null ) if( sortComparer == null )
throw new ArgumentNullException( "sortComparer" ); throw new ArgumentNullException( "sortComparer" );
this.StatResultPropertyName = name; this.StatResultPropertyName = statResultPropertyName;
this.SortDirection = sortDirection; this.SortDirection = sortDirection;
this.SortComparer = sortComparer; 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." ); 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; return null;
Type objectType = null; PropertyDescriptorCollection properties;
ICustomTypeDescriptor customTypeDescriptor = null;
PropertyDescriptorCollection properties = null;
PropertyDescriptor relationDescriptor = null;
TypeDescriptionProvider typeDescriptionProvider = null;
if( iTypedList != null ) properties = typedList.GetItemProperties( null );
{ if( ( properties != null ) && ( properties.Count > 0 ) )
properties = iTypedList.GetItemProperties( null ); return properties[ this.RelationName ];
if( ( properties != null ) && ( properties.Count > 0 ) ) var listName = typedList.GetListName( null );
{ if( string.IsNullOrEmpty( listName ) )
relationDescriptor = properties[ this.RelationName ]; return null;
}
else
{
string listName = iTypedList.GetListName( null );
if( string.IsNullOrEmpty( listName ) == false ) var itemType = Type.GetType( listName, false, false );
{ if( itemType == null )
objectType = Type.GetType( listName, false, false ); return null;
if( objectType != null ) var descriptionProvider = TypeDescriptor.GetProvider( itemType );
{ if( descriptionProvider == null )
typeDescriptionProvider = TypeDescriptor.GetProvider( objectType ); return null;
if( typeDescriptionProvider != null )
{
customTypeDescriptor = typeDescriptionProvider.GetTypeDescriptor( objectType );
if( customTypeDescriptor != null )
{
properties = customTypeDescriptor.GetProperties();
if( ( properties != null ) && ( properties.Count > 0 ) )
relationDescriptor = properties[ this.RelationName ];
}
}
}
}
}
}
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 ) private PropertyDescriptor GetPropertyDescriptorFromFirstItem( object firstItem )
{ {
if( string.IsNullOrEmpty( this.RelationName ) == true ) if( string.IsNullOrEmpty( this.RelationName ) || ( firstItem == null ) )
return null; return null;
Type objectType = null; var descriptor = ItemsSourceHelper.GetCustomTypeDescriptor( firstItem, firstItem.GetType() );
ICustomTypeDescriptor customTypeDescriptor = null; if( descriptor == null )
PropertyDescriptorCollection properties = null; return 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();
if( ( properties != null ) && ( properties.Count > 0 ) ) var properties = descriptor.GetProperties();
relationDescriptor = properties[ this.RelationName ]; if( ( properties != null ) && ( properties.Count > 0 ) )
} return properties[ this.RelationName ];
}
}
return relationDescriptor; return null;
} }
protected internal override IEnumerable GetDetailsForParentItem( DataGridCollectionViewBase parentCollectionView, object parentItem ) 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.ComponentModel;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -482,9 +481,9 @@ namespace Xceed.Wpf.DataGrid
typeof( Queryable ), "Count", typeof( Queryable ), "Count",
new Type[] { queryableElementType }, expressionToCount ); 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 ); 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; return count;
} }
@ -531,7 +530,7 @@ namespace Xceed.Wpf.DataGrid
MemberInfo member = QueryableExtensions.GetMemberInfo( typeExpression.Type, name ); MemberInfo member = QueryableExtensions.GetMemberInfo( typeExpression.Type, name );
if( member == null ) if( member == null )
throw new DataGridInternalException(); throw new DataGridInternalException( "MemberInfo is null." );
if( member is PropertyInfo ) if( member is PropertyInfo )
{ {
@ -651,9 +650,20 @@ namespace Xceed.Wpf.DataGrid
internal interface IQueryableGroupNameCountPair internal interface IQueryableGroupNameCountPair
{ {
object GroupName { get; } object GroupName
Type GroupNameType { get; } {
int Count { get; } get;
}
Type GroupNameType
{
get;
}
int Count
{
get;
}
} }
#endregion INTERNAL NESTED CLASSES #endregion INTERNAL NESTED CLASSES
@ -668,24 +678,42 @@ namespace Xceed.Wpf.DataGrid
this.Count = count; this.Count = count;
} }
public T GroupName { get; set; } public T GroupName
public int Count { get; set; } {
get;
set;
}
public int Count
{
get;
set;
}
#region QueryableGroupNameCountPair Members #region QueryableGroupNameCountPair Members
object IQueryableGroupNameCountPair.GroupName object IQueryableGroupNameCountPair.GroupName
{ {
get { return this.GroupName; } get
{
return this.GroupName;
}
} }
public Type GroupNameType public Type GroupNameType
{ {
get { return typeof( T ); } get
{
return typeof( T );
}
} }
int IQueryableGroupNameCountPair.Count int IQueryableGroupNameCountPair.Count
{ {
get { return this.Count; } get
{
return this.Count;
}
} }
#endregion #endregion
@ -729,10 +757,29 @@ namespace Xceed.Wpf.DataGrid
private struct QueryableGroupNameCountPairInfo private struct QueryableGroupNameCountPairInfo
{ {
public Type Type { get; set; } public Type Type
public ConstructorInfo ConstructorInfo { get; set; } {
public PropertyInfo KeyPropertyInfo { get; set; } get;
public PropertyInfo CountPropertyInfo { get; set; } set;
}
public ConstructorInfo ConstructorInfo
{
get;
set;
}
public PropertyInfo KeyPropertyInfo
{
get;
set;
}
public PropertyInfo CountPropertyInfo
{
get;
set;
}
} }
#endregion PRIVATE NESTED CLASSES #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;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Collections.Specialized;
using System.Text; using System.ComponentModel;
using System.Data;
using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Diagnostics; using Xceed.Utils.Collections;
using System.ComponentModel;
using System.Collections;
using System.Globalization;
using System.Collections.Specialized;
using System.Data;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
public class ForeignKeyConfiguration : DependencyObject public class ForeignKeyConfiguration : DependencyObject, IWeakEventListener
{ {
#region Constructors
static ForeignKeyConfiguration() static ForeignKeyConfiguration()
{ {
ForeignKeyConfiguration.DefaultDistinctValueItemContentTemplateProperty = ForeignKeyConfiguration.DefaultDistinctValueItemContentTemplatePropertyKey.DependencyProperty; ForeignKeyConfiguration.DefaultDistinctValueItemContentTemplateProperty = ForeignKeyConfiguration.DefaultDistinctValueItemContentTemplatePropertyKey.DependencyProperty;
@ -45,30 +41,25 @@ namespace Xceed.Wpf.DataGrid
public ForeignKeyConfiguration() public ForeignKeyConfiguration()
{ {
this.SetDefaultDistinctValueItemContentTemplate( Column.GenericContentTemplateSelector.ForeignKeyDistinctValueItemContentTemplate ); this.SetDefaultCellContentTemplate( GenericContentTemplateSelector.ForeignKeyCellContentTemplate );
this.SetDefaultCellContentTemplate( Column.GenericContentTemplateSelector.ForeignKeyCellContentTemplate ); this.SetDefaultGroupValueTemplate( GenericContentTemplateSelector.ForeignKeyGroupValueTemplate );
this.SetDefaultGroupValueTemplate( Column.GenericContentTemplateSelector.ForeignKeyGroupValueTemplate ); this.SetDefaultScrollTipContentTemplate( GenericContentTemplateSelector.ForeignKeyScrollTipContentTemplate );
this.SetDefaultScrollTipContentTemplate( Column.GenericContentTemplateSelector.ForeignKeyScrollTipContentTemplate );
this.SetDefaultCellEditor( DefaultCellEditorSelector.ForeignKeyCellEditor ); this.SetDefaultCellEditor( DefaultCellEditorSelector.ForeignKeyCellEditor );
} }
#endregion
#region ValuePath Property #region ValuePath Property
public static readonly DependencyProperty ValuePathProperty = DependencyProperty.Register( public static readonly DependencyProperty ValuePathProperty = DependencyProperty.Register(
"ValuePath", "ValuePath",
typeof( string ), typeof( string ),
typeof( ForeignKeyConfiguration ), typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( new FrameworkPropertyMetadata( null ) );
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnSelectedValuePathChanged ) ) );
public string ValuePath public string ValuePath
{ {
get get
{ {
return m_ValuePath; return ( string )this.GetValue( ForeignKeyConfiguration.ValuePathProperty );
} }
set 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 #endregion
#region DisplayMemberPath Property #region DisplayMemberPath Property
@ -96,15 +75,13 @@ namespace Xceed.Wpf.DataGrid
"DisplayMemberPath", "DisplayMemberPath",
typeof( string ), typeof( string ),
typeof( ForeignKeyConfiguration ), typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( new FrameworkPropertyMetadata( null ) );
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnDisplayMemberPathChanged ) ) );
public string DisplayMemberPath public string DisplayMemberPath
{ {
get get
{ {
return m_displayMemberPath; return ( string )this.GetValue( ForeignKeyConfiguration.DisplayMemberPathProperty );
} }
set 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 #endregion
#region ItemContainerStyle Property #region ItemContainerStyle Property
@ -132,15 +97,13 @@ namespace Xceed.Wpf.DataGrid
"ItemContainerStyle", "ItemContainerStyle",
typeof( Style ), typeof( Style ),
typeof( ForeignKeyConfiguration ), typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( new FrameworkPropertyMetadata( null ) );
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnItemContainerStyleChanged ) ) );
public Style ItemContainerStyle public Style ItemContainerStyle
{ {
get get
{ {
return m_itemContainerStyle; return ( Style )this.GetValue( ForeignKeyConfiguration.ItemContainerStyleProperty );
} }
set 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 #endregion
#region ItemContainerStyleSelector Property #region ItemContainerStyleSelector Property
@ -166,15 +119,13 @@ namespace Xceed.Wpf.DataGrid
"ItemContainerStyleSelector", "ItemContainerStyleSelector",
typeof( StyleSelector ), typeof( StyleSelector ),
typeof( ForeignKeyConfiguration ), typeof( ForeignKeyConfiguration ),
new FrameworkPropertyMetadata( new FrameworkPropertyMetadata( null ) );
null,
new PropertyChangedCallback( ForeignKeyConfiguration.OnItemContainerStyleSelectorChanged ) ) );
public StyleSelector ItemContainerStyleSelector public StyleSelector ItemContainerStyleSelector
{ {
get get
{ {
return m_itemContainerStyleSelector; return ( StyleSelector )this.GetValue( ForeignKeyConfiguration.ItemContainerStyleSelectorProperty );
} }
set 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 #endregion
#region IsAutoCreated Property #region IsAutoCreated Property
@ -220,8 +159,7 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_itemsSource; return ( IEnumerable )this.GetValue( ForeignKeyConfiguration.ItemsSourceProperty );
} }
set set
{ {
@ -229,18 +167,65 @@ namespace Xceed.Wpf.DataGrid
} }
} }
private IEnumerable m_itemsSource;
private static void OnItemsSourceChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e ) private static void OnItemsSourceChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
{ {
ForeignKeyConfiguration foreignConfiguration = sender as ForeignKeyConfiguration; var foreignConfiguration = sender as ForeignKeyConfiguration;
if( foreignConfiguration != null ) 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 #endregion
#region ForeignKeyConverter Property #region ForeignKeyConverter Property
@ -265,6 +250,126 @@ namespace Xceed.Wpf.DataGrid
#endregion #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 #region DefaultDistinctValueItemContentTemplate Property
private static readonly DependencyPropertyKey DefaultDistinctValueItemContentTemplatePropertyKey = DependencyProperty.RegisterReadOnly( private static readonly DependencyPropertyKey DefaultDistinctValueItemContentTemplatePropertyKey = DependencyProperty.RegisterReadOnly(
@ -396,7 +501,6 @@ namespace Xceed.Wpf.DataGrid
internal static readonly DependencyProperty DefaultCellEditorProperty; internal static readonly DependencyProperty DefaultCellEditorProperty;
internal CellEditor DefaultCellEditor internal CellEditor DefaultCellEditor
{ {
get get
@ -417,42 +521,72 @@ namespace Xceed.Wpf.DataGrid
#endregion #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( var itemsSource = this.ItemsSource;
Dictionary<string,ColumnBase> columns,
IEnumerable itemsSourceCollection, //Convert the value from the ValuePath value to the DisplayMemberPath value, using a DataRowView or reflection.
Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors, if( ( itemsSource is DataView ) || ( itemsSource is DataTable ) )
bool autoCreateForeignKeyConfigurations ) {
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 = DataGridCollectionViewBase collectionViewBase = itemsSourceCollection as DataGridCollectionViewBase;
itemsSourceCollection as DataGridCollectionViewBase;
if( collectionViewBase != null ) if( collectionViewBase != null )
{ {
ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( columns, collectionViewBase.ItemProperties, autoCreateForeignKeyConfigurations );
columns,
collectionViewBase.ItemProperties,
autoCreateForeignKeyConfigurations );
} }
else else
{ {
ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors( ForeignKeyConfiguration.UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors( columns, fieldDescriptors, autoCreateForeignKeyConfigurations );
columns,
fieldDescriptors,
autoCreateForeignKeyConfigurations );
} }
} }
// If a DataGridCollectionViewBase is used, get the ItemProperties it defines // If a DataGridCollectionViewBase is used, get the ItemProperties it defines to be able to retreive DataGridForeignKeyDescription for each of them
// to be able to retreive DataGridForeignKeyDescription for each of them
// to get the auto-detected ForeignKey ItemsSource (if any). // to get the auto-detected ForeignKey ItemsSource (if any).
// If a DataGridCollectionViewBase is not used, the ItemsSource must be // If a DataGridCollectionViewBase is not used, the ItemsSource must be manually specified on each Column in order to correctly display/edit the Data
// manually specified on each Column in order to correctly display/edit the Data internal static void UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( Dictionary<string, ColumnBase> columns, DataGridItemPropertyCollection itemProperties,
internal static void UpdateColumnsForeignKeyConfigurationsFromDataGridCollectionView( bool autoCreateForeignKeyConfigurations )
Dictionary<string,ColumnBase> columns,
DataGridItemPropertyCollection itemProperties,
bool autoCreateForeignKeyConfigurations )
{ {
if( itemProperties == null ) if( itemProperties == null )
return; return;
@ -467,17 +601,13 @@ namespace Xceed.Wpf.DataGrid
ColumnBase column; ColumnBase column;
columns.TryGetValue( itemProperty.Name, out column ); columns.TryGetValue( itemProperty.Name, out column );
ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription( ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription( column as Column, description, autoCreateForeignKeyConfigurations );
column as Column,
description,
autoCreateForeignKeyConfigurations );
} }
} }
private static void UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors( private static void UpdateColumnsForeignKeyConfigurationsFromFieldDescriptors( Dictionary<string, ColumnBase> columns,
Dictionary<string, ColumnBase> columns, Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors,
Dictionary<string, ItemsSourceHelper.FieldDescriptor> fieldDescriptors, bool autoCreateForeignKeyConfigurations )
bool autoCreateForeignKeyConfigurations )
{ {
if( columns == null ) if( columns == null )
return; return;
@ -495,17 +625,12 @@ namespace Xceed.Wpf.DataGrid
ColumnBase column; ColumnBase column;
columns.TryGetValue( fieldDescriptor.Name, out column ); columns.TryGetValue( fieldDescriptor.Name, out column );
ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription( ForeignKeyConfiguration.SynchronizeForeignKeyConfigurationFromForeignKeyDescription( column as Column, description, autoCreateForeignKeyConfigurations );
column as Column,
description,
autoCreateForeignKeyConfigurations );
} }
} }
internal static void SynchronizeForeignKeyConfigurationFromForeignKeyDescription( internal static void SynchronizeForeignKeyConfigurationFromForeignKeyDescription( Column column, DataGridForeignKeyDescription description,
Column column, bool autoCreateForeignKeyConfigurations )
DataGridForeignKeyDescription description,
bool autoCreateForeignKeyConfigurations )
{ {
if( ( description == null ) || ( column == null ) ) if( ( description == null ) || ( column == null ) )
return; return;
@ -522,21 +647,22 @@ namespace Xceed.Wpf.DataGrid
column.ForeignKeyConfiguration = configuration; column.ForeignKeyConfiguration = configuration;
} }
// ValuePath will be affected to the FieldName when the // ValuePath will be affected to the FieldName when the configuration is auto-created to be able to modify local source using foreign key value
// configuration is auto-created to be able to modify
// local source using foreign key value
if( configuration.IsAutoCreated ) if( configuration.IsAutoCreated )
{ {
if( string.IsNullOrEmpty( configuration.ValuePath ) ) if( string.IsNullOrEmpty( configuration.ValuePath ) )
{ {
configuration.ValuePath = description.ValuePath; configuration.ValuePath = description.ValuePath;
} }
if( string.IsNullOrEmpty( configuration.DisplayMemberPath ) )
{
configuration.DisplayMemberPath = description.DisplayMemberPath;
}
} }
// Affect the ItemsSource on the configuration if it is not // Affect the ItemsSource on the configuration if it is not already set
// already set if( ( configuration.ItemsSource == null ) && ( description.ItemsSource != null ) )
if( ( configuration.ItemsSource == null )
&& ( description.ItemsSource != null ) )
{ {
configuration.ItemsSource = description.ItemsSource; 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 #endregion
} }
} }

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

@ -28,14 +28,8 @@ namespace Xceed.Wpf.DataGrid
{ {
internal class ForeignKeyContentControl : ContentControl internal class ForeignKeyContentControl : ContentControl
{ {
#region Static Members
private static readonly Binding BindingToValue; private static readonly Binding BindingToValue;
#endregion
#region Constructors
static ForeignKeyContentControl() static ForeignKeyContentControl()
{ {
ForeignKeyContentControl.BindingToValue = new Binding(); ForeignKeyContentControl.BindingToValue = new Binding();
@ -56,8 +50,6 @@ namespace Xceed.Wpf.DataGrid
this.Focusable = false; this.Focusable = false;
} }
#endregion
#region ForeignKeyConfiguration Property #region ForeignKeyConfiguration Property
public static readonly DependencyProperty ForeignKeyConfigurationProperty = DependencyProperty.Register( public static readonly DependencyProperty ForeignKeyConfigurationProperty = DependencyProperty.Register(
@ -154,14 +146,12 @@ namespace Xceed.Wpf.DataGrid
if( contentControl != null ) if( contentControl != null )
{ {
contentControl.NotifyKeyChanged(); contentControl.NotifyValueChanged();
} }
} }
#endregion #endregion
#region Protected Methods
protected void NotifyKeyChanged() protected void NotifyKeyChanged()
{ {
if( m_isBeingModified ) if( m_isBeingModified )
@ -196,10 +186,6 @@ namespace Xceed.Wpf.DataGrid
} }
} }
#endregion
#region Private Methods
private void OnKeyChanged() private void OnKeyChanged()
{ {
ForeignKeyConfiguration configuration = this.ForeignKeyConfiguration; ForeignKeyConfiguration configuration = this.ForeignKeyConfiguration;
@ -220,7 +206,7 @@ namespace Xceed.Wpf.DataGrid
if( ( configuration != null ) && ( configuration.ForeignKeyConverter != null ) ) if( ( configuration != null ) && ( configuration.ForeignKeyConverter != null ) )
{ {
this.Key = configuration.ForeignKeyConverter.GetValueFromKey( this.Value, configuration ); this.Key = configuration.ForeignKeyConverter.GetKeyFromValue( this.Value, configuration );
} }
else else
{ {
@ -228,12 +214,6 @@ namespace Xceed.Wpf.DataGrid
} }
} }
#endregion
#region Private Fields
private bool m_isBeingModified; // = false; 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 namespace Xceed.Wpf.DataGrid
{ {
public partial class GeneratorNode internal partial class GeneratorNode
{ {
internal GeneratorNode( GeneratorNode parent ) 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.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Diagnostics; 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;
using System.Windows.Controls;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -33,61 +31,53 @@ namespace Xceed.Wpf.DataGrid
NotifyCollectionChangedEventHandler groupsChangedHandler, NotifyCollectionChangedEventHandler groupsChangedHandler,
EventHandler<ExpansionStateChangedEventArgs> expansionStateChangedHandler, EventHandler<ExpansionStateChangedEventArgs> expansionStateChangedHandler,
EventHandler isExpandedChangingHandler, EventHandler isExpandedChangingHandler,
EventHandler isExpandedChangedHandler ) EventHandler isExpandedChangedHandler,
DataGridControl dataGridControl )
{ {
if( itemsChangedHandler == null ) if( itemsChangedHandler == null )
{
throw new ArgumentNullException( "itemsChangedHandler" ); throw new ArgumentNullException( "itemsChangedHandler" );
}
if( groupsChangedHandler == null ) if( groupsChangedHandler == null )
{
throw new ArgumentNullException( "groupsChangedHandler" ); throw new ArgumentNullException( "groupsChangedHandler" );
}
if( expansionStateChangedHandler == null ) if( expansionStateChangedHandler == null )
{
throw new ArgumentNullException( "expansionStateChangedHandler" ); throw new ArgumentNullException( "expansionStateChangedHandler" );
}
if( isExpandedChangingHandler == null ) if( isExpandedChangingHandler == null )
{
throw new ArgumentNullException( "isExpandedChangingHandler" ); throw new ArgumentNullException( "isExpandedChangingHandler" );
}
if( isExpandedChangedHandler == null ) if( isExpandedChangedHandler == null )
{
throw new ArgumentNullException( "isExpandedChangedHandler" ); throw new ArgumentNullException( "isExpandedChangedHandler" );
}
m_itemsChangedHandler = itemsChangedHandler; m_itemsChangedHandler = itemsChangedHandler;
m_groupsChangedHandler = groupsChangedHandler; m_groupsChangedHandler = groupsChangedHandler;
m_expansionStateChangedHandler = expansionStateChangedHandler; m_expansionStateChangedHandler = expansionStateChangedHandler;
m_isExpandedChangingHandler = isExpandedChangingHandler; m_isExpandedChangingHandler = isExpandedChangingHandler;
m_isExpandedChangedHandler = isExpandedChangedHandler; 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; if( m_dataGridControl == null )
m_nodesCollectionChangedEventHandlers.TryGetValue( sender, out handler ); return null;
if( handler != null )
{
handler.Invoke( sender, ( NotifyCollectionChangedEventArgs )e );
}
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( public GeneratorNode CreateGroupGeneratorNode(
CollectionViewGroup collectionViewGroup, CollectionViewGroup collectionViewGroup,
@ -114,12 +104,10 @@ namespace Xceed.Wpf.DataGrid
node.IsExpanded = groupConfig.InitiallyExpanded; node.IsExpanded = groupConfig.InitiallyExpanded;
if( collectionViewGroup.IsBottomLevel == false ) if( !collectionViewGroup.IsBottomLevel )
{ {
IList<object> subItems = collectionViewGroup.GetItems();
this.RegisterNodeCollectionChanged( this.RegisterNodeCollectionChanged(
( INotifyCollectionChanged )subItems, ( INotifyCollectionChanged )collectionViewGroup.GetItems(),
new NotifyCollectionChangedEventHandler( node.OnCollectionChanged ) ); new NotifyCollectionChangedEventHandler( node.OnCollectionChanged ) );
node.CollectionChanged += m_groupsChangedHandler; node.CollectionChanged += m_groupsChangedHandler;
@ -151,10 +139,6 @@ namespace Xceed.Wpf.DataGrid
Debug.Assert( notifyCollection != null, "collection must be a INotifyCollectionChanged for CreateItemsGeneratorNode()" ); 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; ItemCollection itemCollection = collection as ItemCollection;
if( itemCollection != null ) if( itemCollection != null )
{ {
@ -299,9 +283,7 @@ namespace Xceed.Wpf.DataGrid
} }
newNode.Next = next; newNode.Next = next;
this.RegisterNodeCollectionChanged( this.RegisterNodeCollectionChanged( ( INotifyCollectionChanged )newNode.Items, new NotifyCollectionChangedEventHandler( newNode.OnCollectionChanged ) );
( INotifyCollectionChanged )newNode.Items,
new NotifyCollectionChangedEventHandler( newNode.OnCollectionChanged ) );
newNode.CollectionChanged += m_itemsChangedHandler; newNode.CollectionChanged += m_itemsChangedHandler;
newNode.ExpansionStateChanged += m_expansionStateChangedHandler; 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; ICollection<HeadersFootersGeneratorNode> nodeList;
bool keyFound = m_headersFootersMapping.TryGetValue( notifyCollection, out nodeList ); if( !m_headersFootersMapping.TryGetValue( collection, out nodeList ) )
if( keyFound == false )
{ {
nodeList = new List<HeadersFootersGeneratorNode>(); nodeList = new HashSet<HeadersFootersGeneratorNode>();
notifyCollection.CollectionChanged += OnHeadersFootersCollectionChanged; m_headersFootersMapping.Add( collection, nodeList );
CollectionChangedEventManager.AddListener( collection, this );
m_headersFootersMapping.Add( notifyCollection, nodeList );
} }
nodeList.Add( node ); nodeList.Add( node );
@ -331,47 +310,24 @@ namespace Xceed.Wpf.DataGrid
private void CleanHeadersFootersNotification( HeadersFootersGeneratorNode node ) private void CleanHeadersFootersNotification( HeadersFootersGeneratorNode node )
{ {
INotifyCollectionChanged notifyCollection = node.Items as INotifyCollectionChanged; var collection = node.Items as INotifyCollectionChanged;
if( notifyCollection != null ) if( collection == null )
{ return;
try
{
List<HeadersFootersGeneratorNode> nodeList = m_headersFootersMapping[ notifyCollection ];
nodeList.Remove( node ); try
{
var nodeList = m_headersFootersMapping[ collection ];
nodeList.Remove( node );
if( nodeList.Count == 0 ) if( nodeList.Count == 0 )
{
notifyCollection.CollectionChanged -= OnHeadersFootersCollectionChanged;
m_headersFootersMapping.Remove( notifyCollection );
}
}
catch( Exception e )
{ {
throw new DataGridInternalException( e ); CollectionChangedEventManager.RemoveListener( collection, this );
m_headersFootersMapping.Remove( collection );
} }
} }
} catch( Exception e )
private void OnHeadersFootersCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
INotifyCollectionChanged collectionChanged = sender as INotifyCollectionChanged;
if( collectionChanged != null )
{ {
try throw new DataGridInternalException( e.Message, e, this.DataGridControl );
{
List<HeadersFootersGeneratorNode> nodeList = m_headersFootersMapping[ collectionChanged ];
foreach( HeadersFootersGeneratorNode node in nodeList )
{
m_itemsChangedHandler.Invoke( node, e );
}
}
catch( Exception ex )
{
throw new DataGridInternalException( ex );
}
} }
} }
@ -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_itemsChangedHandler; // = null
private readonly NotifyCollectionChangedEventHandler m_groupsChangedHandler; // = null private readonly NotifyCollectionChangedEventHandler m_groupsChangedHandler; // = null
private readonly EventHandler<ExpansionStateChangedEventArgs> m_expansionStateChangedHandler; // = null private readonly EventHandler<ExpansionStateChangedEventArgs> m_expansionStateChangedHandler; // = null
private readonly EventHandler m_isExpandedChangedHandler; // = null private readonly EventHandler m_isExpandedChangedHandler; // = null
private readonly EventHandler m_isExpandedChangingHandler; // = 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;
using System.Windows.Data;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Collections; using System.Collections;
using System.Windows;
using System.Windows.Data;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -221,7 +219,7 @@ namespace Xceed.Wpf.DataGrid
public bool InsertAfter( GeneratorNode insert ) public bool InsertAfter( GeneratorNode insert )
{ {
if( insert == null ) if( insert == null )
throw new DataGridInternalException(); throw new DataGridInternalException( "GeneratorNode is null." );
int insertionCount; int insertionCount;
int chainLength; int chainLength;
@ -238,7 +236,7 @@ namespace Xceed.Wpf.DataGrid
// Move the current node to the last node inserted // Move the current node to the last node inserted
if( !this.MoveToNextBy( chainLength ) ) if( !this.MoveToNextBy( chainLength ) )
throw new DataGridInternalException(); throw new DataGridInternalException( "Unable to move to the requested generator index." );
return true; return true;
} }
@ -246,7 +244,7 @@ namespace Xceed.Wpf.DataGrid
public bool InsertBefore( GeneratorNode insert ) public bool InsertBefore( GeneratorNode insert )
{ {
if( insert == null ) if( insert == null )
throw new DataGridInternalException(); throw new DataGridInternalException( "GeneratorNode is null" );
int insertionCount; int insertionCount;
int chainLength; int chainLength;
@ -779,7 +777,10 @@ namespace Xceed.Wpf.DataGrid
int endSourceDataItemIndex = -1; int endSourceDataItemIndex = -1;
if( minIndex < 0 ) 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 ) if( ( visitorType & DataGridContextVisitorType.DataGridContext ) == DataGridContextVisitorType.DataGridContext )
{ {
@ -893,7 +894,7 @@ namespace Xceed.Wpf.DataGrid
} }
if( !processed ) if( !processed )
throw new DataGridInternalException(); throw new DataGridInternalException( "Unable to process the visit.", sourceContext.DataGridControl );
if( visitWasStopped ) if( visitWasStopped )
break; break;
@ -915,7 +916,7 @@ namespace Xceed.Wpf.DataGrid
{ {
bool stopVisit = false; bool stopVisit = false;
visitor.Visit( sourceContext, startSourceDataItemIndex, endSourceDataItemIndex, ref stopVisit ); visitor.Visit( sourceContext, startSourceDataItemIndex, endSourceDataItemIndex, ref stopVisit );
visitWasStopped |= stopVisit; visitWasStopped = visitWasStopped || stopVisit;
} }
} }
} }
@ -981,7 +982,7 @@ namespace Xceed.Wpf.DataGrid
( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor( ( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor(
detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped ); detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped );
stopVisit |= visitWasStopped; stopVisit = stopVisit || visitWasStopped;
if( stopVisit ) if( stopVisit )
break; break;
@ -1049,10 +1050,10 @@ namespace Xceed.Wpf.DataGrid
{ {
bool visitWasStopped; bool visitWasStopped;
( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor( ( ( IDataGridContextVisitable )detailNode.DetailGenerator ).AcceptVisitor(
detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped ); detailStartIndex, detailEndIndex, visitor, visitorType, visitDetails, out visitWasStopped );
stopVisit |= visitWasStopped; stopVisit = stopVisit || visitWasStopped;
if( stopVisit ) if( stopVisit )
break; break;

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

@ -230,7 +230,7 @@ namespace Xceed.Wpf.DataGrid
if( this.TotalLeafCountChanged != null ) 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 namespace Xceed.Wpf.DataGrid
{ {
public class NotifyCollectionChangedGeneratorNode : GeneratorNode, INotifyCollectionChanged internal class NotifyCollectionChangedGeneratorNode : GeneratorNode, INotifyCollectionChanged
{ {
internal NotifyCollectionChangedGeneratorNode( GeneratorNode parent ) internal NotifyCollectionChangedGeneratorNode( GeneratorNode parent )
: base( parent ) : base( parent )

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

@ -23,9 +23,10 @@ namespace Xceed.Wpf.DataGrid
{ {
internal class RangeSelectionVisitor : IDataGridContextVisitor internal class RangeSelectionVisitor : IDataGridContextVisitor
{ {
public RangeSelectionVisitor( SelectionRange[] selectedColumns ) public RangeSelectionVisitor( SelectionRange[] selectedColumns, bool unselect )
{ {
m_selectedColumns = selectedColumns; m_selectedColumns = selectedColumns;
m_unselect = unselect;
} }
#region IDataGridContextVisitor Members #region IDataGridContextVisitor Members
@ -56,21 +57,40 @@ namespace Xceed.Wpf.DataGrid
if( intersectionSelectionRange.IsEmpty ) if( intersectionSelectionRange.IsEmpty )
continue; 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() + ")" ); + intersectionSelectionRange.StartIndex.ToString() + " - " + intersectionSelectionRange.EndIndex.ToString() + ")" );
#endif
selectionChangerManager.SelectCells(
sourceContext, var cellRange = new SelectionCellRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null, intersectionSelectionRange );
new SelectionCellRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null, intersectionSelectionRange ) );
if( m_unselect )
{
selectionChangerManager.UnselectCells( sourceContext, cellRange );
}
else
{
selectionChangerManager.SelectCells( sourceContext, cellRange );
}
} }
} }
else 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( if( m_unselect )
sourceContext, {
new SelectionRangeWithItems( new SelectionRange( startSourceDataItemIndex, endSourceDataItemIndex ), null ) ); selectionChangerManager.UnselectItems( sourceContext, itemRange );
}
else
{
selectionChangerManager.SelectItems( sourceContext, itemRange );
}
} }
} }
@ -97,5 +117,6 @@ namespace Xceed.Wpf.DataGrid
#endregion #endregion
private SelectionRange[] m_selectedColumns; 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 else
{ {
HashedLinkedList<ColumnBase> columnsByVisiblePosition = sourceContext.ColumnsByVisiblePosition; HashedLinkedList<ColumnBase> columnsByVisiblePosition = sourceContext.ColumnsByVisiblePosition;
SelectedItemsStorage selectedColumnStore = new SelectedItemsStorage( null, 8 ); SelectedItemsStorage selectedColumnStore = new SelectedItemsStorage( null );
SelectionRange fullColumnRange = new SelectionRange( 0, columnsByVisiblePosition.Count - 1 ); SelectionRange fullColumnRange = new SelectionRange( 0, columnsByVisiblePosition.Count - 1 );
selectedColumnStore.Add( new SelectionRangeWithItems( fullColumnRange, null ) ); selectedColumnStore.Add( new SelectionRangeWithItems( fullColumnRange, null ) );
int index = 0; 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 public enum DistinctValuesConstraint
{ {
All, All,
Filtered Filtered,
FilteredWithAllFilters
} }
} }

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

@ -19,7 +19,7 @@
internal static class _XceedVersionInfo internal static class _XceedVersionInfo
{ {
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] [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" )] [System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion + ".0.0"; public const string Version = BaseVersion + ".0.0";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )] [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 ) 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 ) void ITransformProvider.Rotate( double degrees )

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

@ -15,24 +15,28 @@
***********************************************************************************/ ***********************************************************************************/
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.ComponentModel;
using System.Text; using System.Diagnostics;
using System.Globalization;
using System.Windows;
using System.Windows.Automation;
using System.Windows.Automation.Peers; using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider; using System.Windows.Automation.Provider;
using System.Windows.Data; using System.Windows.Data;
using System.Windows; using Xceed.Wpf.DataGrid.Utils;
using System.Windows.Controls;
using System.Collections;
using System.Collections.ObjectModel;
using System.Windows.Automation;
using System.Globalization;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid.Automation 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 ) public DataGridGroupAutomationPeer( Group uiGroupOwner )
{ {
if( uiGroupOwner == null ) if( uiGroupOwner == null )
@ -41,6 +45,8 @@ namespace Xceed.Wpf.DataGrid.Automation
m_uiGroupOwner = uiGroupOwner; m_uiGroupOwner = uiGroupOwner;
m_dataChildren = new Hashtable( 0 ); m_dataChildren = new Hashtable( 0 );
m_headerFooterChildren = new Hashtable( 0 ); m_headerFooterChildren = new Hashtable( 0 );
PropertyChangedEventManager.AddListener( uiGroupOwner, this, DataGridGroupAutomationPeer.GroupIsExpandedPropertyName );
} }
#region Owner Property #region Owner Property
@ -53,6 +59,8 @@ namespace Xceed.Wpf.DataGrid.Automation
} }
} }
private readonly Group m_uiGroupOwner;
#endregion #endregion
public override object GetPattern( PatternInterface patternInterface ) public override object GetPattern( PatternInterface patternInterface )
@ -174,7 +182,7 @@ namespace Xceed.Wpf.DataGrid.Automation
for( int i = 0; i < itemsCount; i++ ) for( int i = 0; i < itemsCount; i++ )
{ {
Object item = items[ i ]; object item = items[ i ];
CollectionViewGroup collectionViewGroup = item as CollectionViewGroup; CollectionViewGroup collectionViewGroup = item as CollectionViewGroup;
if( collectionViewGroup == null ) if( collectionViewGroup == null )
@ -372,7 +380,27 @@ namespace Xceed.Wpf.DataGrid.Automation
throw new NotSupportedException(); 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, DataGridContext dataGridContext,
HeadersFootersGeneratorNode node, HeadersFootersGeneratorNode node,
List<AutomationPeer> list, List<AutomationPeer> list,
@ -411,7 +439,7 @@ namespace Xceed.Wpf.DataGrid.Automation
} }
} }
static internal void AddFooterPeer( internal static void AddFooterPeer(
DataGridContext dataGridContext, DataGridContext dataGridContext,
HeadersFootersGeneratorNode node, HeadersFootersGeneratorNode node,
List<AutomationPeer> list, List<AutomationPeer> list,
@ -648,8 +676,30 @@ namespace Xceed.Wpf.DataGrid.Automation
#endregion #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_dataChildren;
private Hashtable m_headerFooterChildren; private Hashtable m_headerFooterChildren;
#endregion
} }
} }

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

@ -16,13 +16,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq; using System.Linq;
using System.Text;
using System.Windows.Automation.Peers;
using System.Windows; using System.Windows;
using System.Globalization; using System.Windows.Automation.Peers;
using System.Diagnostics;
using System.Windows.Media;
using System.Windows.Automation.Provider; using System.Windows.Automation.Provider;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using System.Windows.Threading; using System.Windows.Threading;
@ -312,21 +310,17 @@ namespace Xceed.Wpf.DataGrid.Automation
internal UIElement GetWrapper() internal UIElement GetWrapper()
{ {
HeaderFooterItem headerFooterItem = m_owner as HeaderFooterItem; HeaderFooterItem headerFooterItem = m_owner as HeaderFooterItem;
if( headerFooterItem == null ) if( headerFooterItem == null )
{ {
headerFooterItem = headerFooterItem = m_dataGridContext.GetContainerFromItem( m_owner ) as HeaderFooterItem;
m_dataGridContext.GetContainerFromItem( m_owner ) as HeaderFooterItem;
} }
if( headerFooterItem == null ) if( headerFooterItem == null )
return null; return null;
IDataGridItemContainer dataGridItemContainer = HeaderFooterItem.FindIDataGridItemContainerInChildren( var container = headerFooterItem.GetTemplatedDescendantDataGridItemContainers().FirstOrDefault();
headerFooterItem, headerFooterItem.AsVisual() ); if( container != null )
return container as UIElement;
if( dataGridItemContainer != null )
return dataGridItemContainer as UIElement;
return headerFooterItem; 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() public override void OnApplyTemplate()
{ {
base.OnApplyTemplate(); base.OnApplyTemplate();
ChildCheckBox.Background = new System.Windows.Media.SolidColorBrush( System.Windows.Media.Colors.Blue );
} }
public static readonly RoutedEvent CheckedEvent; 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:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.DataGrid" xmlns:local="clr-namespace:Xceed.Wpf.DataGrid"
xmlns:conv="clr-namespace:Xceed.Wpf.DataGrid.Converters" xmlns:conv="clr-namespace:Xceed.Wpf.DataGrid.Converters"
xmlns:markup="clr-namespace:Xceed.Wpf.DataGrid.Markup" xmlns:s="clr-namespace:System;assembly=mscorlib">
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:sxml="clr-namespace:System.Xml;assembly=System.Xml">
<conv:ImageConverter x:Key="imageConverter" /> <conv:ImageConverter x:Key="imageConverter" />
<conv:NullToBooleanConverter x:Key="nullToBooleanConverter" /> <conv:NullToBooleanConverter x:Key="nullToBooleanConverter" />
@ -64,7 +62,10 @@
</DataTemplate> </DataTemplate>
<DataTemplate x:Key="foreignKeyDistinctValueItemDefaultContentTemplate"> <DataTemplate x:Key="commonDefaultContentTemplate">
<TextBlock Text="{Binding Mode=OneWay}" />
</DataTemplate> </DataTemplate>
</ResourceDictionary> </ResourceDictionary>

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

@ -15,20 +15,11 @@
***********************************************************************************/ ***********************************************************************************/
using System; using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Collections; using System.Collections;
using System.ComponentModel; using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Diagnostics; using System.Diagnostics;
using System.Windows.Media; using System.Windows;
using Xceed.Wpf.DataGrid.ValidationRules; using System.Windows.Data;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;
using Xceed.Utils.Collections;
using System.Collections.Specialized;
using Xceed.Wpf.DataGrid.Converters;
namespace Xceed.Wpf.DataGrid 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 )] [Obsolete( "The DisplayMemberBinding property is obsolete and has been replaced by the DisplayMemberBindingInfo property.", false )]
public Column( string fieldName, object title, BindingBase displayMemberBinding ) public Column( string fieldName, object title, BindingBase displayMemberBinding )
: base( fieldName, title ) : base( fieldName, title )
{
this.SetDisplayMemberBinding( displayMemberBinding );
}
internal static Column Create( string fieldName, object title, BindingBase displayMemberBinding )
{ {
// Disable warning for DisplayMemberBinding when internaly used // Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618 #pragma warning disable 618
var column = new Column( fieldName, title, displayMemberBinding );
this.DisplayMemberBinding = displayMemberBinding;
#pragma warning restore 618 #pragma warning restore 618
return column;
} }
#region DisplayMemberBinding Property #region DisplayMemberBinding Property
@ -67,14 +63,33 @@ namespace Xceed.Wpf.DataGrid
set set
{ {
if( value != m_displayMemberBinding ) if( value == m_displayMemberBinding )
{ return;
m_displayMemberBinding = value;
this.OnPropertyChanged( new PropertyChangedEventArgs( "DisplayMemberBinding" ) ); 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 #endregion DisplayMemberBinding Property
#region DisplayMemberBindingInfo Property #region DisplayMemberBindingInfo Property
@ -93,7 +108,6 @@ namespace Xceed.Wpf.DataGrid
if( value != m_displayMemberBindingInfo ) if( value != m_displayMemberBindingInfo )
{ {
m_displayMemberBindingInfo = value; m_displayMemberBindingInfo = value;
m_displayMemberBinding = m_displayMemberBindingInfo.GetBinding(); m_displayMemberBinding = m_displayMemberBindingInfo.GetBinding();
this.OnPropertyChanged( new PropertyChangedEventArgs( "DisplayMemberBindingInfo" ) ); this.OnPropertyChanged( new PropertyChangedEventArgs( "DisplayMemberBindingInfo" ) );
@ -195,7 +209,9 @@ namespace Xceed.Wpf.DataGrid
"ForeignKeyConfiguration", "ForeignKeyConfiguration",
typeof( ForeignKeyConfiguration ), typeof( ForeignKeyConfiguration ),
typeof( Column ), typeof( Column ),
new FrameworkPropertyMetadata( null, new PropertyChangedCallback( Column.OnForeignKeyConfigurationChanged ) ) ); new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback( Column.OnForeignKeyConfigurationChanged ) ) );
public ForeignKeyConfiguration ForeignKeyConfiguration public ForeignKeyConfiguration ForeignKeyConfiguration
{ {
@ -228,10 +244,10 @@ namespace Xceed.Wpf.DataGrid
private void RaiseForeignKeyConfigurationChanged() private void RaiseForeignKeyConfigurationChanged()
{ {
var handler = this.ForeignKeyConfigurationChanged; var handler = this.ForeignKeyConfigurationChanged;
if( handler != null ) if( handler == null )
{ return;
handler( this, EventArgs.Empty );
} handler.Invoke( this, EventArgs.Empty );
} }
#endregion #endregion
@ -242,24 +258,38 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return m_bindingAutoCreated; return m_isBindingAutoCreated;
} }
set set
{ {
m_bindingAutoCreated = value; m_isBindingAutoCreated = value;
} }
} }
private bool m_isBindingAutoCreated; //false
#endregion #endregion
#region IsBoundToDataGridUnboundItemProperty Property #region IsBoundToDataGridUnboundItemProperty Property
internal bool IsBoundToDataGridUnboundItemProperty internal bool IsBoundToDataGridUnboundItemProperty
{ {
get; get
set; {
return m_isBoundToDataGridUnboundItemProperty;
}
set
{
if( value == m_isBoundToDataGridUnboundItemProperty )
return;
m_isBoundToDataGridUnboundItemProperty = value;
this.ResetDefaultCellRecyclingGroup();
}
} }
private bool m_isBoundToDataGridUnboundItemProperty; //false
#endregion #endregion
#if DEBUG #if DEBUG
@ -274,6 +304,48 @@ namespace Xceed.Wpf.DataGrid
} }
#endif #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;
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.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Diagnostics; using System.ComponentModel;
using System.Windows.Threading;
using System.Threading;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -39,20 +34,6 @@ namespace Xceed.Wpf.DataGrid
this.ParentDetailConfiguration = parentDetailConfiguration; 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 #region MainColumn Property
public ColumnBase MainColumn public ColumnBase MainColumn
@ -75,11 +56,9 @@ namespace Xceed.Wpf.DataGrid
#endregion #endregion
// INTERNAL PROPERTIES
#region FieldNameToColumnDictionary Property #region FieldNameToColumnDictionary Property
internal Dictionary<string,ColumnBase> FieldNameToColumnDictionary internal Dictionary<string, ColumnBase> FieldNameToColumnDictionary
{ {
get get
{ {
@ -97,7 +76,6 @@ namespace Xceed.Wpf.DataGrid
{ {
return m_dataGridControl; return m_dataGridControl;
} }
set set
{ {
m_dataGridControl = value; m_dataGridControl = value;
@ -125,86 +103,58 @@ namespace Xceed.Wpf.DataGrid
#region ProcessingVisibleColumnsUpdate Property #region ProcessingVisibleColumnsUpdate Property
internal bool ProcessingVisibleColumnsUpdate internal AutoResetFlag ProcessingVisibleColumnsUpdate
{ {
get get
{ {
return m_processingVisibleColumnsUpdate; return m_processingVisibleColumnsUpdate;
} }
set
{
m_processingVisibleColumnsUpdate = value;
}
} }
private bool m_processingVisibleColumnsUpdate; // = false private readonly AutoResetFlag m_processingVisibleColumnsUpdate = AutoResetFlagFactory.Create();
#endregion #endregion
#region VisibleColumnsUpdateDelayed Property public ColumnBase this[ string fieldName ]
internal bool VisibleColumnsUpdateDelayed
{ {
get get
{ {
return m_visibleColumnsUpdateDelayed; ColumnBase column = null;
}
set
{
m_visibleColumnsUpdateDelayed = value;
}
}
private bool m_visibleColumnsUpdateDelayed; // = false
#endregion
#region Column Event Handlers m_fieldNameToColumns.TryGetValue( fieldName, out column );
private void RegisterColumnChangedEvent( ColumnBase column ) return 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 );
} }
private void UnregisterColumnChangedEvent( ColumnBase column ) #region IsDeferVisibleColumnsUpdate Internal Property
{
column.TitleChanged -= new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged -= new EventHandler( this.OnColumnValueChanged );
column.VisiblePositionChanged -= new EventHandler( this.OnColumnVisibilityChanged );
column.VisibleChanged -= new EventHandler( this.OnColumnVisibilityChanged );
}
private void OnColumnVisibilityChanged( object sender, EventArgs e ) internal bool IsDeferVisibleColumnsUpdate
{ {
if( this.ColumnVisibilityChanged != null ) get
this.ColumnVisibilityChanged( this, new WrappedEventEventArgs( sender, e ) ); {
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 ) protected override void RemoveItem( int index )
{ {
ColumnBase column = this[ index ]; ColumnBase column = this[ index ];
if( column != null ) if( column != null )
{ {
m_fieldNameToColumns.Remove( column.FieldName );
this.UnregisterColumnChangedEvent( column ); this.UnregisterColumnChangedEvent( column );
column.DetachFromContainingCollection(); column.DetachFromContainingCollection();
m_fieldNameToColumns.Remove( column.FieldName );
} }
base.RemoveItem( index ); base.RemoveItem( index );
@ -215,17 +165,15 @@ namespace Xceed.Wpf.DataGrid
if( item != null ) if( item != null )
{ {
if( ( string.IsNullOrEmpty( item.FieldName ) == true ) && ( !DesignerProperties.GetIsInDesignMode( item ) ) ) if( ( string.IsNullOrEmpty( item.FieldName ) == true ) && ( !DesignerProperties.GetIsInDesignMode( item ) ) )
{
throw new ArgumentException( "A column must have a fieldname.", "item" ); throw new ArgumentException( "A column must have a fieldname.", "item" );
}
item.AttachToContainingCollection( this );
if( m_fieldNameToColumns.ContainsKey( item.FieldName ) ) if( m_fieldNameToColumns.ContainsKey( item.FieldName ) )
throw new DataGridException( "A column with same field name already exists in collection." ); throw new DataGridException( "A column with same field name already exists in collection." );
m_fieldNameToColumns.Add( item.FieldName, item ); m_fieldNameToColumns.Add( item.FieldName, item );
item.AttachToContainingCollection( this );
this.RegisterColumnChangedEvent( item ); this.RegisterColumnChangedEvent( item );
} }
@ -249,37 +197,37 @@ namespace Xceed.Wpf.DataGrid
protected override void SetItem( int index, ColumnBase item ) protected override void SetItem( int index, ColumnBase item )
{ {
if( ( item != null ) && ( string.IsNullOrEmpty( item.FieldName ) == true ) ) if( ( item != null ) && ( string.IsNullOrEmpty( item.FieldName ) == true ) )
{
throw new ArgumentException( "A column must have a fieldname.", "item" ); 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 ]; ColumnBase column = this[ index ];
if( ( column != null ) && ( column != item ) ) if( ( column != null ) && ( column != item ) )
{ {
m_fieldNameToColumns.Remove( column.FieldName );
this.UnregisterColumnChangedEvent( column ); this.UnregisterColumnChangedEvent( column );
column.DetachFromContainingCollection(); column.DetachFromContainingCollection();
m_fieldNameToColumns.Remove( column.FieldName );
} }
if( ( item != null ) && ( column != item ) ) if( ( item != null ) && ( column != item ) )
{ {
m_fieldNameToColumns.Add( item.FieldName, item );
item.AttachToContainingCollection( this ); item.AttachToContainingCollection( this );
this.RegisterColumnChangedEvent( item ); this.RegisterColumnChangedEvent( item );
m_fieldNameToColumns.Add( item.FieldName, item );
} }
base.SetItem( index, item ); base.SetItem( index, item );
} }
protected override void OnCollectionChanged( System.Collections.Specialized.NotifyCollectionChangedEventArgs e ) protected override void OnCollectionChanged( NotifyCollectionChangedEventArgs e )
{ {
if( ( m_columnAdditionMessagesDeferedCount > 0 ) if( ( m_columnAdditionMessagesDeferedCount > 0 ) && ( e.Action == NotifyCollectionChangedAction.Add ) && ( e.NewStartingIndex == ( this.Count - e.NewItems.Count ) ) )
&& ( e.Action == NotifyCollectionChangedAction.Add ) && ( e.NewStartingIndex == ( this.Count - e.NewItems.Count ) ) )
{ {
if( m_deferedColumnAdditionMessageStartIndex == -1 ) if( m_deferedColumnAdditionMessageStartIndex == -1 )
{ {
@ -297,8 +245,6 @@ namespace Xceed.Wpf.DataGrid
} }
} }
// INTERNAL METHODS
internal IDisposable DeferColumnAdditionMessages() internal IDisposable DeferColumnAdditionMessages()
{ {
return new DeferedColumnAdditionMessageDisposable( this ); return new DeferedColumnAdditionMessageDisposable( this );
@ -314,11 +260,19 @@ namespace Xceed.Wpf.DataGrid
internal event EventHandler VisibleColumnsUpdating; 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 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_columnAdditionMessagesDeferedCount = 0;
private int m_deferVisibleColumnsUpdateCount = 0;
private int m_deferedColumnAdditionMessageStartIndex = -1; private int m_deferedColumnAdditionMessageStartIndex = -1;
private List<ColumnBase> m_deferedColumns = new List<ColumnBase>(); 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 Dictionary<string, ColumnBase> m_fieldNameToColumns = new Dictionary<string, ColumnBase>(); // To optimize indexing speed for FieldName
private DispatcherOperation m_visibleColumnsUpdatedDispatcherOperation;
private sealed class DeferedColumnAdditionMessageDisposable : IDisposable private sealed class DeferedColumnAdditionMessageDisposable : IDisposable
{ {
@ -374,6 +401,14 @@ namespace Xceed.Wpf.DataGrid
#region IDisposable Members #region IDisposable Members
public void Dispose() public void Dispose()
{
this.Dispose( true );
GC.SuppressFinalize( this );
}
#endregion
private void Dispose( bool disposing )
{ {
m_columns.m_columnAdditionMessagesDeferedCount--; 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 #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 private ColumnCollection m_columns; // = null
} }
@ -408,8 +484,17 @@ namespace Xceed.Wpf.DataGrid
this.WrappedEventArgs = eventArgs; this.WrappedEventArgs = eventArgs;
} }
public object WrappedSender { get; private set; } public object WrappedSender
public object WrappedEventArgs { get; private set; } {
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.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Documents; using System.Windows.Documents;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using Xceed.Utils.Wpf.DragDrop; 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.Automation;
using Xceed.Wpf.DataGrid.Views;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -42,11 +38,9 @@ namespace Xceed.Wpf.DataGrid
FocusableProperty.OverrideMetadata( typeof( ColumnManagerCell ), new FrameworkPropertyMetadata( false ) ); FocusableProperty.OverrideMetadata( typeof( ColumnManagerCell ), new FrameworkPropertyMetadata( false ) );
ReadOnlyProperty.OverrideMetadata( typeof( ColumnManagerCell ), new FrameworkPropertyMetadata( true ) ); ReadOnlyProperty.OverrideMetadata( typeof( ColumnManagerCell ), new FrameworkPropertyMetadata( true ) );
ColumnManagerCell.IsPressedProperty = ColumnManagerCell.IsPressedProperty = ColumnManagerCell.IsPressedPropertyKey.DependencyProperty;
ColumnManagerCell.IsPressedPropertyKey.DependencyProperty;
ColumnManagerCell.IsBeingDraggedProperty = ColumnManagerCell.IsBeingDraggedProperty = ColumnManagerCell.IsBeingDraggedPropertyKey.DependencyProperty;
ColumnManagerCell.IsBeingDraggedPropertyKey.DependencyProperty;
} }
public ColumnManagerCell() public ColumnManagerCell()
@ -98,14 +92,12 @@ namespace Xceed.Wpf.DataGrid
#endregion IsBeingDragged Read-Only Property #endregion IsBeingDragged Read-Only Property
#region DataGridContext Property #region DataGridContext Internal Read-Only Property
private DataGridContext DataGridContext internal DataGridContext DataGridContext
{ {
get get
{ {
Debug.Assert( m_dataGridContext != null );
return m_dataGridContext; return m_dataGridContext;
} }
} }
@ -126,11 +118,44 @@ namespace Xceed.Wpf.DataGrid
#endregion #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 #region ColumnReordering Internal Event
internal static readonly RoutedEvent ColumnReorderingEvent = internal static readonly RoutedEvent ColumnReorderingEvent =
EventManager.RegisterRoutedEvent( "ColumnReordering", EventManager.RegisterRoutedEvent( "ColumnReordering",
RoutingStrategy.Bubble, RoutingStrategy.Bubble,
typeof( ColumnReorderingEventHandler ), typeof( ColumnReorderingEventHandler ),
typeof( ColumnManagerCell ) ); typeof( ColumnManagerCell ) );
@ -147,9 +172,9 @@ namespace Xceed.Wpf.DataGrid
{ {
base.InitializeCore( dataGridContext, parentRow, parentColumn ); base.InitializeCore( dataGridContext, parentRow, parentColumn );
this.SetContent( parentColumn ); this.SetColumnBinding( ColumnManagerCell.ContentProperty, parentColumn, ColumnBase.TitleProperty );
this.SetContentTemplate( parentColumn ); this.SetColumnBinding( ColumnManagerCell.ContentTemplateProperty, parentColumn, ColumnBase.TitleTemplateProperty );
this.SetContentTemplateSelector( parentColumn ); this.SetColumnBinding( ColumnManagerCell.ContentTemplateSelectorProperty, parentColumn, ColumnBase.TitleTemplateSelectorProperty );
} }
protected override AutomationPeer OnCreateAutomationPeer() protected override AutomationPeer OnCreateAutomationPeer()
@ -159,12 +184,11 @@ namespace Xceed.Wpf.DataGrid
protected internal override void PrepareDefaultStyleKey( ViewBase view ) 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 = newThemeKey;
{
this.DefaultStyleKey = currentThemeKey;
}
} }
protected internal override void PrepareContainer( DataGridContext dataGridContext, object item ) 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 // Update the DropOutsideCursor since it is defined on the View
UIViewBase uiViewBase = dataGridContext.DataGridControl.GetView() as UIViewBase; UIViewBase uiViewBase = dataGridContext.DataGridControl.GetView() as UIViewBase;
m_dragSourceManager.DropOutsideCursor = ( uiViewBase != null ) m_dragSourceManager.DropOutsideCursor = ( uiViewBase != null ) ? uiViewBase.CannotDropDraggedElementCursor : UIViewBase.DefaultCannotDropDraggedElementCursor;
? uiViewBase.CannotDropDraggedElementCursor
: UIViewBase.DefaultCannotDropDraggedElementCursor;
m_dragSourceManager.ProcessMouseLeftButtonDown( e ); m_dragSourceManager.ProcessMouseLeftButtonDown( e );
} }
@ -242,8 +264,7 @@ namespace Xceed.Wpf.DataGrid
protected override void OnMouseLeftButtonUp( MouseButtonEventArgs e ) protected override void OnMouseLeftButtonUp( MouseButtonEventArgs e )
{ {
// m_dragSourceManager.ProcessMouseLeftButtonUp() will release the capture, // m_dragSourceManager.ProcessMouseLeftButtonUp() will release the capture, so we need to check the IsMouseCaptured and IsPressed states before calling it.
// so we need to check the IsMouseCaptured and IsPressed states before calling it.
bool isMouseCaptured = this.IsMouseCaptured; bool isMouseCaptured = this.IsMouseCaptured;
bool isPressed = this.IsPressed; bool isPressed = this.IsPressed;
@ -290,7 +311,9 @@ namespace Xceed.Wpf.DataGrid
protected override void OnLostMouseCapture( MouseEventArgs e ) protected override void OnLostMouseCapture( MouseEventArgs e )
{ {
if( m_dragSourceManager != null ) if( m_dragSourceManager != null )
{
m_dragSourceManager.ProcessLostMouseCapture( e ); m_dragSourceManager.ProcessLostMouseCapture( e );
}
if( this.IsPressed ) if( this.IsPressed )
{ {
@ -303,7 +326,6 @@ namespace Xceed.Wpf.DataGrid
internal bool CanDoSort() internal bool CanDoSort()
{ {
ColumnManagerRow parentRow = this.ParentRow as ColumnManagerRow; ColumnManagerRow parentRow = this.ParentRow as ColumnManagerRow;
if( parentRow != null ) if( parentRow != null )
{ {
if( !parentRow.AllowSort ) if( !parentRow.AllowSort )
@ -311,10 +333,13 @@ namespace Xceed.Wpf.DataGrid
} }
DataGridContext dataGridContext = this.DataGridContext; DataGridContext dataGridContext = this.DataGridContext;
if( dataGridContext == null ) if( dataGridContext == null )
return false; 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.SourceDetailConfiguration == null )
{ {
if( !dataGridContext.Items.CanSort ) if( !dataGridContext.Items.CanSort )
@ -325,7 +350,6 @@ namespace Xceed.Wpf.DataGrid
return false; return false;
ColumnBase parentColumn = this.ParentColumn; ColumnBase parentColumn = this.ParentColumn;
if( ( parentColumn == null ) || ( !parentColumn.AllowSort ) ) if( ( parentColumn == null ) || ( !parentColumn.AllowSort ) )
return false; return false;
@ -338,159 +362,83 @@ namespace Xceed.Wpf.DataGrid
return; return;
DataGridContext dataGridContext = this.DataGridContext; DataGridContext dataGridContext = this.DataGridContext;
ColumnBase column = this.ParentColumn;
Debug.Assert( dataGridContext != null ); Debug.Assert( dataGridContext != null );
SortingHelper.ToggleColumnSort( var toggleColumnSortCommand = dataGridContext.ToggleColumnSortCommand;
dataGridContext, dataGridContext.Items.SortDescriptions, if( !toggleColumnSortCommand.CanExecute( column, shiftUnpressed ) )
dataGridContext.Columns, this.ParentColumn, shiftUnpressed ); return;
toggleColumnSortCommand.Execute( column, shiftUnpressed );
} }
internal void DoResize( double newWidth ) internal void DoResize( double newWidth, ColumnBase parentColumn )
{ {
if( !this.IsEnabled ) if( !this.IsEnabled )
return; return;
ColumnBase parentColumn = this.ParentColumn;
if( parentColumn == null )
return;
if( !parentColumn.HasFixedWidth ) if( !parentColumn.HasFixedWidth )
{ {
if( newWidth < MIN_WIDTH ) if( newWidth < MIN_WIDTH )
{
newWidth = MIN_WIDTH; newWidth = MIN_WIDTH;
}
if( newWidth < parentColumn.MinWidth ) if( newWidth < parentColumn.MinWidth )
{
newWidth = parentColumn.MinWidth; newWidth = parentColumn.MinWidth;
}
if( newWidth > parentColumn.MaxWidth ) if( newWidth > parentColumn.MaxWidth )
{
newWidth = parentColumn.MaxWidth; newWidth = parentColumn.MaxWidth;
}
parentColumn.Width = newWidth; parentColumn.Width = newWidth;
} }
} }
private void SetContent( ColumnBase parentColumn ) internal virtual void OnColumnResizerThumbDragStarted( DragStartedEventArgs e )
{
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 )
{ {
Binding binding = new Binding(); var parentColumn = this.ParentColumn;
binding.Path = new PropertyPath( ColumnBase.TitleTemplateSelectorProperty ); Debug.Assert( parentColumn != null );
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 dataGridContext = this.DataGridContext;
Debug.Assert( dataGridContext != null );
if( m_dragSourceManager != null ) m_originalWidth = parentColumn.ActualWidth;
{
m_dragSourceManager.PropertyChanged -= this.DragSourceManager_PropertyChanged;
}
// The DataGridControl's AdornerDecoratorForDragAndDrop must be used for dragging in order to include the if( TableView.GetRemoveColumnStretchingOnResize( dataGridContext ) )
// 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
{ {
m_dragSourceManager = new ColumnReorderingDragSourceManager( this, dataGridContext.ColumnStretchingManager.DisableColumnStretching();
null,
dataGridControl );
} }
}
m_dragSourceManager.PropertyChanged += this.DragSourceManager_PropertyChanged; internal virtual void OnColumnResizerThumbDragDelta( DragDeltaEventArgs e )
{
// Create bindings to ViewProperties for AutoScroll Properties var parentColumn = this.ParentColumn;
Binding binding = new Binding(); Debug.Assert( parentColumn != null );
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 ); 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 ) if( m_dropMarkAdorner == null )
{ {
DataGridContext dataGridContext = DataGridControl.GetDataGridContext( this ); var dataGridContext = this.DataGridContext;
var grid = ( dataGridContext != null ) ? dataGridContext.DataGridControl : null;
DataGridControl grid = ( dataGridContext != null )
? dataGridContext.DataGridControl
: null;
Pen pen = UIViewBase.GetDropMarkPen( this ); Pen pen = UIViewBase.GetDropMarkPen( this );
@ -513,20 +461,24 @@ namespace Xceed.Wpf.DataGrid
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this ); AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this );
if( adornerLayer != null ) if( adornerLayer != null )
{
adornerLayer.Add( m_dropMarkAdorner ); adornerLayer.Add( m_dropMarkAdorner );
}
} }
m_dropMarkAdorner.UpdateAlignment( mousePosition ); m_dropMarkAdorner.UpdateAlignment( mousePosition );
} }
private void HideDropMark() internal void HideDropMark()
{ {
if( m_dropMarkAdorner != null ) if( m_dropMarkAdorner != null )
{ {
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this ); AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer( this );
if( adornerLayer != null ) if( adornerLayer != null )
{
adornerLayer.Remove( m_dropMarkAdorner ); adornerLayer.Remove( m_dropMarkAdorner );
}
m_dropMarkAdorner = null; m_dropMarkAdorner = null;
} }
@ -536,22 +488,22 @@ namespace Xceed.Wpf.DataGrid
{ {
if( m_columnResizerThumb != null ) if( m_columnResizerThumb != null )
{ {
m_columnResizerThumb.DragStarted -= new DragStartedEventHandler( ColumnResizerThumb_DragStarted ); m_columnResizerThumb.DragStarted -= new DragStartedEventHandler( this.ColumnResizerThumb_DragStarted );
m_columnResizerThumb.DragDelta -= new DragDeltaEventHandler( ColumnResizerThumb_DragDelta ); m_columnResizerThumb.DragDelta -= new DragDeltaEventHandler( this.ColumnResizerThumb_DragDelta );
m_columnResizerThumb.DragCompleted -= new DragCompletedEventHandler( ColumnResizerThumb_DragCompleted ); m_columnResizerThumb.DragCompleted -= new DragCompletedEventHandler( this.ColumnResizerThumb_DragCompleted );
m_columnResizerThumb.QueryCursor -= new QueryCursorEventHandler( ColumnResizerThumb_QueryCursor ); m_columnResizerThumb.QueryCursor -= new QueryCursorEventHandler( this.ColumnResizerThumb_QueryCursor );
m_columnResizerThumb.MouseDoubleClick -= new MouseButtonEventHandler( ColumnResizerThumb_MouseDoubleClick ); m_columnResizerThumb.MouseDoubleClick -= new MouseButtonEventHandler( this.ColumnResizerThumb_MouseDoubleClick );
m_columnResizerThumb = null; m_columnResizerThumb = null;
} }
if( m_columnResizerThumbLeft != null ) if( m_columnResizerThumbLeft != null )
{ {
m_columnResizerThumbLeft.DragStarted -= new DragStartedEventHandler( ColumnResizerThumbLeft_DragStarted ); m_columnResizerThumbLeft.DragStarted -= new DragStartedEventHandler( this.ColumnResizerThumbLeft_DragStarted );
m_columnResizerThumbLeft.DragDelta -= new DragDeltaEventHandler( ColumnResizerThumbLeft_DragDelta ); m_columnResizerThumbLeft.DragDelta -= new DragDeltaEventHandler( this.ColumnResizerThumbLeft_DragDelta );
m_columnResizerThumbLeft.DragCompleted -= new DragCompletedEventHandler( ColumnResizerThumbLeft_DragCompleted ); m_columnResizerThumbLeft.DragCompleted -= new DragCompletedEventHandler( this.ColumnResizerThumbLeft_DragCompleted );
m_columnResizerThumbLeft.QueryCursor -= new QueryCursorEventHandler( ColumnResizerThumbLeft_QueryCursor ); m_columnResizerThumbLeft.QueryCursor -= new QueryCursorEventHandler( this.ColumnResizerThumbLeft_QueryCursor );
m_columnResizerThumbLeft.MouseDoubleClick -= new MouseButtonEventHandler( ColumnResizerThumbLeft_MouseDoubleClick ); m_columnResizerThumbLeft.MouseDoubleClick -= new MouseButtonEventHandler( this.ColumnResizerThumbLeft_MouseDoubleClick );
m_columnResizerThumbLeft = null; m_columnResizerThumbLeft = null;
} }
@ -561,120 +513,157 @@ namespace Xceed.Wpf.DataGrid
if( m_columnResizerThumb != null ) if( m_columnResizerThumb != null )
{ {
m_columnResizerThumb.DragStarted += new DragStartedEventHandler( ColumnResizerThumb_DragStarted ); m_columnResizerThumb.DragStarted += new DragStartedEventHandler( this.ColumnResizerThumb_DragStarted );
m_columnResizerThumb.DragDelta += new DragDeltaEventHandler( ColumnResizerThumb_DragDelta ); m_columnResizerThumb.DragDelta += new DragDeltaEventHandler( this.ColumnResizerThumb_DragDelta );
m_columnResizerThumb.DragCompleted += new DragCompletedEventHandler( ColumnResizerThumb_DragCompleted ); m_columnResizerThumb.DragCompleted += new DragCompletedEventHandler( this.ColumnResizerThumb_DragCompleted );
m_columnResizerThumb.QueryCursor += new QueryCursorEventHandler( ColumnResizerThumb_QueryCursor ); m_columnResizerThumb.QueryCursor += new QueryCursorEventHandler( this.ColumnResizerThumb_QueryCursor );
m_columnResizerThumb.MouseDoubleClick += new MouseButtonEventHandler( ColumnResizerThumb_MouseDoubleClick ); m_columnResizerThumb.MouseDoubleClick += new MouseButtonEventHandler( this.ColumnResizerThumb_MouseDoubleClick );
} }
if( m_columnResizerThumbLeft != null ) if( m_columnResizerThumbLeft != null )
{ {
m_columnResizerThumbLeft.DragStarted += new DragStartedEventHandler( ColumnResizerThumbLeft_DragStarted ); m_columnResizerThumbLeft.DragStarted += new DragStartedEventHandler( this.ColumnResizerThumbLeft_DragStarted );
m_columnResizerThumbLeft.DragDelta += new DragDeltaEventHandler( ColumnResizerThumbLeft_DragDelta ); m_columnResizerThumbLeft.DragDelta += new DragDeltaEventHandler( this.ColumnResizerThumbLeft_DragDelta );
m_columnResizerThumbLeft.DragCompleted += new DragCompletedEventHandler( ColumnResizerThumbLeft_DragCompleted ); m_columnResizerThumbLeft.DragCompleted += new DragCompletedEventHandler( this.ColumnResizerThumbLeft_DragCompleted );
m_columnResizerThumbLeft.QueryCursor += new QueryCursorEventHandler( ColumnResizerThumbLeft_QueryCursor ); m_columnResizerThumbLeft.QueryCursor += new QueryCursorEventHandler( this.ColumnResizerThumbLeft_QueryCursor );
m_columnResizerThumbLeft.MouseDoubleClick += new MouseButtonEventHandler( ColumnResizerThumbLeft_MouseDoubleClick ); m_columnResizerThumbLeft.MouseDoubleClick += new MouseButtonEventHandler( this.ColumnResizerThumbLeft_MouseDoubleClick );
} }
} }
private void ColumnResizerThumb_MouseDoubleClick( object sender, MouseButtonEventArgs e ) private void SetupDragManager()
{ {
ColumnBase parentColumn = this.ParentColumn; var dataGridContext = this.DataGridContext;
// Can be null in design-time (edition of a style TargetType ColumnManagerCell).
if( parentColumn == null ) if( dataGridContext == null )
return; return;
e.Handled = true; // 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 );
double fittedWidth = parentColumn.GetFittedWidth(); if( adornerLayer == null )
if( fittedWidth != -1 )
{ {
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 ) if( adornerLayer == null )
{ return;
ColumnBase parentColumn = this.ParentColumn; }
if( parentColumn == null ) var dataGridControl = dataGridContext.DataGridControl;
if( dataGridControl == null )
return; return;
DataGridContext dataGridContext = this.DataGridContext; if( m_dragSourceManager != null )
bool showResizeCursor = !parentColumn.HasFixedWidth;
if( !showResizeCursor )
{ {
// Don't disable resizing if ColumnStretching can be disabled by an end-user resize. m_dragSourceManager.PropertyChanged -= this.DragSourceManager_PropertyChanged;
showResizeCursor = ( dataGridContext != null ) && ( TableView.GetRemoveColumnStretchingOnResize( dataGridContext ) );
} }
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 ) m_dragSourceManager = new ColumnReorderingDragSourceManager( this, dataGridControl.DragDropAdornerDecorator.AdornerLayer, dataGridControl, this.ParentRow.LevelCache );
{ }
UIViewBase uiViewBase = dataGridContext.DataGridControl.GetView() as UIViewBase; else
{
m_dragSourceManager = new ColumnReorderingDragSourceManager( this, null, dataGridControl, this.ParentRow.LevelCache );
}
e.Cursor = ( uiViewBase != null ) m_dragSourceManager.PropertyChanged += this.DragSourceManager_PropertyChanged;
? uiViewBase.ColumnResizeWestEastCursor
: UIViewBase.DefaultColumnResizeWestEastCursor;
}
else
{
e.Cursor = UIViewBase.DefaultColumnResizeWestEastCursor;
}
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 ) 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; 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 ) ) ) this.OnColumnResizerThumbDragCompleted( e );
{
dataGridContext.ColumnStretchingManager.DisableColumnStretching();
}
} }
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 ) if( parentColumn == null )
return; return;
if( e.Canceled || parentColumn.HasFixedWidth ) var dataGridContext = this.DataGridContext;
parentColumn.Width = m_originalWidth;
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() private ColumnManagerCell GetPreviousVisibleColumnManagerCell()
{ {
var previousVisibleColumn = this.ParentColumn.PreviousVisibleColumn; var previousVisibleColumn = this.ParentColumn.PreviousVisibleColumn;
if( previousVisibleColumn == null ) if( previousVisibleColumn == null )
return null; return null;
@ -684,69 +673,119 @@ namespace Xceed.Wpf.DataGrid
private void ColumnResizerThumbLeft_QueryCursor( object sender, QueryCursorEventArgs e ) private void ColumnResizerThumbLeft_QueryCursor( object sender, QueryCursorEventArgs e )
{ {
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell(); 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 ) private void ColumnResizerThumbLeft_DragStarted( object sender, DragStartedEventArgs e )
{ {
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell(); 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 ) private void ColumnResizerThumbLeft_MouseDoubleClick( object sender, MouseButtonEventArgs e )
{ {
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell(); 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 ) private void ColumnResizerThumbLeft_DragDelta( object sender, DragDeltaEventArgs e )
{ {
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell(); 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 ) private void ColumnResizerThumbLeft_DragCompleted( object sender, DragCompletedEventArgs e )
{ {
var previousColumnManagerCell = this.GetPreviousVisibleColumnManagerCell(); 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 ) return ( binding.Source == parentColumn )
previousColumnManagerCell.ColumnResizerThumb_DragCompleted( previousColumnManagerCell, e ); && ( 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 #region IDropTarget Members
bool IDropTarget.CanDropElement( UIElement draggedElement ) 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; ColumnManagerRow parentRow = this.ParentRow as ColumnManagerRow;
if( ( parentRow == null ) || !parentRow.AllowColumnReorder )
return false;
if( parentRow != null ) if( !ColumnManagerCell.CanMove( draggedCell ) || !ColumnManagerCell.CanMove( this ) )
allowColumnReorder = parentRow.AllowColumnReorder; return false;
DataGridContext draggedDetailContext = draggedCell.DataGridContext;
DataGridContext sourceDetailContext = this.DataGridContext; DataGridContext sourceDetailContext = this.DataGridContext;
Debug.Assert( sourceDetailContext != null ); Debug.Assert( ( draggedDetailContext != null ) && ( 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;
return ( sourceDetailContext.SourceDetailConfiguration == draggedDetailContext.SourceDetailConfiguration ) &&
return ( ( sourceDetailConfig == draggedDetailConfig ) && ( sourceDetailContext.GroupLevelDescriptions == draggedDetailContext.GroupLevelDescriptions );
( sourceDetailContext != null ) &&
( draggedDetailContext != null ) &&
( sourceDetailContext.GroupLevelDescriptions == draggedDetailContext.GroupLevelDescriptions ) &&
( allowColumnReorder ) &&
( draggedElement is ColumnManagerCell ) &&
( draggedElement != this ) );
} }
void IDropTarget.DragEnter( UIElement draggedElement ) void IDropTarget.DragEnter( UIElement draggedElement )
@ -759,8 +798,7 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell != null ) if( draggedCell != null )
{ {
ColumnReorderingDragSourceManager manager = ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
// No need for drop mark when performing animated Column reordering // No need for drop mark when performing animated Column reordering
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) ) if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
@ -776,8 +814,7 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell != null ) if( draggedCell != null )
{ {
ColumnReorderingDragSourceManager manager = ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
// No need for drop mark when performing animated Column reordering // No need for drop mark when performing animated Column reordering
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) ) if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
@ -794,6 +831,11 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell == null ) if( draggedCell == null )
return; return;
this.ProcessDrop( draggedCell );
}
internal void ProcessDrop( ColumnManagerCell draggedCell )
{
ColumnReorderingDragSourceManager manager = null; ColumnReorderingDragSourceManager manager = null;
if( draggedCell != null ) if( draggedCell != null )
@ -816,15 +858,6 @@ namespace Xceed.Wpf.DataGrid
this.HideDropMark(); 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( draggedCell.ParentColumn.VisiblePosition < newPosition )
{ {
if( alignment == DropMarkAlignment.Near ) if( alignment == DropMarkAlignment.Near )
@ -847,14 +880,45 @@ namespace Xceed.Wpf.DataGrid
draggedCell.ParentColumn.VisiblePosition = newPosition + 1; 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 #endregion IDropTarget Members
// Will remain null when no AdornerLayer is found. // Will remain null when no AdornerLayer is found.
private ColumnReorderingDragSourceManager m_dragSourceManager; private ColumnReorderingDragSourceManager m_dragSourceManager;
private DropMarkAdorner m_dropMarkAdorner; private DropMarkAdorner m_dropMarkAdorner;
private DataGridContext m_dataGridContext; // = null; 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 System.Windows;
using Xceed.Wpf.DataGrid.Views;
using System.Windows.Automation.Peers; using System.Windows.Automation.Peers;
using Xceed.Wpf.DataGrid.Automation; using Xceed.Wpf.DataGrid.Automation;
using Xceed.Wpf.DataGrid.Views;
using Xceed.Utils.Wpf.DragDrop; using Xceed.Utils.Wpf.DragDrop;
using System.Diagnostics;
namespace Xceed.Wpf.DataGrid 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... 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 //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 #region AllowColumnReorder Property
@ -138,20 +139,17 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell == null ) if( draggedCell == null )
return false; return false;
ColumnReorderingDragSourceManager manager = ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) ) if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
{ {
ColumnManagerCell cell = draggedElement as ColumnManagerCell; ColumnManagerCell cell = draggedElement as ColumnManagerCell;
if( ( cell != null ) if( ( cell != null ) && ( cell.IsBeingDragged ) )
&& ( cell.IsBeingDragged ) )
{ {
DataGridContext rowDataGridContext = DataGridControl.GetDataGridContext( this ); DataGridContext rowDataGridContext = DataGridControl.GetDataGridContext( this );
if( ( rowDataGridContext != null ) if( ( rowDataGridContext != null ) && ( rowDataGridContext.Columns.Contains( cell.ParentColumn ) ) )
&& ( rowDataGridContext.Columns.Contains( cell.ParentColumn ) ) )
{ {
canDrop = true; canDrop = true;
} }
@ -180,8 +178,7 @@ namespace Xceed.Wpf.DataGrid
if( draggedCell == null ) if( draggedCell == null )
return; return;
ColumnReorderingDragSourceManager manager = ColumnReorderingDragSourceManager manager = draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
draggedCell.DragSourceManager as ColumnReorderingDragSourceManager;
if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) ) if( ( manager != null ) && ( manager.IsAnimatedColumnReorderingEnabled ) )
{ {

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

@ -17,7 +17,6 @@
using System; using System;
using System.Windows; using System.Windows;
// TODO (case 117282) : Renommer ce fichier.
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
internal delegate void ColumnReorderingEventHandler( object sender, ColumnReorderingEventArgs e ); internal delegate void ColumnReorderingEventHandler( object sender, ColumnReorderingEventArgs e );
@ -26,12 +25,12 @@ namespace Xceed.Wpf.DataGrid
{ {
#region Constructors #region Constructors
public ColumnReorderingEventArgs(RoutedEvent routedEvent, int oldVisiblePosition, int newVisiblePosition ) public ColumnReorderingEventArgs( RoutedEvent routedEvent, int oldVisiblePosition, int newVisiblePosition )
: base( routedEvent ) : base( routedEvent )
{ {
m_oldVisiblePosition = oldVisiblePosition; m_oldVisiblePosition = oldVisiblePosition;
m_newVisiblePosition = newVisiblePosition; m_newVisiblePosition = newVisiblePosition;
} }
#endregion #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 ) if( m_formatProvider == null )
{ {
return string.Format( format, value ); return string.Format( culture, format, value );
} }
else 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 // Synchronize the CurrentItem of the DataGridContext
// with the one of the CollecitonView. // with the one of the CollecitonView.
m_dataGridContext.SetCurrent( m_dataGridContext.SetCurrent(
m_collectionView.CurrentItem, null, m_collectionView.CurrentPosition, m_collectionView.CurrentItem,
m_dataGridContext.CurrentColumn, false, false, this.ShouldSynchronizeSelectionWithCurrent ); null,
m_collectionView.CurrentPosition,
m_dataGridContext.CurrentColumn,
false,
false,
this.ShouldSynchronizeSelectionWithCurrent,
AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
if( m_collectionView.CurrentItem == null ) if( m_collectionView.CurrentItem == null )
this.ChangeCurrentDataGridContext(); this.ChangeCurrentDataGridContext();
@ -163,8 +169,14 @@ namespace Xceed.Wpf.DataGrid
m_dataGridContext.CancelEdit(); m_dataGridContext.CancelEdit();
m_dataGridContext.SetCurrent( m_dataGridContext.SetCurrent(
m_collectionView.CurrentItem, null, m_collectionView.CurrentPosition, m_collectionView.CurrentItem,
m_dataGridContext.CurrentColumn, false, false, this.ShouldSynchronizeSelectionWithCurrent ); null,
m_collectionView.CurrentPosition,
m_dataGridContext.CurrentColumn,
false,
false,
this.ShouldSynchronizeSelectionWithCurrent,
AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
if( m_collectionView.CurrentItem == null ) if( m_collectionView.CurrentItem == null )
this.ChangeCurrentDataGridContext(); this.ChangeCurrentDataGridContext();
@ -180,9 +192,7 @@ namespace Xceed.Wpf.DataGrid
{ {
if( ( m_dataGridContext.ParentDataGridContext == null ) if( ( m_dataGridContext.ParentDataGridContext == null )
|| ( m_dataGridContext.ParentItem == null ) ) || ( m_dataGridContext.ParentItem == null ) )
{
return; return;
}
List<DataGridContext> childContexts = this.GetParentItemChildContexts(); List<DataGridContext> childContexts = this.GetParentItemChildContexts();
int currentContextIndex = childContexts.IndexOf( m_dataGridContext ); int currentContextIndex = childContexts.IndexOf( m_dataGridContext );
@ -200,7 +210,7 @@ namespace Xceed.Wpf.DataGrid
if( childContext.Items.Count == 0 ) if( childContext.Items.Count == 0 )
continue; continue;
childContext.SetCurrentItemCore( childContext.Items.GetItemAt( 0 ), false, this.ShouldSynchronizeSelectionWithCurrent ); childContext.SetCurrentItemCore( childContext.Items.GetItemAt( 0 ), false, this.ShouldSynchronizeSelectionWithCurrent, AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
return; return;
} }
} }
@ -216,13 +226,13 @@ namespace Xceed.Wpf.DataGrid
if( count == 0 ) if( count == 0 )
continue; continue;
childContext.SetCurrentItemCore( childContext.Items.GetItemAt( count - 1 ), false, this.ShouldSynchronizeSelectionWithCurrent ); childContext.SetCurrentItemCore( childContext.Items.GetItemAt( count - 1 ), false, this.ShouldSynchronizeSelectionWithCurrent, AutoScrollCurrentItemSourceTriggers.CollectionViewCurrentItemChanged );
return; return;
} }
} }
// No context after or before us have been found, we will set the CurrentItem to our ParentItem. // 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() private List<DataGridContext> GetParentItemChildContexts()

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

@ -15,21 +15,15 @@
***********************************************************************************/ ***********************************************************************************/
using System; using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data; 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.Input;
using System.Windows.Media; using System.Xml;
using System.Collections.ObjectModel; using Xceed.Wpf.DataGrid.Converters;
using System.ComponentModel;
using Xceed.Wpf.DataGrid.Views;
using Xceed.Wpf.DataGrid.Markup;
namespace Xceed.Wpf.DataGrid namespace Xceed.Wpf.DataGrid
{ {
@ -55,10 +49,13 @@ namespace Xceed.Wpf.DataGrid
{ {
get get
{ {
return ( m_canBeRecycled && base.CanBeRecycled ); return ( m_canBeRecycled )
&& ( base.CanBeRecycled );
} }
} }
private bool m_canBeRecycled; //= false
#endregion #endregion
#region OverrideColumnCellContentTemplate Property #region OverrideColumnCellContentTemplate Property
@ -73,13 +70,36 @@ namespace Xceed.Wpf.DataGrid
#endregion #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 ) protected override void InitializeCore( DataGridContext dataGridContext, Row parentRow, ColumnBase parentColumn )
{ {
ColumnBase oldParentColumn = this.ParentColumn; ColumnBase oldParentColumn = this.ParentColumn;
base.InitializeCore( dataGridContext, parentRow, 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 // 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 // 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 ) 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 = newThemeKey;
{
this.DefaultStyleKey = currentThemeKey;
}
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters" )] [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 the dataContext is our ParentRow, we do not create any binding
if( dataContext != this.ParentRow ) if( dataContext != this.ParentRow )
{ {
displayMemberBinding = column.GetDisplayMemberBinding();
// Disable warning for DisplayMemberBinding when internaly used
#pragma warning disable 618
displayMemberBinding = column.DisplayMemberBinding;
#pragma warning restore 618
if( displayMemberBinding == null ) if( displayMemberBinding == null )
{ {
@ -163,19 +175,13 @@ namespace Xceed.Wpf.DataGrid
{ {
bool isDataGridUnboundItemProperty; bool isDataGridUnboundItemProperty;
displayMemberBinding = ItemsSourceHelper.AutoCreateDisplayMemberBinding( displayMemberBinding = ItemsSourceHelper.AutoCreateDisplayMemberBinding( column, dataGridContext, dataContext, out isDataGridUnboundItemProperty );
column, dataGridContext, dataContext, out isDataGridUnboundItemProperty );
column.IsBoundToDataGridUnboundItemProperty = 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.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() internal override void ContentCommitted()
{ {
base.ContentCommitted(); base.ContentCommitted();
@ -222,6 +233,33 @@ namespace Xceed.Wpf.DataGrid
parentRow.EnsurePosition( dataGridContext, this ); 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 ) private static bool VerifyDisplayMemberBinding( BindingBase binding )
{ {
bool retval = false; bool retval = false;
@ -242,7 +280,5 @@ namespace Xceed.Wpf.DataGrid
return retval; 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 #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 #region NotifyOnSourceUpdated Property
public bool NotifyOnSourceUpdated public bool NotifyOnSourceUpdated
@ -210,7 +227,6 @@ namespace Xceed.Wpf.DataGrid
#endregion ReadOnly Property #endregion ReadOnly Property
#region UpdateSourceExceptionFilter Property #region UpdateSourceExceptionFilter Property
public UpdateSourceExceptionFilterCallback UpdateSourceExceptionFilter public UpdateSourceExceptionFilterCallback UpdateSourceExceptionFilter
@ -257,7 +273,6 @@ namespace Xceed.Wpf.DataGrid
#endregion Path Property #endregion Path Property
#region INTERNAL METHODS #region INTERNAL METHODS
internal Binding GetBinding() 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 ) public DataGridException( string message, Exception innerException )
: base( message, innerException ) : base( message, innerException )
{ {
} }
public DataGridException( string message, Exception innerException, DataGridControl dataGridControl )
: base( message, innerException )
{
this.DataGridControl = dataGridControl;
}
protected DataGridException( SerializationInfo info, StreamingContext context ) protected DataGridException( SerializationInfo info, StreamingContext context )
: base( info, 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