Browse Source

1.8.0 Release

pull/1645/head
emartin_cp 13 years ago
parent
commit
0c933c8124
  1. 25
      ExtendedWPFToolkitSolution/ExtendedWPFToolkit.sln
  2. 30
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.CheckLists/Views/HomeView.xaml
  3. 46
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/DataGridModule.cs
  4. 72
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Properties/AssemblyInfo.cs
  5. 116
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Samples.Modules.DataGrid.csproj
  6. 103
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/FullVersion.xaml
  7. 46
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/FullVersion.xaml.cs
  8. 54
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/HomeView.xaml
  9. 47
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/HomeView.xaml.cs
  10. 32
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/NavigationView.xaml
  11. 18
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/NavigationView.xaml.cs
  12. 11
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DateTime/Views/HomeView.xaml
  13. 2
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Magnifier/Views/HomeView.xaml
  14. 126
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.MessageBox/Views/HomeView.xaml
  15. 15
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.MessageBox/Views/HomeView.xaml.cs
  16. 115
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Numeric/Views/HomeView.xaml
  17. 1
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Pie/Views/PieChart.xaml
  18. 1
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Pie/Views/PieProgress.xaml
  19. 19
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Samples.Modules.PropertyGrid.csproj
  20. 180
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/DisplayLocalizationRes.Designer.cs
  21. 159
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/DisplayLocalizationRes.fr.resx
  22. 159
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/DisplayLocalizationRes.resx
  23. 13
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml
  24. 6
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml.cs
  25. 7
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Samples.Modules.Text.csproj
  26. 1
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/TextModule.cs
  27. 118
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/AutoSelectTextBoxView.xaml
  28. 20
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/AutoSelectTextBoxView.xaml.cs
  29. 26
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/MaskedTextBoxView.xaml
  30. 6
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/MaskedTextBoxView.xaml.cs
  31. 3
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/MultiLineTextEditor.xaml
  32. 4
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/NavigationView.xaml
  33. 3
      ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/RichTextBoxView.xaml
  34. 1
      ExtendedWPFToolkitSolution/Src/Samples/Samples/App.config
  35. 14
      ExtendedWPFToolkitSolution/Src/Samples/Samples/Resources/TreeViewStyles.xaml
  36. 4
      ExtendedWPFToolkitSolution/Src/Samples/Samples/Samples.csproj
  37. 2
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AssemblyVersionInfo.cs
  38. 31
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/AutoSelectBehaviorEnum.cs
  39. 301
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/AutoSelectTextBox.cs
  40. 76
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/QueryMoveFocusEventArgs.cs
  41. 22
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs
  42. 73
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs
  43. 2
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Themes/Generic.xaml
  44. 2
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs
  45. 4
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Converters/WizardPageButtonVisibilityConverter.cs
  46. 32
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Input/IValidateInput.cs
  47. 46
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Input/InputValidationErrorEventArgs.cs
  48. 57
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/CachedTextInfo.cs
  49. 557
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs
  50. 12
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SelectorItem.cs
  51. 113
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs
  52. 1192
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValueRangeTextBox.cs
  53. 57
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/QueryTextFromValueEventArgs.cs
  54. 70
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/QueryValueFromTextEventArgs.cs
  55. 2
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ColorUtilities.cs
  56. 163
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/NotifyPropertyChangedHelper.cs
  57. 136
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ReflectionHelper.cs
  58. 238
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/TreeHelper.cs
  59. 153
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ValueChangeHelper.cs
  60. 10
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DateTimePicker/Themes/Generic.xaml
  61. 26
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DateTimeUpDown/Implementation/DateTimeUpDown.cs
  62. 4
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Magnifier/Implementation/Magnifier.cs
  63. 108
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/AutoCompletingMaskEventArgs.cs
  64. 32
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/InsertKeyModeEnum.cs
  65. 33
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskFormatEnum.cs
  66. 2116
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskedTextBox.cs
  67. 80
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/Implementation/MessageBox.cs
  68. 43
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/Themes/Generic.xaml
  69. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ByteUpDown.cs
  70. 184
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/CommonNumericUpDown.cs
  71. 86
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DecimalUpDown.cs
  72. 86
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DoubleUpDown.cs
  73. 87
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/IntegerUpDown.cs
  74. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/LongUpDown.cs
  75. 15
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/NumericUpDown.cs
  76. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/SByteUpDown.cs
  77. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ShortUpDown.cs
  78. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/SingleUpDown.cs
  79. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/UIntegerUpDown.cs
  80. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ULongUpDown.cs
  81. 55
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/UShortUpDown.cs
  82. 67
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Themes/Generic.xaml
  83. 726
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Obselete/MaskedTextBox/Implementation/MaskedTextBox.cs
  84. 2
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs
  85. 92
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/SelectedObjectConverter.cs
  86. 52
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/UpDownEditors.cs
  87. 36
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/IPropertyParent.cs
  88. 344
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs
  89. 85
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGridUtilities.cs
  90. 282
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs
  91. 68
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItemCollection.cs
  92. 42
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml
  93. 28
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/RichTextBox.cs
  94. 42
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj
  95. 288
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/EmptyDataItem.cs
  96. 956
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualList.cs
  97. 157
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListEnumerator.cs
  98. 172
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualListTableOfContent.cs
  99. 658
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPage.cs
  100. 867
      ExtendedWPFToolkitSolution/Src/Xceed.Wpf.DataGrid/(CollectionView)/(DataVirtualization)/VirtualPageManager.cs

25
ExtendedWPFToolkitSolution/ExtendedWPFToolkit.sln

@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.ChildWindow
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.Color", "Src\Samples\Modules\Samples.Modules.Color\Samples.Modules.Color.csproj", "{A36AB9C9-D813-4018-B341-8729A9B5BD7D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.DataGrid", "Src\Samples\Modules\Samples.Modules.DataGrid\Samples.Modules.DataGrid.csproj", "{129477D9-F413-495F-BE05-D049575BC16C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.DateTime", "Src\Samples\Modules\Samples.Modules.DateTime\Samples.Modules.DateTime.csproj", "{CAB850B9-1D47-4F45-A6A5-07B48599B5D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.Numeric", "Src\Samples\Modules\Samples.Modules.Numeric\Samples.Modules.Numeric.csproj", "{CBED4977-79ED-4E46-AA00-0A4D83D333A6}"
@ -54,6 +56,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.Magnifier",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Modules.MessageBox", "Src\Samples\Modules\Samples.Modules.MessageBox\Samples.Modules.MessageBox.csproj", "{C324395B-C1D1-407B-8745-4AAC39B8BFD9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xceed.Wpf.DataGrid", "Src\Xceed.Wpf.DataGrid\Xceed.Wpf.DataGrid.csproj", "{63648392-6CE9-4A60-96D4-F9FD718D29B0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -254,6 +258,26 @@ Global
{C324395B-C1D1-407B-8745-4AAC39B8BFD9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{C324395B-C1D1-407B-8745-4AAC39B8BFD9}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{C324395B-C1D1-407B-8745-4AAC39B8BFD9}.Release|x86.ActiveCfg = Release|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Debug|x86.ActiveCfg = Debug|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Release|Any CPU.Build.0 = Release|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{63648392-6CE9-4A60-96D4-F9FD718D29B0}.Release|x86.ActiveCfg = Release|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Debug|x86.ActiveCfg = Debug|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Release|Any CPU.Build.0 = Release|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{129477D9-F413-495F-BE05-D049575BC16C}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -278,5 +302,6 @@ Global
{910A7A19-DD9F-4989-A001-BD7E5BAD2FE8} = {F927B3FE-820C-4EE1-921F-D10D3AE287AE}
{C3D3FFAD-2DA3-4142-8DE8-7045E347B63A} = {F927B3FE-820C-4EE1-921F-D10D3AE287AE}
{C324395B-C1D1-407B-8745-4AAC39B8BFD9} = {F927B3FE-820C-4EE1-921F-D10D3AE287AE}
{129477D9-F413-495F-BE05-D049575BC16C} = {F927B3FE-820C-4EE1-921F-D10D3AE287AE}
EndGlobalSection
EndGlobal

30
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.CheckLists/Views/HomeView.xaml

@ -129,7 +129,6 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="CheckListBox Usage:" Margin="5" Style="{StaticResource Header}" />
<xctk:CheckListBox x:Name="_checkListBox"
Grid.Column="0"
@ -152,34 +151,7 @@
ValueMemberPath="{Binding ElementName=_valueMemberPath, Path=SelectedItem}"
SelectedMemberPath="{Binding ElementName=_selectedMemberPath, Path=Text}"
DisplayMemberPath="{Binding ElementName=_displayMemberPath, Path=SelectedItem}"
IsDropDownOpen="{Binding ElementName=_isDropDownOpen, Path=IsChecked, Mode=TwoWay}"
/>
<!---->
IsDropDownOpen="{Binding ElementName=_isDropDownOpen, Path=IsChecked, Mode=TwoWay}" />
</Grid>
<!--<StackPanel>
<xctk:CheckComboBox x:Name="_combo"
HorizontalAlignment="Center"
VerticalAlignment="Center"
DisplayMemberPath="Color"
ValueMemberPath="Level"
SelectedItems="{Binding SelectedItems}"
SelectedValue="{Binding SelectedValue}" />
<xctk:CheckListBox x:Name="_listBox" Visibility="Collapsed"
Height="250"
DisplayMemberPath="Color"
ValueMemberPath="Level"
SelectedMemberPath="IsSelected"
SelectedItems="{Binding SelectedItems}"
SelectedValue="{Binding SelectedValue}" />
<TextBlock Text="{Binding SelectedValue}" />
<ListBox ItemsSource="{Binding SelectedItems}" Height="50" Visibility="Collapsed"/>
<Button Click="Button_Click">Set</Button>
</StackPanel>-->
</Grid>
</sample:DemoView>

46
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/DataGridModule.cs

@ -0,0 +1,46 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;
using Samples.Infrastructure;
using Samples.Infrastructure.Extensions;
using Samples.Modules.DataGrid.Views;
namespace Samples.Modules.DataGrid
{
public class DataGridModule : ModuleBase
{
public DataGridModule( IUnityContainer container, IRegionManager regionManager )
: base( container, regionManager )
{
}
protected override void InitializeModule()
{
RegionManager.RegisterViewWithRegion( RegionNames.NavigationRegion, typeof( NavigationView ) );
}
protected override void RegisterViewsAndTypes()
{
Container.RegisterNavigationType( typeof( HomeView ) );
Container.RegisterNavigationType( typeof( FullVersion ) );
}
}
}

72
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Properties/AssemblyInfo.cs

@ -0,0 +1,72 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle( "Extended WPF Toolkit DataGrid Sample" )]
[assembly: AssemblyDescription( "" )]
[assembly: AssemblyConfiguration( "" )]
[assembly: AssemblyCompany( "Xceed Software Inc." )]
[assembly: AssemblyProduct( "Extended WPF Toolkit DataGrid Sample" )]
[assembly: AssemblyCopyright( "Copyright © Xceed Software Inc. 2010-2012" )]
[assembly: AssemblyTrademark( "" )]
[assembly: AssemblyCulture( "" )]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible( false )]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion( "1.0.0.0" )]
[assembly: AssemblyFileVersion( "1.0.0.0" )]

116
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Samples.Modules.DataGrid.csproj

@ -0,0 +1,116 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{129477D9-F413-495F-BE05-D049575BC16C}</ProjectGuid>
<OutputType>library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Samples.Modules.DataGrid</RootNamespace>
<AssemblyName>Samples.Modules.DataGrid</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Practices.Prism">
<HintPath>..\..\..\..\Libs\Prism\Microsoft.Practices.Prism.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity">
<HintPath>..\..\..\..\Libs\Prism\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="Xceed.Wpf.DataGrid.Samples.SampleData">
<HintPath>..\..\..\..\Libs\Xceed.Wpf.DataGrid.Samples.SampleData.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="DataGridModule.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Views\FullVersion.xaml.cs">
<DependentUpon>FullVersion.xaml</DependentUpon>
</Compile>
<Compile Include="Views\HomeView.xaml.cs">
<DependentUpon>HomeView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\NavigationView.xaml.cs">
<DependentUpon>NavigationView.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Xceed.Wpf.DataGrid\Xceed.Wpf.DataGrid.csproj">
<Project>{63648392-6CE9-4A60-96D4-F9FD718D29B0}</Project>
<Name>Xceed.Wpf.DataGrid</Name>
</ProjectReference>
<ProjectReference Include="..\..\Samples.Infrastructure\Samples.Infrastructure.csproj">
<Project>{A4A049A4-665A-4651-9046-7D06E9D0CCDC}</Project>
<Name>Samples.Infrastructure</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="Views\FullVersion.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\HomeView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\NavigationView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(TargetDir)*.*" "$(SolutionDir)Src\Samples\Samples\bin\$(ConfigurationName)\" /Y
xcopy "$(ProjectDir)Views" "$(SolutionDir)Src\Samples\Samples\bin\$(ConfigurationName)\Samples\$(ProjectName)\" /s /Y /I</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

103
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/FullVersion.xaml

@ -0,0 +1,103 @@
<!--*********************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<sample:DemoView x:Class="Samples.Modules.DataGrid.Views.FullVersion"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Samples.Infrastructure.Controls;assembly=Samples.Infrastructure"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:compModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Title="Full Version" >
<StackPanel>
<RichTextBox IsReadOnly="True" IsDocumentEnabled="False" BorderThickness="0">
<FlowDocument>
<Paragraph>
The full featured version of the DataGrid available commercially will provide
you with extended features like:
</Paragraph>
<List>
<ListItem>
<Paragraph>Master Details</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Filter Row</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Insertion Row</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Excel Auto-Filtering</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Column Chooser</Paragraph>
</ListItem>
<ListItem>
<Paragraph>CardView, CompactCardView</Paragraph>
</ListItem>
<ListItem>
<Paragraph>3DView, MultiSurfaceView</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Statistical Functions and Summary row</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Print, Print Preview</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Export to Excel</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Fixed Column Splitter UI element</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Persist User Settings</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Design time support in Visual Studio and Expression Blend</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Comprehensive documentation fully integrated into Visual Studio</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Includes a variety of VB.NET and C# sample applications to get you started</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Office 2007 Themes: Blue, Black, and Silver</Paragraph>
</ListItem>
<ListItem>
<Paragraph>The Xceed Live Explorer theme</Paragraph>
</ListItem>
<ListItem>
<Paragraph>Includes Xceed 3D Views for WPF</Paragraph>
</ListItem>
<ListItem>
<Paragraph>And many more....</Paragraph>
</ListItem>
</List>
</FlowDocument>
</RichTextBox>
<TextBlock Margin="0,20,0,0">
<Hyperlink NavigateUri="http://www.xceed.com/Grid_WPF_Intro.html" RequestNavigate="Hyperlink_RequestNavigate">
Click here for more details about the full featured DataGrid control.
</Hyperlink>
</TextBlock>
</StackPanel>
</sample:DemoView>

46
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/FullVersion.xaml.cs

@ -0,0 +1,46 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using Microsoft.Practices.Prism.Regions;
using Samples.Infrastructure.Controls;
using Xceed.Wpf.DataGrid.Samples.SampleData;
using System.Data;
using Xceed.Wpf.DataGrid;
using System.Diagnostics;
namespace Samples.Modules.DataGrid.Views
{
/// <summary>
/// Interaction logic for FullVersion.xaml
/// </summary>
[RegionMemberLifetime( KeepAlive = false )]
public partial class FullVersion : DemoView
{
public FullVersion()
{
InitializeComponent();
}
private void Hyperlink_RequestNavigate( object sender, System.Windows.Navigation.RequestNavigateEventArgs e )
{
Process.Start( new ProcessStartInfo( e.Uri.AbsoluteUri ) );
e.Handled = true;
}
}
}

54
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/HomeView.xaml

@ -0,0 +1,54 @@
<!--*********************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<sample:DemoView x:Class="Samples.Modules.DataGrid.Views.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Samples.Infrastructure.Controls;assembly=Samples.Infrastructure"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid"
xmlns:compModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
Title="DataGrid"
x:Name="_demo">
<sample:DemoView.Description>
The experience Xceed DataGrid for WPF provides centers on its Tableflow view, which lets you take advantage of a stunning, shaded appearance and capabilities such as inertial smooth scrolling and animated full-column reordering—which mimic the physics of real-life movement. Add to that the datagrid’s zero-lag data virtualization, and you have the fastest WPF datagrid around—in performance and feel.
It's rock-solid and time-tested, so you can trust it in your most important applications. Constantly evolving—no other datagrid is updated as often—it has more features than any other offering and a flexible, extensible object model. It also provides unbeatable performance by handling millions of rows and thousands of columns, and integrates easily into any WPF app. It’s easy to understand why it’s the most-adopted WPF datagrid available and used by Microsoft in Visual Studio 2010 and by IBM U2 in SystemBuilder 4GL (SB+)!
</sample:DemoView.Description>
<Grid>
<Grid.Resources>
<xcdg:DataGridCollectionViewSource x:Key="cvsOrders"
Source="{Binding ElementName=_demo, Path=Orders}">
<xcdg:DataGridCollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ShipCountry" />
<PropertyGroupDescription PropertyName="ShipCity" />
</xcdg:DataGridCollectionViewSource.GroupDescriptions>
</xcdg:DataGridCollectionViewSource>
</Grid.Resources>
<xcdg:DataGridControl x:Name="_dataGrid"
MaxHeight="400"
ItemsSource="{Binding Source={StaticResource cvsOrders}}" >
<xcdg:DataGridControl.View>
<xcdg:TableflowView FixedColumnCount="2" />
</xcdg:DataGridControl.View>
</xcdg:DataGridControl>
</Grid>
</sample:DemoView>

47
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/HomeView.xaml.cs

@ -0,0 +1,47 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using Microsoft.Practices.Prism.Regions;
using Samples.Infrastructure.Controls;
using Xceed.Wpf.DataGrid.Samples.SampleData;
using System.Data;
using Xceed.Wpf.DataGrid;
namespace Samples.Modules.DataGrid.Views
{
/// <summary>
/// Interaction logic for HomeView.xaml
/// </summary>
[RegionMemberLifetime( KeepAlive = false )]
public partial class HomeView : DemoView
{
public HomeView()
{
this.Orders = DataProvider.GetNorthwindDataSet().Tables[ "Orders" ];
InitializeComponent();
}
public DataTable Orders
{
get;
private set;
}
}
}

32
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/NavigationView.xaml

@ -0,0 +1,32 @@
<!--*********************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<TreeViewItem x:Class="Samples.Modules.DataGrid.Views.NavigationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Samples.Modules.DataGrid.Views"
Header="DataGrid" Tag="{x:Type views:HomeView}"
Style="{StaticResource newFeature}">
<TreeViewItem.Resources>
<Style TargetType="views:NavigationView" BasedOn="{StaticResource {x:Type TreeViewItem}}" />
</TreeViewItem.Resources>
<TreeViewItem Header="Full Version" Tag="{x:Type views:FullVersion}" />
</TreeViewItem>

18
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DoubleUpDownEditor.cs → ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DataGrid/Views/NavigationView.xaml.cs

@ -17,18 +17,18 @@
**********************************************************************/
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
using System.Windows.Controls;
namespace Samples.Modules.DataGrid.Views
{
public class DoubleUpDownEditor : TypeEditor<DoubleUpDown>
/// <summary>
/// Interaction logic for NavigationView.xaml
/// </summary>
public partial class NavigationView : TreeViewItem
{
protected override void SetControlProperties()
{
Editor.BorderThickness = new System.Windows.Thickness( 0 );
}
protected override void SetValueDependencyProperty()
public NavigationView()
{
ValueProperty = DoubleUpDown.ValueProperty;
InitializeComponent();
}
}
}

11
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.DateTime/Views/HomeView.xaml

@ -16,7 +16,7 @@
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<!--//#TODODOC for description -->
<sample:DemoView x:Class="Samples.Modules.DateTime.Views.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -25,7 +25,7 @@
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:conv="clr-namespace:Samples.Modules.DateTime.Converters"
Title="DateTime Controls"
Description="DateTimePicker and TimePicker controls let you the date and time with many possibilities. The TimePicker is included in the DateTimePicker.">
Description="The DateTimePicker and TimePicker controls let you select the date and the time in several ways. The TimePicker is used in the DateTimePicker.">
<sample:DemoView.Resources>
<conv:DateTimeToTimeSpanConverter x:Key="dateTimeToTimeSpanConverter" />
@ -45,7 +45,6 @@
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- TODODOC: Common Features -->
<GroupBox Header="Features" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" >
<Grid>
<Grid.RowDefinitions>
@ -67,20 +66,17 @@
</Grid>
</GroupBox>
<!--TODODOC: DateTimePicker -->
<StackPanel Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left">
<TextBlock Text="DateTimePicker Usage: " Margin="0,10,0,0" Style="{StaticResource Header}" />
<xctk:DateTimePicker x:Name="_datetimePicker"
Width="300"
VerticalAlignment="Top"
IsReadOnly="False"
BorderBrush="Black"
IsReadOnly="False"
TimeFormat="{Binding Source={x:Reference _timeFormat}, Path=SelectedItem}"
TimeWatermark="{Binding Source={x:Reference _timeWatermark}, Path=Text}"/>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch">
<!-- TODODOC TimePicker Features-->
<GroupBox Header="TimePicker Features" Margin="0,15,0,0">
<Grid>
<Grid.RowDefinitions>
@ -102,7 +98,6 @@
</Grid>
</GroupBox>
<!--TODODOC: TimePicker -->
<StackPanel>
<TextBlock Text="TimePicker Usage: " Style="{StaticResource Header}" />
<xctk:TimePicker x:Name="_timePicker"

2
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Magnifier/Views/HomeView.xaml

@ -16,7 +16,7 @@
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<!--//#TODODOC for description -->
<sample:DemoView x:Class="Samples.Modules.Magnifier.Views.HomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

126
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.MessageBox/Views/HomeView.xaml

@ -24,8 +24,48 @@
Title="MessageBox"
Description="This extended MessageBox allows you to customize and style various aspects of the control.">
<sample:DemoView.Resources>
<SolidColorBrush x:Key="MyButtonHoverBrush" Color="YellowGreen" />
<SolidColorBrush x:Key="MyButtonPressedBrush" Color="Maroon" />
<LinearGradientBrush x:Key="buttonRegionBackground" StartPoint="0,0" EndPoint="1,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FF3D3D3D" />
<GradientStop Offset="1" Color="#FF000000" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="MyButtonHoverBrush" Color="#FFD23C93" />
<SolidColorBrush x:Key="MyButtonPressedBrush" Color="#FF841B5D" />
<LinearGradientBrush x:Key="WindowDarkBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0" />
<GradientStop Color="#FF8399A9" Offset="0.375" />
<GradientStop Color="#FF718597" Offset="0.375" />
<GradientStop Color="#FF617584" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="WindowButtonHoverBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FFb5bdc8" />
<GradientStop Offset="0.370" Color="#FF8399a9" />
<GradientStop Offset="0.370" Color="#FF718597" />
<GradientStop Offset="0.906" Color="#FFb9c1ca" />
<GradientStop Offset="1" Color="#FFb9c1ca" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="WindowButtonPressedBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FF6b7c8d" />
<GradientStop Offset="0.370" Color="#FF4d606f" />
<GradientStop Offset="0.370" Color="#FF465460" />
<GradientStop Offset="0.906" Color="#FF262d33" />
<GradientStop Offset="1" Color="#FF262d33" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Style x:Key="MyCloseButtonStyle" TargetType="Button">
<Setter Property="Template">
@ -49,9 +89,15 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" To=".3"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="Opacity" To=".3"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" CornerRadius="0,0,2,0" Background="Green">
<Border x:Name="Background" CornerRadius="0,0,2,0" Background="#FF565456">
<Border Margin="1,0,1,1" BorderBrush="#59FFFFFF" BorderThickness="1" CornerRadius="0,0,1,0"/>
</Border>
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
@ -67,24 +113,70 @@
</Setter>
</Style>
<Style x:Key="WindowButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="#FFFFFFFF" />
<Setter Property="Padding" Value="3" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{StaticResource WindowButtonHoverBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background)">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{StaticResource WindowButtonPressedBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" CornerRadius="0,0,2,0" Background="{StaticResource WindowDarkBrush}">
<Border Margin="1,0,1,1" BorderBrush="#59FFFFFF" BorderThickness="1" CornerRadius="0,0,1,0" />
</Border>
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="messageBoxStyle" TargetType="{x:Type xctk:MessageBox}">
<Setter Property="Background" Value="Aquamarine" />
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="CaptionForeground" Value="Orange" />
<Setter Property="WindowBorderBrush" Value="Blue" />
<Setter Property="WindowBackground" Value="Green" />
<Setter Property="WindowOpacity" Value="0.3" />
<Setter Property="Foreground" Value="Purple"/>
<Setter Property="Background" Value="Black" />
<Setter Property="BorderBrush" Value="Pink" />
<Setter Property="CaptionForeground" Value="White" />
<Setter Property="WindowBorderBrush" Value="Black" />
<Setter Property="WindowBackground" Value="#FF7304A2" />
<Setter Property="WindowOpacity" Value="0.65" />
<Setter Property="Foreground" Value="White"/>
<Setter Property="ButtonRegionBackground" Value="{StaticResource buttonRegionBackground}" />
<Setter Property="OkButtonStyle" Value="{StaticResource WindowButtonStyle}" />
<Setter Property="CancelButtonStyle" Value="{StaticResource WindowButtonStyle}" />
<Setter Property="YesButtonStyle" Value="{StaticResource WindowButtonStyle}" />
<Setter Property="NoButtonStyle" Value="{StaticResource WindowButtonStyle}" />
<Setter Property="CloseButtonStyle" Value="{StaticResource MyCloseButtonStyle}"/>
</Style>
</sample:DemoView.Resources>
<Grid >
<Button Width="300"
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<Button Width="150"
Height="100"
Margin="10"
Content="Standard MessageBox"
Click="StandardMessageBoxButton_Click"/>
<Button Width="150"
Height="100"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Content="Show me that ugly styled MessageBox!"
Click="Button_Click"/>
</Grid>
Content="Styled MessageBox"
Click="StyledMessageBoxButton_Click"/>
</StackPanel>
</sample:DemoView>

15
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.MessageBox/Views/HomeView.xaml.cs

@ -32,16 +32,25 @@ namespace Samples.Modules.MessageBox.Views
[RegionMemberLifetime( KeepAlive = false )]
public partial class HomeView : DemoView
{
private string _standardTitle = "Standard MessageBox";
private string _styledTitle = "Extended WPF Toolkit MessageBox";
private string _standardMessage = "The standard system MessageBox will always have this look. No styling is possible.";
private string _styledMessage = "The Toolkit MessageBox allows you to style it in order to integrate it into your application colors and styles.";
public HomeView()
{
InitializeComponent();
}
private void Button_Click( object sender, System.Windows.RoutedEventArgs e )
private void StandardMessageBoxButton_Click( object sender, System.Windows.RoutedEventArgs e )
{
System.Windows.Style style = ( System.Windows.Style )this.Resources[ "messageBoxStyle" ];
Xceed.Wpf.Toolkit.MessageBox.Show( null, "Hello World!", "Extended WPF Toolkit MessageBox", style );
System.Windows.MessageBox.Show( _standardMessage, _standardTitle );
}
private void StyledMessageBoxButton_Click( object sender, System.Windows.RoutedEventArgs e )
{
System.Windows.Style style = ( System.Windows.Style )this.Resources[ "messageBoxStyle" ];
Xceed.Wpf.Toolkit.MessageBox.Show( null, _styledMessage, _styledTitle, style );
}
}
}

115
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Numeric/Views/HomeView.xaml

@ -21,58 +21,71 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Samples.Infrastructure.Controls;assembly=Samples.Infrastructure"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="Numeric Controls"
Description="The DecimalUpDown, DoubleUpDown and IntegerUpDown provides a TextBox with button spinners that allow incrementing and decrementing numeric values by using the spinner buttons, keyboard up/down arrows, or mouse wheel.">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
Title="Numeric Controls">
<StackPanel>
<RichTextBox IsReadOnly="True" BorderThickness="0">
<FlowDocument>
<Paragraph>
Numeric up-down controls provides a TextBox with button spinners that allow incrementing
and decrementing numeric values by using the spinner buttons, keyboard up/down arrows, or mouse wheel
</Paragraph>
<Paragraph>
The following controls are present to support various native numeric types:
ByteUpDown, ShortUpDown, IntegerUpDown, LongUpDown, SingleUpDown, DoubleUpDown, DecimalUpDown.
</Paragraph>
</FlowDocument>
</RichTextBox>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<GroupBox Header="Features" Grid.Row="0" Margin="5">
<Grid Margin="5" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="FormatString:" VerticalAlignment="Center" />
<ComboBox x:Name="_formatString" SelectedIndex="0" Grid.Column="1" Width="150" Margin="5">
<ComboBoxItem Tag="C2">Currency</ComboBoxItem>
<ComboBoxItem Tag="F2">Fixed Point</ComboBoxItem>
<ComboBoxItem Tag="G">General</ComboBoxItem>
<ComboBoxItem Tag="N">Number</ComboBoxItem>
<ComboBoxItem Tag="P2">Percent</ComboBoxItem>
</ComboBox>
<TextBlock Text="Watermark:" Grid.Row="1" VerticalAlignment="Center" />
<TextBox x:Name="_watermark" Grid.Row="1" Grid.Column="1" Width="150" Margin="5" Text="Enter Value" />
<TextBlock Text="Show Button Spinner:" Grid.Row="2" VerticalAlignment="Center" />
<CheckBox x:Name="_showButtonSpinner" Grid.Row="2" Grid.Column="1" IsChecked="True" ClickMode="Press" Margin="5" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Text="Increment" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Grid.Row="1" Text="Minimum" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Grid.Row="2" Text="Maximum" VerticalAlignment="Center" />
<xctk:DecimalUpDown Grid.Column="3" Name="_increment" Minimum="0" Value="0.5" VerticalAlignment="Center" Margin="5" Width="150" />
<xctk:DecimalUpDown Grid.Column="3" Grid.Row="1" Name="_minimum" Value="-100" VerticalAlignment="Center" Margin="5" Width="150" />
<xctk:DecimalUpDown Grid.Column="3" Grid.Row="2" Name="_maximum" Value="100" VerticalAlignment="Center" Margin="5" Width="150" />
</Grid>
</GroupBox>
<GroupBox Header="Features" Grid.Row="0" Margin="5">
<Grid Margin="5" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Text="FormatString:" VerticalAlignment="Center" />
<ComboBox x:Name="_formatString" SelectedIndex="0" Grid.Column="1" Width="150" Margin="5">
<ComboBoxItem Tag="C2">Currency</ComboBoxItem>
<ComboBoxItem Tag="F2">Fixed Point</ComboBoxItem>
<ComboBoxItem Tag="G">General</ComboBoxItem>
<ComboBoxItem Tag="N">Number</ComboBoxItem>
<ComboBoxItem Tag="P2">Percent</ComboBoxItem>
</ComboBox>
<TextBlock Text="Watermark:" Grid.Row="1" VerticalAlignment="Center" />
<TextBox x:Name="_watermark" Grid.Row="1" Grid.Column="1" Width="150" Margin="5" Text="Enter Value" />
<TextBlock Text="Show Button Spinner:" Grid.Row="2" VerticalAlignment="Center" />
<CheckBox x:Name="_showButtonSpinner" Grid.Row="2" Grid.Column="1" IsChecked="True" ClickMode="Press" Margin="5" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Text="Increment" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Grid.Row="1" Text="Minimum" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Grid.Row="2" Text="Maximum" VerticalAlignment="Center" />
<xctk:DecimalUpDown Grid.Column="3" Name="_increment" Minimum="0" Value="0.5" VerticalAlignment="Center" Margin="5" Width="150" />
<xctk:DecimalUpDown Grid.Column="3" Grid.Row="1" Name="_minimum" Value="-100" VerticalAlignment="Center" Margin="5" Width="150" />
<xctk:DecimalUpDown Grid.Column="3" Grid.Row="2" Name="_maximum" Value="100" VerticalAlignment="Center" Margin="5" Width="150" />
</Grid>
</GroupBox>
<StackPanel Grid.Row="1" Margin="10" HorizontalAlignment="Left">
<TextBlock Text="Usage:" Style="{StaticResource Header}" />
<xctk:DecimalUpDown Margin="10" Width="250"
Increment="{Binding Value, ElementName=_increment}"
Maximum="{Binding Value, ElementName=_maximum}"
Minimum="{Binding Value, ElementName=_minimum}"
FormatString="{Binding SelectedItem.Tag, ElementName=_formatString}"
Watermark="{Binding Text, ElementName=_watermark}"
ShowButtonSpinner="{Binding IsChecked, ElementName=_showButtonSpinner, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Grid.Row="1" Margin="10" HorizontalAlignment="Left">
<TextBlock Text="Usage:" Style="{StaticResource Header}" />
<xctk:DecimalUpDown Margin="10" Width="250"
Increment="{Binding Value, ElementName=_increment}"
Maximum="{Binding Value, ElementName=_maximum}"
Minimum="{Binding Value, ElementName=_minimum}"
FormatString="{Binding SelectedItem.Tag, ElementName=_formatString}"
Watermark="{Binding Text, ElementName=_watermark}"
ShowButtonSpinner="{Binding IsChecked, ElementName=_showButtonSpinner, Mode=TwoWay}"/>
</StackPanel>
</Grid>
</Grid>
</StackPanel>
</sample:DemoView>

1
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Pie/Views/PieChart.xaml

@ -24,7 +24,6 @@
xmlns:local="clr-namespace:Samples.Modules.Pie.Views"
Title="Chart"
Description="Obviously, the Pie control can be used to create a pie chart.">
<!--TODODOC See description above and remove this comment-->
<sample:DemoView.Resources>
<XmlDataProvider x:Key="XMLData">

1
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Pie/Views/PieProgress.xaml

@ -24,7 +24,6 @@
xmlns:local="clr-namespace:Samples.Modules.Pie.Views"
Title="Progress"
Description="The Pie control properties can be animated to create various effects and controls like this circular progress bar">
<!--TODODOC See description above and remove this comment-->
<sample:DemoView.Resources>
<ControlTemplate x:Key="PieProgressTemplate"

19
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Samples.Modules.PropertyGrid.csproj

@ -84,6 +84,11 @@
<Compile Include="Views\DefaultEditors.xaml.cs">
<DependentUpon>DefaultEditors.xaml</DependentUpon>
</Compile>
<Compile Include="Views\DisplayLocalizationRes.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>DisplayLocalizationRes.resx</DependentUpon>
</Compile>
<Compile Include="Views\ExpandableProperties.xaml.cs">
<DependentUpon>ExpandableProperties.xaml</DependentUpon>
</Compile>
@ -136,9 +141,21 @@
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Views\DisplayLocalizationRes.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>DisplayLocalizationRes.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Views\DisplayLocalizationRes.fr.resx">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy "$(TargetDir)*.*" "$(SolutionDir)Src\Samples\Samples\bin\$(ConfigurationName)\" /Y
<PostBuildEvent>xcopy "$(TargetDir)*.*" "$(SolutionDir)Src\Samples\Samples\bin\$(ConfigurationName)\" /Y /S
xcopy "$(ProjectDir)Views" "$(SolutionDir)Src\Samples\Samples\bin\$(ConfigurationName)\Samples\$(ProjectName)\" /s /Y /I</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

180
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/DisplayLocalizationRes.Designer.cs

@ -0,0 +1,180 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.269
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Samples.Modules.PropertyGrid.Views {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class DisplayLocalizationRes {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal DisplayLocalizationRes() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Samples.Modules.PropertyGrid.Views.DisplayLocalizationRes", typeof(DisplayLocalizationRes).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Details.
/// </summary>
internal static string DetailsCategory {
get {
return ResourceManager.GetString("DetailsCategory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Favorite Actor 1 (No DisplayName).
/// </summary>
internal static string FavoriteActor1 {
get {
return ResourceManager.GetString("FavoriteActor1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This property type is an enum where values has no DisplayName attributes. Theses values display are provided by ToString() method.
/// </summary>
internal static string FavoriteActor1Desc {
get {
return ResourceManager.GetString("FavoriteActor1Desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Favorite Actor 2 (With DisplayName).
/// </summary>
internal static string FavoriteActor2 {
get {
return ResourceManager.GetString("FavoriteActor2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This property type is an enum where values are decorated with the ExtendedDisplayName attribute. Combined with the EnumDisplayNameConverter, this allow to customize display values.
/// </summary>
internal static string FavoriteActor2Desc {
get {
return ResourceManager.GetString("FavoriteActor2Desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Favorite Actor 3.
/// </summary>
internal static string FavoriteActor3 {
get {
return ResourceManager.GetString("FavoriteActor3", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &quot;(Not listed)&quot; enum value show that enum values can also be localized.
/// </summary>
internal static string FavoriteActor3Desc {
get {
return ResourceManager.GetString("FavoriteActor3Desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to First Name.
/// </summary>
internal static string FirstName {
get {
return ResourceManager.GetString("FirstName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to First name of that person.
/// </summary>
internal static string FirstNameDesc {
get {
return ResourceManager.GetString("FirstNameDesc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Information.
/// </summary>
internal static string InfoCategory {
get {
return ResourceManager.GetString("InfoCategory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Last Name.
/// </summary>
internal static string LastName {
get {
return ResourceManager.GetString("LastName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Usualy the Familly name of the person.
/// </summary>
internal static string LastNameDesc {
get {
return ResourceManager.GetString("LastNameDesc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to (No listed).
/// </summary>
internal static string NotListed {
get {
return ResourceManager.GetString("NotListed", resourceCulture);
}
}
}
}

159
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/DisplayLocalizationRes.fr.resx

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="DetailsCategory" xml:space="preserve">
<value>Détails</value>
</data>
<data name="FavoriteActor1" xml:space="preserve">
<value>Acteur Favori 1 (Aucun DisplayName)</value>
</data>
<data name="FavoriteActor1Desc" xml:space="preserve">
<value>Le type de cette propriété est un enum où les valeurs n'ont aucun attribut "DisplayName". Les valeur affiché sont retourné par la méthode ToString()</value>
</data>
<data name="FavoriteActor2" xml:space="preserve">
<value>Acteur Favori 2 (Avec DisplayName)</value>
</data>
<data name="FavoriteActor2Desc" xml:space="preserve">
<value>Le type de cette propriété est un enum où les valeurs sont décoré avec l'attribut "DisplayName". Les valeurs affichées sont celles spécifié par l'attribut ExtendedDisplayName</value>
</data>
<data name="FavoriteActor3" xml:space="preserve">
<value>Acteur Favori 3</value>
</data>
<data name="FavoriteActor3Desc" xml:space="preserve">
<value>La valeur "(Non proposé)" démontre que les valeur des enum peuvent aussi être localisée</value>
</data>
<data name="FirstName" xml:space="preserve">
<value>Prénom</value>
</data>
<data name="FirstNameDesc" xml:space="preserve">
<value>Prénom de la personne</value>
</data>
<data name="InfoCategory" xml:space="preserve">
<value>Information</value>
</data>
<data name="LastName" xml:space="preserve">
<value>Nom de famille</value>
</data>
<data name="LastNameDesc" xml:space="preserve">
<value>Le nom de famille de la personne</value>
</data>
<data name="NotListed" xml:space="preserve">
<value>(Non proposé)</value>
</data>
</root>

159
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/DisplayLocalizationRes.resx

@ -0,0 +1,159 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="DetailsCategory" xml:space="preserve">
<value>Details</value>
</data>
<data name="FavoriteActor1" xml:space="preserve">
<value>Favorite Actor 1 (No DisplayName)</value>
</data>
<data name="FavoriteActor1Desc" xml:space="preserve">
<value>This property type is an enum where values has no DisplayName attributes. Theses values display are provided by ToString() method</value>
</data>
<data name="FavoriteActor2" xml:space="preserve">
<value>Favorite Actor 2 (With DisplayName)</value>
</data>
<data name="FavoriteActor2Desc" xml:space="preserve">
<value>This property type is an enum where values are decorated with the ExtendedDisplayName attribute. Combined with the EnumDisplayNameConverter, this allow to customize display values</value>
</data>
<data name="FavoriteActor3" xml:space="preserve">
<value>Favorite Actor 3</value>
</data>
<data name="FavoriteActor3Desc" xml:space="preserve">
<value>"(Not listed)" enum value show that enum values can also be localized</value>
</data>
<data name="FirstName" xml:space="preserve">
<value>First Name</value>
</data>
<data name="FirstNameDesc" xml:space="preserve">
<value>First name of that person</value>
</data>
<data name="InfoCategory" xml:space="preserve">
<value>Information</value>
</data>
<data name="LastName" xml:space="preserve">
<value>Last Name</value>
</data>
<data name="LastNameDesc" xml:space="preserve">
<value>Usualy the Familly name of the person</value>
</data>
<data name="NotListed" xml:space="preserve">
<value>(No listed)</value>
</data>
</root>

13
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml

@ -34,6 +34,7 @@
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@ -57,6 +58,8 @@
<TextBlock Text="Show Advanced Options:" VerticalAlignment="Center" Grid.Row="1" Grid.Column="2" />
<CheckBox x:Name="_showAdvancedOptions" Grid.Row="1" Grid.Column="3" IsChecked="True" VerticalAlignment="Center" Margin="5" ToolTip="Shows/Hides the advanced options menu next to a property." />
<TextBlock Text="IsReadOnly:" VerticalAlignment="Center" Grid.Row="2" Grid.Column="0" />
<CheckBox x:Name="_isReadOnly" Grid.Row="2" Grid.Column="1" IsChecked="False" VerticalAlignment="Center" Margin="5" ToolTip="Set the IsReadOnly property to true or false" />
</Grid>
</GroupBox>
@ -70,14 +73,18 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button x:Name="_button" Height="200" Width="200" Margin="25" HorizontalAlignment="Center" VerticalAlignment="Center">Inspect Me</Button>
<StackPanel>
<Button x:Name="_button1" Click="OnButtonClick" Height="200" Width="200" Margin="25" HorizontalAlignment="Center" VerticalAlignment="Center">Inspect Me</Button>
<Button x:Name="_button2" Click="OnButtonClick" Foreground="Red" FontSize="22" FontFamily="Bell MT" Height="50" Width="200" Margin="25" HorizontalAlignment="Center" VerticalAlignment="Center">Inspect That</Button>
</StackPanel>
<xctk:PropertyGrid Grid.Column="1"
x:Name="_propertyGrid"
ShowSummary="{Binding IsChecked, ElementName=_showSummary}"
Filter="{Binding Text, ElementName=_filter, Mode=TwoWay}"
IsCategorized="{Binding IsChecked, ElementName=_isCategorized, Mode=TwoWay}"
ShowAdvancedOptions="{Binding IsChecked, ElementName=_showAdvancedOptions}"
SelectedObject="{Binding ElementName=_button}" />
ShowAdvancedOptions="{Binding IsChecked, ElementName=_showAdvancedOptions}"
IsReadOnly="{Binding IsChecked, ElementName=_isReadOnly}"/>
</Grid>
</StackPanel>
</Grid>

6
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.PropertyGrid/Views/HomeView.xaml.cs

@ -19,6 +19,7 @@
using Microsoft.Practices.Prism.Regions;
using Samples.Infrastructure.Controls;
using System;
namespace Samples.Modules.PropertyGrid.Views
{
@ -32,5 +33,10 @@ namespace Samples.Modules.PropertyGrid.Views
{
InitializeComponent();
}
private void OnButtonClick( object sender, EventArgs e )
{
_propertyGrid.SelectedObject = sender;
}
}
}

7
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Samples.Modules.Text.csproj

@ -69,6 +69,9 @@
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Views\AutoSelectTextBoxView.xaml.cs">
<DependentUpon>AutoSelectTextBoxView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\HomeView.xaml.cs">
<DependentUpon>HomeView.xaml</DependentUpon>
</Compile>
@ -90,6 +93,10 @@
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Page Include="Views\AutoSelectTextBoxView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Views\HomeView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

1
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/TextModule.cs

@ -44,6 +44,7 @@ namespace Samples.Modules.Text
Container.RegisterNavigationType( typeof( MultiLineTextEditorView ) );
Container.RegisterNavigationType( typeof( RichTextBoxView ) );
Container.RegisterNavigationType( typeof( WatermarkTextBoxView ) );
Container.RegisterNavigationType( typeof( AutoSelectTextBoxView ) );
}
}
}

118
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/AutoSelectTextBoxView.xaml

@ -0,0 +1,118 @@
<!--*********************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<sample:DemoView x:Class="Samples.Modules.Text.Views.AutoSelectTextBoxView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Samples.Infrastructure.Controls;assembly=Samples.Infrastructure"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="AutoSelectTextBox"
Description="The AutoSelectTextBox allow to select the text content when the control get the focus. It also allow to affect the Focus navigation behavior winthin the control">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type xctk:AutoSelectTextBox}">
<Setter Property="Margin" Value="5"/>
<Setter Property="AutoSelectBehavior" Value="{Binding SelectedItem, ElementName=_autoSelectBehavior}"/>
<Setter Property="AutoMoveFocus" Value="{Binding IsChecked, ElementName=_autoMoveFocus}"/>
</Style>
</StackPanel.Resources>
<!-- FEATURES GROUP BOX -->
<GroupBox Header="Features" >
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="0">
<TextBlock Grid.Row="0" Grid.Column="0" Text="AutoSelectBehavior: " VerticalAlignment="Center" />
<ComboBox Grid.Row="0" Grid.Column="1" x:Name="_autoSelectBehavior" SelectedIndex="1" Width="100" VerticalAlignment="Center">
<x:StaticExtension Member="xctk:AutoSelectBehavior.Never" />
<x:StaticExtension Member="xctk:AutoSelectBehavior.OnFocus" />
</ComboBox>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1">
<TextBlock Grid.Row="0" Grid.Column="2" Text="AutoMoveFocus: " VerticalAlignment="Center" />
<CheckBox Grid.Row="0" Grid.Column="3" x:Name="_autoMoveFocus" IsChecked="True" VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</GroupBox>
<StackPanel>
<TextBlock Text="Usage:" Style="{StaticResource Header}"/>
<RichTextBox IsReadOnly="True" BorderThickness="0">
<FlowDocument>
<Paragraph>
<Bold>AutoSelectBehavior:</Bold>
<LineBreak/>
Controled by the "AutoSelectBehavior" property, the content of the AutoSelectTextBox will be selected or not when the control get the focus.
<LineBreak/>
<LineBreak/>
<Bold>AutoMoveFocus:</Bold>
<LineBreak/>
<Italic>Effect with "MaxLength" property:</Italic>
<LineBreak/>
<LineBreak/>
Setting the "MaxLenght" of the text box allow the focus to move from the AutoSelectTextBox once the max lenght has been reached.
In the following "Telephone Number" fields, the "MaxLenght" property of the control has been set to 3, 3 and 4, respectively
</Paragraph>
</FlowDocument>
</RichTextBox>
<!-- PHONE NUMBER FIELDS -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock Text="(" VerticalAlignment="Center"/>
<xctk:AutoSelectTextBox MaxLength="3" Width="30" Text="555"/>
<TextBlock Text=")" VerticalAlignment="Center"/>
<xctk:AutoSelectTextBox MaxLength="3" Width="30" Text="555"/>
<TextBlock Text="-" VerticalAlignment="Center"/>
<xctk:AutoSelectTextBox MaxLength="4" Width="40" Text="5555"/>
</StackPanel>
<RichTextBox IsReadOnly="True" BorderThickness="0">
<FlowDocument>
<Paragraph>
<Italic>Effect with Arrow keys</Italic>
<LineBreak/>
<LineBreak/>
The "AutoMoveFocus" at true also allow to navigate the focus thru the controls using the arrow keys to move the focus up, down, left or right.
You are no longer limited to the "left-right" scenario of the "Tab, Shift-Tab" keys.
</Paragraph>
</FlowDocument>
</RichTextBox>
<!-- TEXTBOX MATRIX -->
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<xctk:AutoSelectTextBox Text="Text1" Width="100" />
<xctk:AutoSelectTextBox Text="Text2" Width="100"/>
<xctk:AutoSelectTextBox Text="Text3" Width="100"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<xctk:AutoSelectTextBox Text="Text4" Width="100"/>
<xctk:AutoSelectTextBox Text="Text5" Width="100"/>
<xctk:AutoSelectTextBox Text="Text6" Width="100"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<xctk:AutoSelectTextBox Text="Text7" Width="100"/>
<xctk:AutoSelectTextBox Text="Text8" Width="100"/>
<xctk:AutoSelectTextBox Text="Text9" Width="100"/>
</StackPanel>
</StackPanel>
</StackPanel>
</StackPanel>
</sample:DemoView>

20
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/DecimalUpDownEditor.cs → ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/AutoSelectTextBoxView.xaml.cs

@ -17,18 +17,20 @@
**********************************************************************/
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
using Microsoft.Practices.Prism.Regions;
using Samples.Infrastructure.Controls;
namespace Samples.Modules.Text.Views
{
public class DecimalUpDownEditor : TypeEditor<DecimalUpDown>
/// <summary>
/// Interaction logic for WatermarkTextBoxView.xaml
/// </summary>
[RegionMemberLifetime( KeepAlive = false )]
public partial class AutoSelectTextBoxView : DemoView
{
protected override void SetControlProperties()
{
Editor.BorderThickness = new System.Windows.Thickness( 0 );
}
protected override void SetValueDependencyProperty()
public AutoSelectTextBoxView()
{
ValueProperty = DecimalUpDown.ValueProperty;
InitializeComponent();
}
}
}

26
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/MaskedTextBoxView.xaml

@ -21,6 +21,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sample="clr-namespace:Samples.Infrastructure.Controls;assembly=Samples.Infrastructure"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:osb="clr-namespace:Xceed.Wpf.Toolkit.Obselete;assembly=WPFToolkit.Extended"
xmlns:s="clr-namespace:System;assembly=mscorlib"
Title="MaskedTextBox"
Description="The MaskedTextBox control lets you display and edit values based on a mask.">
<Grid>
@ -43,10 +45,12 @@
</Grid.ColumnDefinitions>
<TextBlock Text="Include literals:" VerticalAlignment="Center" Margin="2" />
<CheckBox x:Name="_literals" Grid.Column="1" VerticalAlignment="Center" Margin="5" />
<CheckBox x:Name="_literals" Grid.Column="1" VerticalAlignment="Center" Margin="5"
IsChecked="{Binding IncludeLiteralsInValue, ElementName=_maskedTextBox, Mode=TwoWay}"/>
<TextBlock Text="Include prompt:" Grid.Row="1" VerticalAlignment="Center" Margin="2" />
<CheckBox x:Name="_prompt" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5" />
<CheckBox x:Name="_prompt" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5"
IsChecked="{Binding IncludePromptInValue, ElementName=_maskedTextBox, Mode=TwoWay}"/>
</Grid>
<Grid Margin="0,5,0,0">
<Grid.RowDefinitions>
@ -60,23 +64,25 @@
</Grid.ColumnDefinitions>
<TextBlock Text="Mask:" VerticalAlignment="Center" Margin="2" />
<TextBox x:Name="_mask" Grid.Column="1" VerticalAlignment="Center" Margin="5" Text="(000) 000-0000" />
<TextBox x:Name="_mask" Grid.Column="1" VerticalAlignment="Center" Margin="5"
Text="{Binding Mask, ElementName=_maskedTextBox, ValidatesOnExceptions=True}" />
<TextBlock Text="Value:" Grid.Row="1" VerticalAlignment="Center" Margin="2" />
<TextBox x:Name="_value" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5" Text="1234567890" />
<TextBox x:Name="_value" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Margin="5"
Text="{Binding Value, ElementName=_maskedTextBox, ValidatesOnExceptions=True}" />
<TextBlock Text="Text:" Grid.Row="2" VerticalAlignment="Center" Margin="2" />
<TextBox x:Name="_text" Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="5" />
<TextBox x:Name="_text" Grid.Row="2" Grid.Column="1" VerticalAlignment="Center" Margin="5"
Text="{Binding Text, ElementName=_maskedTextBox, ValidatesOnExceptions=True}"/>
</Grid>
</StackPanel>
</GroupBox>
<StackPanel Grid.Row="1" Margin="10">
<xctk:MaskedTextBox IncludeLiterals="{Binding IsChecked, ElementName=_literals, Mode=TwoWay}"
IncludePrompt="{Binding IsChecked, ElementName=_prompt, Mode=TwoWay}"
Mask="{Binding Text, ElementName=_mask}"
Value="{Binding Text, ElementName=_value, Mode=TwoWay}"
Text="{Binding Text, ElementName=_text, Mode=TwoWay}" />
<xctk:MaskedTextBox x:Name="_maskedTextBox"
Mask="(000) 000-0000"
ValueDataType="{x:Type s:String}" />
</StackPanel>
</Grid>
</sample:DemoView>

6
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/MaskedTextBoxView.xaml.cs

@ -31,6 +31,12 @@ namespace Samples.Modules.Text.Views
public MaskedTextBoxView()
{
InitializeComponent();
_mask.TextChanged += new System.Windows.Controls.TextChangedEventHandler( _mask_TextChanged );
}
void _mask_TextChanged( object sender, System.Windows.Controls.TextChangedEventArgs e )
{
_maskedTextBox.Value = null;
}
}
}

3
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/MultiLineTextEditor.xaml

@ -16,6 +16,7 @@
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<sample:DemoView x:Class="Samples.Modules.Text.Views.MultiLineTextEditorView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -23,7 +24,7 @@
xmlns:sample="clr-namespace:Samples.Infrastructure.Controls;assembly=Samples.Infrastructure"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MultiLineTextEditor"
Description="The MultiLineTextEditor is a TextBox that allows you to edit text that is too long to display in a regular TextBox. The popup is resizable to accommodates any text.">
Description="The MultiLineTextEditor is a TextBox that allows you to edit text that is too long to display in a regular TextBox. The popup is resizable to accommodate any text.">
<sample:DemoView.Resources>
<DataTemplate x:Key="multiLineTextEditorStyle" >
<xctk:MultiLineTextEditor TextWrapping="Wrap" Text="{Binding Path=Review}" Content="{Binding Text, RelativeSource={RelativeSource Self}}" Height="24" />

4
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/NavigationView.xaml

@ -20,12 +20,14 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Samples.Modules.Text.Views"
Header="Text" Tag="{x:Type views:HomeView}">
Header="Text" Tag="{x:Type views:HomeView}"
Style="{StaticResource newFeature}" >
<TreeViewItem.Resources>
<Style TargetType="views:NavigationView" BasedOn="{StaticResource {x:Type TreeViewItem}}" />
</TreeViewItem.Resources>
<TreeViewItem Header="AutoSelectTextBox" Tag="{x:Type views:AutoSelectTextBoxView}" Style="{StaticResource newFeature}" />
<TreeViewItem Header="MaskedTextBox" Tag="{x:Type views:MaskedTextBoxView}" />
<TreeViewItem Header="MultiLineTextEditor" Tag="{x:Type views:MultiLineTextEditorView}" />
<TreeViewItem Header="RichTextBox" Tag="{x:Type views:RichTextBoxView}"/>

3
ExtendedWPFToolkitSolution/Src/Samples/Modules/Samples.Modules.Text/Views/RichTextBoxView.xaml

@ -16,6 +16,7 @@
Visit http://xceed.com and follow @datagrid on Twitter.
********************************************************************-->
<sample:DemoView x:Class="Samples.Modules.Text.Views.RichTextBoxView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -24,7 +25,7 @@
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:local="clr-namespace:Samples.Modules.Text.Views"
Title="RichTextBox"
Description="The RichTextBox is a TextBox that allows you to edits formated text based on TextFormatters. The RichTextBoxFormatBar is a contextual formatting toolbar that mimics the behavior of the Microsoft Office 2010 formatting bar on selection.">
Description="The RichTextBox is a TextBox that allows you to edit formatted text based on TextFormatters. The RichTextBoxFormatBar is a contextual formatting toolbar that mimics the behavior of the Microsoft Office 2010 formatting bar on selection.">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />

1
ExtendedWPFToolkitSolution/Src/Samples/Samples/App.config

@ -10,6 +10,7 @@
<module assemblyFile="Samples.Modules.Calculator.dll" moduleType="Samples.Modules.Calculator.CalculatorModule, Samples.Modules.Calculator" moduleName="CalculatorModule" />
<module assemblyFile="Samples.Modules.CheckLists.dll" moduleType="Samples.Modules.CheckLists.CheckListsModule, Samples.Modules.CheckLists" moduleName="CheckListsModule" />
<module assemblyFile="Samples.Modules.ChildWindow.dll" moduleType="Samples.Modules.ChildWindow.ChildWindowModule, Samples.Modules.ChildWindow" moduleName="ChildWindowModule" />
<module assemblyFile="Samples.Modules.DataGrid.dll" moduleType="Samples.Modules.DataGrid.DataGridModule, Samples.Modules.DataGrid" moduleName="DataGridModule" />
<module assemblyFile="Samples.Modules.Color.dll" moduleType="Samples.Modules.Color.ColorModule, Samples.Modules.Color" moduleName="ColorModule" />
<module assemblyFile="Samples.Modules.DateTime.dll" moduleType="Samples.Modules.DateTime.DateTimeModule, Samples.Modules.DateTime" moduleName="DateTimeModule" />
<module assemblyFile="Samples.Modules.Magnifier.dll" moduleType="Samples.Modules.Magnifier.MagnifierModule, Samples.Modules.Magnifier" moduleName="MagnifierModule" />

14
ExtendedWPFToolkitSolution/Src/Samples/Samples/Resources/TreeViewStyles.xaml

@ -246,4 +246,18 @@
<Setter Property="Foreground" Value="{StaticResource ForegroundFill}" />
</Style>
<Style x:Key="newFeature" TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}" >
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
<TextBlock Margin="5,0,0,0" Text="New" FontStyle="Italic" FontSize="8" BaselineOffset="7" Foreground="Red" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

4
ExtendedWPFToolkitSolution/Src/Samples/Samples/Samples.csproj

@ -87,6 +87,10 @@
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\WPFToolkit.Extended\WPFToolkit.Extended.csproj">
<Project>{72E591D6-8F83-4D8C-8F67-9C325E623234}</Project>
<Name>WPFToolkit.Extended</Name>
</ProjectReference>
<ProjectReference Include="..\Samples.Infrastructure\Samples.Infrastructure.csproj">
<Project>{A4A049A4-665A-4651-9046-7D06E9D0CCDC}</Project>
<Name>Samples.Infrastructure</Name>

2
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AssemblyVersionInfo.cs

@ -22,7 +22,7 @@
internal static class _XceedVersionInfo
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "1.7";
public const string BaseVersion = "1.8";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
_XceedVersionInfoCommon.Build;

31
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/AutoSelectBehaviorEnum.cs

@ -0,0 +1,31 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.Toolkit
{
public enum AutoSelectBehavior
{
Never,
OnFocus
}
}

301
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/AutoSelectTextBox.cs

@ -0,0 +1,301 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;
using System.Windows.Automation;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit
{
public class AutoSelectTextBox : TextBox
{
static AutoSelectTextBox()
{
AutomationProperties.AutomationIdProperty.OverrideMetadata( typeof( AutoSelectTextBox ), new UIPropertyMetadata( "AutoSelectTextBox" ) );
}
#region AutoSelectBehavior PROPERTY
public AutoSelectBehavior AutoSelectBehavior
{
get
{
return ( AutoSelectBehavior )GetValue( AutoSelectBehaviorProperty );
}
set
{
SetValue( AutoSelectBehaviorProperty, value );
}
}
public static readonly DependencyProperty AutoSelectBehaviorProperty =
DependencyProperty.Register( "AutoSelectBehavior", typeof( AutoSelectBehavior ), typeof( AutoSelectTextBox ),
new UIPropertyMetadata( AutoSelectBehavior.Never ) );
#endregion AutoSelectBehavior PROPERTY
#region AutoMoveFocus PROPERTY
public bool AutoMoveFocus
{
get
{
return ( bool )GetValue( AutoMoveFocusProperty );
}
set
{
SetValue( AutoMoveFocusProperty, value );
}
}
public static readonly DependencyProperty AutoMoveFocusProperty =
DependencyProperty.Register( "AutoMoveFocus", typeof( bool ), typeof( AutoSelectTextBox ), new UIPropertyMetadata( false ) );
#endregion AutoMoveFocus PROPERTY
#region QueryMoveFocus EVENT
public static readonly RoutedEvent QueryMoveFocusEvent = EventManager.RegisterRoutedEvent( "QueryMoveFocus",
RoutingStrategy.Bubble,
typeof( QueryMoveFocusEventHandler ),
typeof( AutoSelectTextBox ) );
#endregion QueryMoveFocus EVENT
protected override void OnPreviewKeyDown( KeyEventArgs e )
{
if( !this.AutoMoveFocus )
{
base.OnPreviewKeyDown( e );
return;
}
if( ( e.Key == Key.Left )
&& ( ( Keyboard.Modifiers == ModifierKeys.None )
|| ( Keyboard.Modifiers == ModifierKeys.Control ) ) )
{
e.Handled = this.MoveFocusLeft();
}
if( ( e.Key == Key.Right )
&& ( ( Keyboard.Modifiers == ModifierKeys.None )
|| ( Keyboard.Modifiers == ModifierKeys.Control ) ) )
{
e.Handled = this.MoveFocusRight();
}
if( ( ( e.Key == Key.Up ) || ( e.Key == Key.PageUp ) )
&& ( ( Keyboard.Modifiers == ModifierKeys.None )
|| ( Keyboard.Modifiers == ModifierKeys.Control ) ) )
{
e.Handled = this.MoveFocusUp();
}
if( ( ( e.Key == Key.Down ) || ( e.Key == Key.PageDown ) )
&& ( ( Keyboard.Modifiers == ModifierKeys.None )
|| ( Keyboard.Modifiers == ModifierKeys.Control ) ) )
{
e.Handled = this.MoveFocusDown();
}
base.OnPreviewKeyDown( e );
}
protected override void OnPreviewGotKeyboardFocus( KeyboardFocusChangedEventArgs e )
{
base.OnPreviewGotKeyboardFocus( e );
if( this.AutoSelectBehavior == AutoSelectBehavior.OnFocus )
{
// If the focus was not in one of our child ( or popup ), we select all the text.
if( !TreeHelper.IsDescendantOf( e.OldFocus as DependencyObject, this ) )
this.SelectAll();
}
}
protected override void OnPreviewMouseLeftButtonDown( MouseButtonEventArgs e )
{
base.OnPreviewMouseLeftButtonDown( e );
if( this.AutoSelectBehavior == AutoSelectBehavior.Never )
return;
if( this.IsKeyboardFocusWithin == false )
{
this.Focus();
e.Handled = true;
}
}
protected override void OnTextChanged( TextChangedEventArgs e )
{
base.OnTextChanged( e );
if( !this.AutoMoveFocus )
return;
if( ( this.Text.Length != 0 )
&& ( this.Text.Length == this.MaxLength )
&& ( this.CaretIndex == this.MaxLength ) )
{
if( this.CanMoveFocus( FocusNavigationDirection.Right, true ) == true )
{
FocusNavigationDirection direction = ( this.FlowDirection == FlowDirection.LeftToRight )
? FocusNavigationDirection.Right
: FocusNavigationDirection.Left;
this.MoveFocus( new TraversalRequest( direction ) );
}
}
}
private bool CanMoveFocus( FocusNavigationDirection direction, bool reachedMax )
{
QueryMoveFocusEventArgs e = new QueryMoveFocusEventArgs( direction, reachedMax );
this.RaiseEvent( e );
return e.CanMoveFocus;
}
private bool MoveFocusLeft()
{
if( this.FlowDirection == FlowDirection.LeftToRight )
{
//occurs only if the cursor is at the beginning of the text
if( ( this.CaretIndex == 0 ) && ( this.SelectionLength == 0 ) )
{
if( ComponentCommands.MoveFocusBack.CanExecute( null, this ) )
{
ComponentCommands.MoveFocusBack.Execute( null, this );
return true;
}
else if( this.CanMoveFocus( FocusNavigationDirection.Left, false ) )
{
this.MoveFocus( new TraversalRequest( FocusNavigationDirection.Left ) );
return true;
}
}
}
else
{
//occurs only if the cursor is at the end of the text
if( ( this.CaretIndex == this.Text.Length ) && ( this.SelectionLength == 0 ) )
{
if( ComponentCommands.MoveFocusBack.CanExecute( null, this ) )
{
ComponentCommands.MoveFocusBack.Execute( null, this );
return true;
}
else if( this.CanMoveFocus( FocusNavigationDirection.Left, false ) )
{
this.MoveFocus( new TraversalRequest( FocusNavigationDirection.Left ) );
return true;
}
}
}
return false;
}
private bool MoveFocusRight()
{
if( this.FlowDirection == FlowDirection.LeftToRight )
{
//occurs only if the cursor is at the beginning of the text
if( ( this.CaretIndex == this.Text.Length ) && ( this.SelectionLength == 0 ) )
{
if( ComponentCommands.MoveFocusForward.CanExecute( null, this ) )
{
ComponentCommands.MoveFocusForward.Execute( null, this );
return true;
}
else if( this.CanMoveFocus( FocusNavigationDirection.Right, false ) )
{
this.MoveFocus( new TraversalRequest( FocusNavigationDirection.Right ) );
return true;
}
}
}
else
{
//occurs only if the cursor is at the end of the text
if( ( this.CaretIndex == 0 ) && ( this.SelectionLength == 0 ) )
{
if( ComponentCommands.MoveFocusForward.CanExecute( null, this ) )
{
ComponentCommands.MoveFocusForward.Execute( null, this );
return true;
}
else if( this.CanMoveFocus( FocusNavigationDirection.Right, false ) )
{
this.MoveFocus( new TraversalRequest( FocusNavigationDirection.Right ) );
return true;
}
}
}
return false;
}
private bool MoveFocusUp()
{
int lineNumber = this.GetLineIndexFromCharacterIndex( this.SelectionStart );
//occurs only if the cursor is on the first line
if( lineNumber == 0 )
{
if( ComponentCommands.MoveFocusUp.CanExecute( null, this ) )
{
ComponentCommands.MoveFocusUp.Execute( null, this );
return true;
}
else if( this.CanMoveFocus( FocusNavigationDirection.Up, false ) )
{
this.MoveFocus( new TraversalRequest( FocusNavigationDirection.Up ) );
return true;
}
}
return false;
}
private bool MoveFocusDown()
{
int lineNumber = this.GetLineIndexFromCharacterIndex( this.SelectionStart );
//occurs only if the cursor is on the first line
if( lineNumber == ( this.LineCount - 1 ) )
{
if( ComponentCommands.MoveFocusDown.CanExecute( null, this ) )
{
ComponentCommands.MoveFocusDown.Execute( null, this );
return true;
}
else if( this.CanMoveFocus( FocusNavigationDirection.Down, false ) )
{
this.MoveFocus( new TraversalRequest( FocusNavigationDirection.Down ) );
return true;
}
}
return false;
}
}
}

76
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/QueryMoveFocusEventArgs.cs

@ -0,0 +1,76 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System.Windows;
using System.Windows.Input;
namespace Xceed.Wpf.Toolkit
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Design", "CA1003:UseGenericEventHandlerInstances" )]
public delegate void QueryMoveFocusEventHandler( object sender, QueryMoveFocusEventArgs e );
public class QueryMoveFocusEventArgs : RoutedEventArgs
{
//default CTOR private to prevent its usage.
private QueryMoveFocusEventArgs()
{
}
//internal to prevent anybody from building this type of event.
internal QueryMoveFocusEventArgs( FocusNavigationDirection direction, bool reachedMaxLength )
: base( AutoSelectTextBox.QueryMoveFocusEvent )
{
m_navigationDirection = direction;
m_reachedMaxLength = reachedMaxLength;
}
public FocusNavigationDirection FocusNavigationDirection
{
get
{
return m_navigationDirection;
}
}
public bool ReachedMaxLength
{
get
{
return m_reachedMaxLength;
}
}
public bool CanMoveFocus
{
get
{
return m_canMove;
}
set
{
m_canMove = value;
}
}
private FocusNavigationDirection m_navigationDirection;
private bool m_reachedMaxLength;
private bool m_canMove = true; //defaults to true... if nobody does nothing, then its capable of moving focus.
}
}

22
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs

@ -22,11 +22,14 @@ using System.Linq;
using System.Windows;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Primitives;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit
{
public class CheckComboBox : Selector
{
private ValueChangeHelper _displayMemberPathValuesChangeHelper;
#region Constructors
static CheckComboBox()
@ -37,6 +40,7 @@ namespace Xceed.Wpf.Toolkit
public CheckComboBox()
{
Mouse.AddPreviewMouseDownOutsideCapturedElementHandler( this, OnMouseDownOutsideCapturedElement );
_displayMemberPathValuesChangeHelper = new ValueChangeHelper( this.OnDisplayMemberPathValuesChanged );
}
#endregion //Constructors
@ -98,7 +102,13 @@ namespace Xceed.Wpf.Toolkit
protected override void OnDisplayMemberPathChanged( string oldDisplayMemberPath, string newDisplayMemberPath )
{
base.OnDisplayMemberPathChanged( oldDisplayMemberPath, newDisplayMemberPath );
UpdateText();
this.UpdateDisplayMemberPathValuesBindings();
}
protected override void OnItemsSourceChanged( System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue )
{
base.OnItemsSourceChanged( oldValue, newValue );
this.UpdateDisplayMemberPathValuesBindings();
}
#endregion //Base Class Overrides
@ -114,6 +124,16 @@ namespace Xceed.Wpf.Toolkit
#region Methods
private void UpdateDisplayMemberPathValuesBindings()
{
_displayMemberPathValuesChangeHelper.UpdateValueSource( ItemsCollection, this.DisplayMemberPath );
}
private void OnDisplayMemberPathValuesChanged()
{
this.UpdateText();
}
private void UpdateText()
{
#if VS2008

73
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs

@ -25,17 +25,20 @@ using System.Windows.Media;
using Xceed.Wpf.Toolkit.Core.Utilities;
using Xceed.Wpf.Toolkit.Primitives;
using System.IO;
using System;
namespace Xceed.Wpf.Toolkit
{
[TemplatePart( Name = PART_ColorShadingCanvas, Type = typeof( Canvas ) )]
[TemplatePart( Name = PART_ColorShadeSelector, Type = typeof( Canvas ) )]
[TemplatePart( Name = PART_SpectrumSlider, Type = typeof( ColorSpectrumSlider ) )]
[TemplatePart( Name = PART_HexadecimalTextBox, Type = typeof( TextBox ) )]
public class ColorCanvas : Control
{
private const string PART_ColorShadingCanvas = "PART_ColorShadingCanvas";
private const string PART_ColorShadeSelector = "PART_ColorShadeSelector";
private const string PART_SpectrumSlider = "PART_SpectrumSlider";
private const string PART_HexadecimalTextBox = "PART_HexadecimalTextBox";
#region Private Members
@ -43,6 +46,7 @@ namespace Xceed.Wpf.Toolkit
private Canvas _colorShadingCanvas;
private Canvas _colorShadeSelector;
private ColorSpectrumSlider _spectrumSlider;
private TextBox _hexadecimalTextBox;
private Point? _currentColorPosition;
private bool _surpressPropertyChanged;
@ -74,7 +78,7 @@ namespace Xceed.Wpf.Toolkit
protected virtual void OnSelectedColorChanged( Color oldValue, Color newValue )
{
HexadecimalString = GetFormatedColorString( newValue );
SetHexadecimalStringProperty( GetFormatedColorString( newValue ), false );
UpdateRGBValues( newValue );
UpdateColorShadeSelectorPosition( newValue );
@ -237,6 +241,8 @@ namespace Xceed.Wpf.Toolkit
string currentColorString = GetFormatedColorString( SelectedColor );
if( !currentColorString.Equals( newColorString ) )
UpdateSelectedColor( ( Color )ColorConverter.ConvertFromString( newColorString ) );
SetHexadecimalTextBoxTextProperty( newValue );
}
private static object OnCoerceHexadecimalString( DependencyObject d, object basevalue )
@ -251,16 +257,19 @@ namespace Xceed.Wpf.Toolkit
private object OnCoerceHexadecimalString( object newValue )
{
var value = newValue as string;
string retValue = value;
try
{
ColorConverter.ConvertFromString( value );
}
catch
{
//When HexadecimalString is changed via Code-Behind and hexadecimal format is bad, throw.
throw new InvalidDataException( "Color provided is not in the correct format." );
}
return value;
return retValue;
}
#endregion //HexadecimalString
@ -289,7 +298,7 @@ namespace Xceed.Wpf.Toolkit
protected virtual void OnUsingAlphaChannelChanged()
{
HexadecimalString = GetFormatedColorString( SelectedColor );
SetHexadecimalStringProperty( GetFormatedColorString( SelectedColor ), false );
}
#endregion //UsingAlphaChannel
@ -342,17 +351,31 @@ namespace Xceed.Wpf.Toolkit
if( _spectrumSlider != null )
_spectrumSlider.ValueChanged += SpectrumSlider_ValueChanged;
if( _hexadecimalTextBox != null )
_hexadecimalTextBox.LostFocus -= new RoutedEventHandler( HexadecimalTextBox_LostFocus );
_hexadecimalTextBox = GetTemplateChild( PART_HexadecimalTextBox ) as TextBox;
if( _hexadecimalTextBox != null )
_hexadecimalTextBox.LostFocus += new RoutedEventHandler( HexadecimalTextBox_LostFocus );
UpdateRGBValues( SelectedColor );
UpdateColorShadeSelectorPosition( SelectedColor );
// When changing theme, HexadecimalString needs to be set since it is not binded.
SetHexadecimalTextBoxTextProperty( GetFormatedColorString( SelectedColor ) );
}
protected override void OnPreviewKeyDown( KeyEventArgs e )
protected override void OnKeyDown( KeyEventArgs e )
{
//hitting enter on textbox will update value of underlying source
base.OnKeyDown( e );
//hitting enter on textbox will update Hexadecimal string
if( e.Key == Key.Enter && e.OriginalSource is TextBox )
{
BindingExpression be = ( ( TextBox )e.OriginalSource ).GetBindingExpression( TextBox.TextProperty );
be.UpdateSource();
TextBox textBox = ( TextBox )e.OriginalSource;
if( textBox.Name == PART_HexadecimalTextBox )
SetHexadecimalStringProperty( textBox.Text, true );
}
}
@ -404,6 +427,12 @@ namespace Xceed.Wpf.Toolkit
}
}
void HexadecimalTextBox_LostFocus( object sender, RoutedEventArgs e )
{
TextBox textbox = sender as TextBox;
SetHexadecimalStringProperty( textbox.Text, true );
}
#endregion //Event Handlers
#region Events
@ -503,7 +532,7 @@ namespace Xceed.Wpf.Toolkit
var currentColor = ColorUtilities.ConvertHsvToRgb( hsv.H, hsv.S, hsv.V );
currentColor.A = A;
SelectedColor = currentColor;
HexadecimalString = GetFormatedColorString( SelectedColor );
SetHexadecimalStringProperty( GetFormatedColorString( SelectedColor ), false );
}
private string GetFormatedColorString( Color colorToFormat )
@ -516,6 +545,34 @@ namespace Xceed.Wpf.Toolkit
return ColorUtilities.FormatColorString( stringToFormat, UsingAlphaChannel );
}
private void SetHexadecimalStringProperty( string newValue, bool modifyFromUI )
{
if( modifyFromUI )
{
try
{
ColorConverter.ConvertFromString( newValue );
HexadecimalString = newValue;
}
catch
{
//When HexadecimalString is changed via UI and hexadecimal format is bad, keep the previous HexadecimalString.
SetHexadecimalTextBoxTextProperty( HexadecimalString );
}
}
else
{
//When HexadecimalString is changed via Code-Behind, hexadecimal format will be evaluated in OnCoerceHexadecimalString()
HexadecimalString = newValue;
}
}
private void SetHexadecimalTextBoxTextProperty( string newValue )
{
if( _hexadecimalTextBox != null )
_hexadecimalTextBox.Text = newValue;
}
#endregion //Methods
}
}

2
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorCanvas/Themes/Generic.xaml

@ -260,7 +260,7 @@
<Border Background="{StaticResource CheckerBrush}" Height="22" Margin="2,0,2,0" BorderThickness="1" BorderBrush="#FFC9CACA">
<Rectangle x:Name="SelectedColor" Fill="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorToSolidColorBrushConverter}}" />
</Border>
<TextBox Grid.Column="1" Text="{Binding HexadecimalString, RelativeSource={RelativeSource TemplatedParent}}" Margin="2,0,2,0" VerticalAlignment="Center" Style="{StaticResource ColorCanvasTextBoxStyle}" />
<TextBox x:Name="PART_HexadecimalTextBox" Grid.Column="1" Margin="2,0,2,0" VerticalAlignment="Center" Style="{StaticResource ColorCanvasTextBoxStyle}" />
</Grid>
</Border>

2
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs

@ -343,7 +343,7 @@ namespace Xceed.Wpf.Toolkit
{
return ( bool )GetValue( UsingAlphaChannelProperty );
}
protected set
set
{
SetValue( UsingAlphaChannelProperty, value );
}

4
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Converters/WizardPageButtonVisibilityConverter.cs

@ -28,7 +28,9 @@ namespace Xceed.Wpf.Toolkit.Core.Converters
public object Convert( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
Visibility wizardVisibility = ( Visibility )values[ 0 ];
WizardPageButtonVisibility wizardPageVisibility = ( WizardPageButtonVisibility )values[ 1 ];
WizardPageButtonVisibility wizardPageVisibility = ( (values[ 1 ] == null) || (values[ 1 ] == DependencyProperty.UnsetValue) )
? WizardPageButtonVisibility.Hidden
: ( WizardPageButtonVisibility )values[ 1 ];
Visibility visibility = Visibility.Visible;

32
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Input/IValidateInput.cs

@ -0,0 +1,32 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.Toolkit.Core.Input
{
public interface IValidateInput
{
event InputValidationErrorEventHandler InputValidationError;
void CommitInput();
}
}

46
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Input/InputValidationErrorEventArgs.cs

@ -0,0 +1,46 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Xceed.Wpf.Toolkit.Core.Input
{
public delegate void InputValidationErrorEventHandler( object sender, InputValidationErrorEventArgs e );
public class InputValidationErrorEventArgs : EventArgs
{
public InputValidationErrorEventArgs( string errorMsg )
{
_errorMessage = errorMsg;
}
public string ErrorMessage
{
get
{
return _errorMessage;
}
}
private string _errorMessage;
}
}

57
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/CachedTextInfo.cs

@ -0,0 +1,57 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
namespace Xceed.Wpf.Toolkit.Primitives
{
internal class CachedTextInfo : ICloneable
{
private CachedTextInfo( string text, int caretIndex, int selectionStart, int selectionLength )
{
this.Text = text;
this.CaretIndex = caretIndex;
this.SelectionStart = selectionStart;
this.SelectionLength = selectionLength;
}
public CachedTextInfo( TextBox textBox )
: this( textBox.Text, textBox.CaretIndex, textBox.SelectionStart, textBox.SelectionLength )
{
}
public string Text { get; private set; }
public int CaretIndex { get; private set; }
public int SelectionStart { get; private set; }
public int SelectionLength { get; private set; }
#region ICloneable Members
public object Clone()
{
return new CachedTextInfo( this.Text, this.CaretIndex, this.SelectionStart, this.SelectionLength );
}
#endregion
}
}

557
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs

@ -26,16 +26,28 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.Primitives
{
public class Selector : ItemsControl //should probably make this control an ICommandSource
public class Selector : ItemsControl, IWeakEventListener //should probably make this control an ICommandSource
{
#region Members
private bool _ignoreSetSelectedValue;
private bool _surpressSelectionChanged;
private bool _surpressSelectedValueChanged;
private bool _surpressItemSelectionChanged;
private bool _ignoreSelectedItemChanged;
private bool _ignoreSelectedValueChanged;
private int _ignoreSelectedItemsCollectionChanged;
private int _ignoreSelectedMemberPathValuesChanged;
private IList _selectedItems;
private ValueChangeHelper _selectedMemberPathValuesHelper;
private ValueChangeHelper _valueMemberPathValuesHelper;
#endregion //Members
@ -43,9 +55,11 @@ namespace Xceed.Wpf.Toolkit.Primitives
public Selector()
{
SelectedItems = new ObservableCollection<object>();
AddHandler( Selector.SelectedEvent, new RoutedEventHandler( Selector_ItemSelected ) );
AddHandler( Selector.UnSelectedEvent, new RoutedEventHandler( Selector_ItemUnselected ) );
this.SelectedItems = new ObservableCollection<object>();
AddHandler( Selector.SelectedEvent, new RoutedEventHandler( ( s, args ) => this.OnItemSelectionChangedCore( args, false ) ) );
AddHandler( Selector.UnSelectedEvent, new RoutedEventHandler( ( s, args ) => this.OnItemSelectionChangedCore( args, true ) ) );
_selectedMemberPathValuesHelper = new ValueChangeHelper( this.OnSelectedMemberPathValuesChanged );
_valueMemberPathValuesHelper = new ValueChangeHelper( this.OnValueMemberPathValuesChanged );
}
#endregion //Constructors
@ -88,7 +102,9 @@ namespace Xceed.Wpf.Toolkit.Primitives
#endregion
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( "SelectedItem", typeof( object ), typeof( Selector ), new UIPropertyMetadata( null ) );
#region SelectedItem property
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( "SelectedItem", typeof( object ), typeof( Selector ), new UIPropertyMetadata( null, OnSelectedItemChanged ) );
public object SelectedItem
{
get
@ -101,22 +117,91 @@ namespace Xceed.Wpf.Toolkit.Primitives
}
}
//Since you cannot data bind to ReadOnly DependencyProperty, I am leaving this a public get/set DP. This will allow you to data bind to the SelectedItems from a ViewModel, but it is
//intended to be ReadOnly. So you MUST set the binding Mode=OneWayToSource. Otherwise it will not behave as expected.
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register( "SelectedItems", typeof( IList ), typeof( Selector ), new UIPropertyMetadata( null ) );
private static void OnSelectedItemChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args )
{
( ( Selector )sender ).OnSelectedItemChanged( args.OldValue, args.NewValue );
}
private void OnSelectedItemChanged( object oldValue, object newValue )
{
if( _ignoreSelectedItemChanged )
return;
_ignoreSelectedItemsCollectionChanged++;
SelectedItems.Clear();
if( newValue != null )
{
SelectedItems.Add( newValue );
}
this.UpdateFromSelectedItems();
_ignoreSelectedItemsCollectionChanged--;
}
#endregion
#region SelectedItems Property
public IList SelectedItems
{
get
{
return ( IList )GetValue( SelectedItemsProperty );
return _selectedItems;
}
private set
{
if( value == null )
throw new ArgumentNullException( "value" );
INotifyCollectionChanged oldCollection = _selectedItems as INotifyCollectionChanged;
INotifyCollectionChanged newCollection = value as INotifyCollectionChanged;
if( oldCollection != null )
{
CollectionChangedEventManager.RemoveListener( oldCollection, this );
}
if( newCollection != null )
{
CollectionChangedEventManager.AddListener( newCollection, this );
}
_selectedItems = value;
this.UpdateFromSelectedItems();
}
}
#endregion SelectedItems
#region SelectedItemsOverride property
public static readonly DependencyProperty SelectedItemsOverrideProperty = DependencyProperty.Register( "SelectedItemsOverride", typeof( IList ), typeof( Selector ), new UIPropertyMetadata( null, SelectedItemsOverrideChanged ) );
public IList SelectedItemsOverride
{
get
{
return ( IList )GetValue( SelectedItemsOverrideProperty );
}
set
{
SetValue( SelectedItemsProperty, value );
SetValue( SelectedItemsOverrideProperty, value );
}
}
public static readonly DependencyProperty SelectedMemberPathProperty = DependencyProperty.Register( "SelectedMemberPath", typeof( string ), typeof( Selector ), new UIPropertyMetadata( null ) );
private static void SelectedItemsOverrideChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args )
{
( ( Selector )sender ).OnSelectedItemsOverrideChanged( ( IList )args.OldValue, ( IList )args.NewValue );
}
private void OnSelectedItemsOverrideChanged( IList oldValue, IList newValue )
{
this.SelectedItems = ( newValue != null ) ? newValue : new ObservableCollection<object>();
}
#endregion
public static readonly DependencyProperty SelectedMemberPathProperty = DependencyProperty.Register( "SelectedMemberPath", typeof( string ), typeof( Selector ), new UIPropertyMetadata( null, OnSelectedMemberPathChanged ) );
public string SelectedMemberPath
{
get
@ -129,6 +214,11 @@ namespace Xceed.Wpf.Toolkit.Primitives
}
}
private static void OnSelectedMemberPathChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
( ( Selector )o ).UpdateSelectedMemberPathValuesBindings();
}
#region SelectedValue
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register( "SelectedValue", typeof( string ), typeof( Selector ), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedValueChanged ) );
@ -153,10 +243,10 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected virtual void OnSelectedValueChanged( string oldValue, string newValue )
{
if( _surpressSelectedValueChanged )
if( _ignoreSelectedValueChanged )
return;
UpdateSelectedItemsFromSelectedValue();
UpdateFromSelectedValue();
}
#endregion //SelectedValue
@ -178,7 +268,20 @@ namespace Xceed.Wpf.Toolkit.Primitives
private static void OnValueMemberPathChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
( ( Selector )o ).UpdateSelectedValue();
( ( Selector )o ).UpdateValueMemberPathValuesBindings();
}
#endregion
#region ItemsCollection Property
protected IEnumerable ItemsCollection
{
get
{
return ItemsSource ?? ( ( IEnumerable )Items ?? ( IEnumerable )new object[ 0 ] );
}
}
#endregion
@ -199,79 +302,65 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected override void PrepareContainerForItemOverride( DependencyObject element, object item )
{
_surpressSelectionChanged = true;
base.PrepareContainerForItemOverride( element, item );
_surpressItemSelectionChanged = true;
var selectorItem = element as FrameworkElement;
//first try resolving SelectorItem.IsSelected by data binding to the SelectedMemeberPath property
if( !String.IsNullOrEmpty( SelectedMemberPath ) )
selectorItem.SetValue( SelectorItem.IsSelectedProperty, SelectedItems.Contains(item) );
_surpressItemSelectionChanged = false;
}
protected override void OnItemsSourceChanged( IEnumerable oldValue, IEnumerable newValue )
{
base.OnItemsSourceChanged( oldValue, newValue );
var oldCollection = oldValue as INotifyCollectionChanged;
var newCollection = newValue as INotifyCollectionChanged;
if( oldCollection != null )
{
Binding selectedBinding = new Binding( SelectedMemberPath )
{
Mode = BindingMode.TwoWay,
Source = item
};
selectorItem.SetBinding( SelectorItem.IsSelectedProperty, selectedBinding );
CollectionChangedEventManager.RemoveListener( oldCollection, this );
}
//now let's search the SelectedItems for the current item. If it's there then mark it as selected
if( SelectedItems != null )
if( newCollection != null )
{
foreach( object selectedItem in SelectedItems )
{
//a match was found so select it and get the hell out of here
if( item.Equals( selectedItem ) )
{
selectorItem.SetValue( SelectorItem.IsSelectedProperty, true );
break;
}
}
CollectionChangedEventManager.AddListener( newCollection, this );
}
base.PrepareContainerForItemOverride( element, item );
_surpressSelectionChanged = false;
this.RemoveUnavailableSelectedItems();
this.UpdateSelectedMemberPathValuesBindings();
this.UpdateValueMemberPathValuesBindings();
}
#endregion //Base Class Overrides
#region Events
public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent( "SelectedEvent", RoutingStrategy.Bubble, typeof( SelectedItemChangedEventHandler ), typeof( Selector ) );
public static readonly RoutedEvent UnSelectedEvent = EventManager.RegisterRoutedEvent( "UnSelectedEvent", RoutingStrategy.Bubble, typeof( SelectedItemChangedEventHandler ), typeof( Selector ) );
public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent( "SelectedEvent", RoutingStrategy.Bubble, typeof( RoutedEventHandler ), typeof( Selector ) );
public static readonly RoutedEvent UnSelectedEvent = EventManager.RegisterRoutedEvent( "UnSelectedEvent", RoutingStrategy.Bubble, typeof( RoutedEventHandler ), typeof( Selector ) );
public static readonly RoutedEvent SelectedItemChangedEvent = EventManager.RegisterRoutedEvent( "SelectedItemChanged", RoutingStrategy.Bubble, typeof( SelectedItemChangedEventHandler ), typeof( Selector ) );
public event SelectedItemChangedEventHandler SelectedItemChanged
public static readonly RoutedEvent ItemSelectionChangedEvent = EventManager.RegisterRoutedEvent( "ItemSelectionChanged", RoutingStrategy.Bubble, typeof( ItemSelectionChangedEventHandler ), typeof( Selector ) );
public event ItemSelectionChangedEventHandler ItemSelectionChanged
{
add
{
AddHandler( SelectedItemChangedEvent, value );
AddHandler( ItemSelectionChangedEvent, value );
}
remove
{
RemoveHandler( SelectedItemChangedEvent, value );
RemoveHandler( ItemSelectionChangedEvent, value );
}
}
#endregion //Events
#region Event Handlers
protected virtual void Selector_ItemSelected( object sender, RoutedEventArgs e )
{
OnItemSelected( e.OriginalSource, false );
}
protected virtual void Selector_ItemUnselected( object sender, RoutedEventArgs e )
{
OnItemSelected( e.OriginalSource, true );
}
#endregion //Event Handlers
#region Methods
protected object GetItemValue( object item )
{
if( !String.IsNullOrEmpty( ValueMemberPath ) && (item != null))
if( !String.IsNullOrEmpty( ValueMemberPath ) && ( item != null ) )
{
var property = item.GetType().GetProperty( ValueMemberPath );
if( property != null )
@ -281,49 +370,86 @@ namespace Xceed.Wpf.Toolkit.Primitives
return item;
}
protected string GetDelimitedValue( object value )
protected object ResolveItemByValue( string value )
{
return String.Format( "{0}{1}", value, Delimiter );
if( !String.IsNullOrEmpty( ValueMemberPath ) )
{
foreach( object item in ItemsCollection )
{
var property = item.GetType().GetProperty( ValueMemberPath );
if( property != null )
{
var propertyValue = property.GetValue( item, null );
if( value.Equals( propertyValue.ToString(), StringComparison.InvariantCultureIgnoreCase ) )
return item;
}
}
}
return value;
}
protected virtual void OnItemSelected( object itemContainer, bool remove )
private bool? GetSelectedMemberPathValue( object item )
{
object item = this.ItemContainerGenerator.ItemFromContainer( ( DependencyObject )itemContainer );
Update( item, remove );
RaiseSelectedItemChangedEvent( item, !remove ); //inverse the remove paramter to correctly reflect the IsSelected state
PropertyInfo prop = this.GetSelectedMemberPathProperty(item);
return ( prop != null )
? ( bool )prop.GetValue( item, null )
: ( bool? )null;
}
protected virtual void RaiseSelectedItemChangedEvent( object item, bool isSelected )
private void SetSelectedMemberPathValue( object item, bool value )
{
if( _surpressSelectionChanged )
return;
RaiseEvent( new SelectedItemChangedEventArgs( Selector.SelectedItemChangedEvent, this, item, isSelected ) );
PropertyInfo prop = this.GetSelectedMemberPathProperty(item);
if( Command != null )
Command.Execute( item );
if( prop != null )
{
prop.SetValue( item, value, null );
}
}
protected virtual void Update( object item, bool remove )
private PropertyInfo GetSelectedMemberPathProperty(object item)
{
UpdateSelectedItem( item );
UpdateSelectedItems( item, remove );
UpdateSelectedValue();
PropertyInfo propertyInfo = null;
if( !String.IsNullOrEmpty( SelectedMemberPath ) && ( item != null ) )
{
var property = item.GetType().GetProperty( SelectedMemberPath );
if( property != null && property.PropertyType == typeof( bool ) )
{
propertyInfo = property;
}
}
return propertyInfo;
}
private void UpdateSelectedItem( object item )
/// <summary>
/// When SelectedItems collection implements INotifyPropertyChanged, this is the callback.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSelectedItemsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
SelectedItem = item;
if( _ignoreSelectedItemsCollectionChanged > 0 )
return;
// Keep it simple for now. Just update all
this.UpdateFromSelectedItems();
}
private void UpdateSelectedItems( object item, bool remove )
private void OnItemSelectionChangedCore( RoutedEventArgs args, bool unselected )
{
if( SelectedItems == null )
SelectedItems = new ObservableCollection<object>();
object item = this.ItemContainerGenerator.ItemFromContainer( ( DependencyObject )args.OriginalSource );
if( remove )
// When the item is it's own container, "UnsetValue" will be returned.
if( item == DependencyProperty.UnsetValue )
{
if( SelectedItems.Contains( item ) )
item = args.OriginalSource;
}
if( unselected )
{
while( SelectedItems.Contains( item ) )
SelectedItems.Remove( item );
}
else
@ -331,116 +457,263 @@ namespace Xceed.Wpf.Toolkit.Primitives
if( !SelectedItems.Contains( item ) )
SelectedItems.Add( item );
}
OnItemSelectionChanged(
new ItemSelectionChangedEventArgs( Selector.ItemSelectionChangedEvent, this, item, !unselected ) );
}
private void UpdateSelectedValue()
/// <summary>
/// When the ItemsSource implements INotifyPropertyChanged, this is the change callback.
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void OnItemsSourceCollectionChanged( object sender, NotifyCollectionChangedEventArgs args )
{
//get out of here if we don't want to set the SelectedValue
if( _ignoreSetSelectedValue )
this.RemoveUnavailableSelectedItems();
this.UpdateSelectedMemberPathValuesBindings();
this.UpdateValueMemberPathValuesBindings();
}
/// <summary>
/// This is called when any value of any item referenced by SelectedMemberPath
/// is modified. This may affect the SelectedItems collection.
/// </summary>
private void OnSelectedMemberPathValuesChanged()
{
if( _ignoreSelectedMemberPathValuesChanged > 0 )
return;
_surpressSelectedValueChanged = true;
this.UpdateFromSelectedMemberPathValues();
}
/// <summary>
/// This is called when any value of any item referenced by ValueMemberPath
/// is modified. This will affect the SelectedValue property
/// </summary>
private void OnValueMemberPathValuesChanged()
{
this.UpdateSelectedValue();
}
private void UpdateSelectedMemberPathValuesBindings()
{
_selectedMemberPathValuesHelper.UpdateValueSource( ItemsCollection, SelectedMemberPath );
}
private void UpdateValueMemberPathValuesBindings()
{
_valueMemberPathValuesHelper.UpdateValueSource( ItemsCollection, ValueMemberPath );
}
/// <summary>
/// This method will be called when the "IsSelected" property of an SelectorItem
/// has been modified.
/// </summary>
/// <param name="args"></param>
protected virtual void OnItemSelectionChanged( ItemSelectionChangedEventArgs args )
{
if( _surpressItemSelectionChanged )
return;
RaiseEvent( args );
if( Command != null )
Command.Execute( args.Item );
}
/// <summary>
/// Updates the SelectedValue property based on what is present in the SelectedItems property.
/// </summary>
private void UpdateSelectedValue()
{
#if VS2008
string newValue = String.Join( Delimiter, SelectedItems.Cast<object>().Select( x => GetItemValue( x ).ToString() ).ToArray() );
#else
string newValue = String.Join( Delimiter, SelectedItems.Cast<object>().Select( x => GetItemValue( x ) ) );
#endif
if( String.IsNullOrEmpty( SelectedValue ) || !SelectedValue.Equals( newValue ) )
{
_ignoreSelectedValueChanged = true;
SelectedValue = newValue;
_surpressSelectedValueChanged = false;
_ignoreSelectedValueChanged = false;
}
}
private void UpdateSelectedItemsFromSelectedValue()
/// <summary>
/// Updates the SelectedItem property based on what is present in the SelectedItems property.
/// </summary>
private void UpdateSelectedItem()
{
_surpressSelectionChanged = true;
//first we have to unselect everything
ClearSelectedItems();
if( !SelectedItems.Contains( SelectedItem ) )
{
_ignoreSelectedItemChanged = true;
SelectedItem = ( SelectedItems.Count > 0 ) ? SelectedItems[ 0 ] : null;
_ignoreSelectedItemChanged = false;
}
}
if( !String.IsNullOrEmpty( SelectedValue ) )
/// <summary>
/// Update the SelectedItems collection based on the values
/// refered to by the SelectedMemberPath property.
/// </summary>
private void UpdateFromSelectedMemberPathValues()
{
_ignoreSelectedItemsCollectionChanged++;
foreach( var item in ItemsCollection )
{
string[] values = SelectedValue.Split( new string[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries );
foreach( string value in values )
bool? isSelected = this.GetSelectedMemberPathValue( item );
if( isSelected != null )
{
var item = ResolveItemByValue( value );
if( item != null )
if( isSelected.Value )
{
SelectedItems.Add( item );
//now try to select it in the list
var selectorItem = ItemContainerGenerator.ContainerFromItem( item ) as SelectorItem;
if( selectorItem != null )
if( !SelectedItems.Contains( item ) )
{
SelectedItems.Add( item );
}
}
else
{
if( SelectedItems.Contains( item ) )
{
if( !selectorItem.IsSelected )
selectorItem.IsSelected = true;
SelectedItems.Remove( item );
}
}
}
}
_surpressSelectionChanged = false;
_ignoreSelectedItemsCollectionChanged--;
this.UpdateFromSelectedItems();
}
private void ClearSelectedItems()
/// <summary>
/// Updates the following based on the content of SelectedItems:
/// - All SelectorItems "IsSelected" properties
/// - Values refered to by SelectedMemberPath
/// - SelectedItem property
/// - SelectedValue property
/// Refered to by the SelectedMemberPath property.
/// </summary>
private void UpdateFromSelectedItems()
{
if( SelectedItems != null )
SelectedItems.Clear();
else
SelectedItems = new ObservableCollection<object>();
foreach( object o in ItemsCollection )
{
bool isSelected = SelectedItems.Contains( o );
UnselectAllInternal();
_ignoreSelectedMemberPathValuesChanged++;
this.SetSelectedMemberPathValue(o, isSelected);
_ignoreSelectedMemberPathValuesChanged--;
var selectorItem = ItemContainerGenerator.ContainerFromItem( o ) as SelectorItem;
if( selectorItem != null )
{
selectorItem.IsSelected = isSelected;
}
}
UpdateSelectedItem();
UpdateSelectedValue();
}
private void UnselectAllInternal()
/// <summary>
/// Removes all items from SelectedItems that are no longer in ItemsSource.
/// </summary>
private void RemoveUnavailableSelectedItems()
{
_ignoreSetSelectedValue = true;
_ignoreSelectedItemsCollectionChanged++;
HashSet<object> hash = new HashSet<object>( ItemsCollection.Cast<object>() );
if( ItemsSource != null )
for( int i = 0; i < SelectedItems.Count; i++ )
{
foreach( object item in ItemsSource )
if( !hash.Contains( SelectedItems[ i ] ) )
{
var selectorItem = ItemContainerGenerator.ContainerFromItem( item ) as SelectorItem;
if( selectorItem != null )
{
if( selectorItem.IsSelected )
selectorItem.IsSelected = false;
}
SelectedItems.RemoveAt( i );
i--;
}
}
_ignoreSelectedItemsCollectionChanged--;
_ignoreSetSelectedValue = false;
UpdateSelectedItem();
UpdateSelectedValue();
}
protected object ResolveItemByValue( string value )
/// <summary>
/// Updates the SelectedItems collection based on the content of
/// the SelectedValue property.
/// </summary>
private void UpdateFromSelectedValue()
{
if( !String.IsNullOrEmpty( ValueMemberPath ) )
_ignoreSelectedItemsCollectionChanged++;
// Just update the SelectedItems collection content
// and let the synchronization be made from UpdateFromSelectedItems();
SelectedItems.Clear();
if( !String.IsNullOrEmpty( SelectedValue ) )
{
if( ItemsSource != null )
List<string> selectedValues = SelectedValue.Split( new string[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries ).ToList();
ValueEqualityComparer comparer = new ValueEqualityComparer();
foreach( object item in ItemsCollection )
{
foreach( object item in ItemsSource )
object itemValue = this.GetItemValue( item );
bool isSelected = ( itemValue != null )
&& selectedValues.Contains( itemValue.ToString(), comparer );
if( isSelected )
{
var property = item.GetType().GetProperty( ValueMemberPath );
if( property != null )
{
var propertyValue = property.GetValue( item, null );
if( value.Equals( propertyValue.ToString(), StringComparison.InvariantCultureIgnoreCase ) )
return item;
}
SelectedItems.Add( item );
}
}
}
_ignoreSelectedItemsCollectionChanged--;
return value;
this.UpdateFromSelectedItems();
}
#endregion //Methods
#region IWeakEventListener Members
public bool ReceiveWeakEvent( Type managerType, object sender, EventArgs e )
{
if( managerType == typeof( CollectionChangedEventManager ) )
{
if( object.ReferenceEquals( _selectedItems, sender ) )
{
this.OnSelectedItemsCollectionChanged( sender, ( NotifyCollectionChangedEventArgs )e );
return true;
}
else if( object.ReferenceEquals( ItemsCollection, sender ) )
{
this.OnItemsSourceCollectionChanged( sender, ( NotifyCollectionChangedEventArgs )e );
}
}
return false;
}
#endregion
#region ValueEqualityComparer private class
private class ValueEqualityComparer : IEqualityComparer<string>
{
public bool Equals( string x, string y )
{
return string.Equals( x, y, StringComparison.InvariantCultureIgnoreCase );
}
public int GetHashCode( string obj )
{
return 1;
}
}
#endregion
}
public delegate void SelectedItemChangedEventHandler( object sender, SelectedItemChangedEventArgs e );
public class SelectedItemChangedEventArgs : RoutedEventArgs
public delegate void ItemSelectionChangedEventHandler( object sender, ItemSelectionChangedEventArgs e );
public class ItemSelectionChangedEventArgs : RoutedEventArgs
{
public bool IsSelected
{
@ -453,7 +726,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
private set;
}
public SelectedItemChangedEventArgs( RoutedEvent routedEvent, object source, object item, bool isSelected )
public ItemSelectionChangedEventArgs( RoutedEvent routedEvent, object source, object item, bool isSelected )
: base( routedEvent, source )
{
Item = item;

12
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SelectorItem.cs

@ -64,9 +64,9 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected virtual void OnIsSelectedChanged( bool oldValue, bool newValue )
{
if( newValue )
RaiseSelectionChangedEvent( new RoutedEventArgs( Selector.SelectedEvent, this ) );
this.RaiseEvent( new RoutedEventArgs( Selector.SelectedEvent, this ) );
else
RaiseSelectionChangedEvent( new RoutedEventArgs( Selector.UnSelectedEvent, this ) );
this.RaiseEvent( new RoutedEventArgs( Selector.UnSelectedEvent, this ) );
}
internal Selector ParentSelector
@ -95,13 +95,5 @@ namespace Xceed.Wpf.Toolkit.Primitives
#endregion //Event Hanlders
#region Methods
private void RaiseSelectionChangedEvent( RoutedEventArgs e )
{
base.RaiseEvent( e );
}
#endregion //Methods
}
}

113
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs

@ -22,12 +22,14 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using Xceed.Wpf.Toolkit.Core;
using Xceed.Wpf.Toolkit.Core.Input;
namespace Xceed.Wpf.Toolkit.Primitives
{
[TemplatePart( Name = PART_TextBox, Type = typeof( TextBox ) )]
[TemplatePart( Name = PART_Spinner, Type = typeof( Spinner ) )]
public abstract class UpDownBase<T> : InputBase
public abstract class UpDownBase<T> : InputBase, IValidateInput
{
#region Members
@ -45,6 +47,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
/// Flags if the Text and Value properties are in the process of being sync'd
/// </summary>
private bool _isSyncingTextAndValueProperties;
private bool _isTextChangedFromUI;
#endregion //Members
@ -114,7 +117,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( T ), typeof( UpDownBase<T> ), new FrameworkPropertyMetadata( default( T ), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, null, false, UpdateSourceTrigger.LostFocus ) );
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( T ), typeof( UpDownBase<T> ), new FrameworkPropertyMetadata( default( T ), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged, OnCoerceValue, false, UpdateSourceTrigger.LostFocus ) );
public T Value
{
get
@ -127,6 +130,16 @@ namespace Xceed.Wpf.Toolkit.Primitives
}
}
private static object OnCoerceValue( DependencyObject o, object basevalue )
{
return ( ( UpDownBase<T> )o ).OnCoerceValue( basevalue );
}
protected virtual object OnCoerceValue( object newValue )
{
return newValue;
}
private static void OnValueChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
UpDownBase<T> upDownBase = o as UpDownBase<T>;
@ -136,9 +149,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected virtual void OnValueChanged( T oldValue, T newValue )
{
ValidateValue( newValue );
SyncTextAndValueProperties( ValueProperty, string.Empty );
SyncTextAndValueProperties( false, null );
SetValidSpinDirection();
@ -174,6 +185,12 @@ namespace Xceed.Wpf.Toolkit.Primitives
base.OnApplyTemplate();
TextBox = GetTemplateChild( PART_TextBox ) as TextBox;
if( TextBox != null )
{
TextBox.Text = Text;
TextBox.LostFocus += new RoutedEventHandler( TextBox_LostFocus );
TextBox.TextChanged += new TextChangedEventHandler( TextBox_TextChanged );
}
if( Spinner != null )
Spinner.Spin -= OnSpinnerSpin;
@ -213,6 +230,20 @@ namespace Xceed.Wpf.Toolkit.Primitives
}
}
protected override void OnKeyDown( KeyEventArgs e )
{
switch( e.Key )
{
case Key.Enter:
{
// Commit Text on "Enter" to raise Error event
CommitInput();
e.Handled = true;
break;
}
}
}
protected override void OnMouseWheel( MouseWheelEventArgs e )
{
base.OnMouseWheel( e );
@ -234,7 +265,10 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected override void OnTextChanged( string oldValue, string newValue )
{
SyncTextAndValueProperties( InputBase.TextProperty, newValue );
if( !_isTextChangedFromUI )
{
SyncTextAndValueProperties( true, Text );
}
}
#endregion //Base Class Overrides
@ -251,6 +285,10 @@ namespace Xceed.Wpf.Toolkit.Primitives
#region Events
public event InputValidationErrorEventHandler InputValidationError;
#region ValueChanged Event
//Due to a bug in Visual Studio, you cannot create event handlers for generic T args in XAML, so I have to use object instead.
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent( "ValueChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<object> ), typeof( UpDownBase<T> ) );
public event RoutedPropertyChangedEventHandler<object> ValueChanged
@ -265,6 +303,8 @@ namespace Xceed.Wpf.Toolkit.Primitives
}
}
#endregion
#endregion //Events
#region Methods
@ -302,38 +342,65 @@ namespace Xceed.Wpf.Toolkit.Primitives
}
}
protected void SyncTextAndValueProperties( DependencyProperty p, string text )
private void TextBox_TextChanged( object sender, TextChangedEventArgs e )
{
_isTextChangedFromUI = true;
TextBox textBox = sender as TextBox;
Text = textBox.Text;
_isTextChangedFromUI = false;
}
private void TextBox_LostFocus( object sender, RoutedEventArgs e )
{
CommitInput();
}
public void CommitInput()
{
this.SyncTextAndValueProperties( true, Text );
}
protected void SyncTextAndValueProperties(bool updateValueFromText, string text )
{
//prevents recursive syncing properties
if( _isSyncingTextAndValueProperties )
return;
_isSyncingTextAndValueProperties = true;
Exception error = null;
//this only occures when the user typed in the value
if( InputBase.TextProperty == p )
if( updateValueFromText )
{
Value = ConvertTextToValue( text );
try
{
Value = ConvertTextToValue( Text );
}
catch( Exception e )
{
error = e;
}
}
Text = ConvertValueToText();
#if VS2008
//there is a bug in .NET 3.5 which will not correctly update the textbox text through binding.
if ( TextBox != null )
if( TextBox != null )
TextBox.Text = Text;
#endif
if( updateValueFromText )
{
if( ( error != null ) && ( InputValidationError != null ) )
{
InputValidationErrorEventArgs args = new InputValidationErrorEventArgs( error.Message );
InputValidationError( this, args );
}
}
_isSyncingTextAndValueProperties = false;
}
#region Abstract
/// <summary>
/// Coerces the value.
/// </summary>
protected abstract T CoerceValue( T value );
/// <summary>
/// Converts the formatted text to a value.
/// </summary>
@ -360,12 +427,6 @@ namespace Xceed.Wpf.Toolkit.Primitives
/// </summary>
protected abstract void SetValidSpinDirection();
/// <summary>
/// Validates the value and keeps it between the Min and Max values.
/// </summary>
/// <param name="value">The value.</param>
protected abstract void ValidateValue( T value );
#endregion //Abstract
#endregion //Methods

1192
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValueRangeTextBox.cs

File diff suppressed because it is too large

57
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/QueryTextFromValueEventArgs.cs

@ -0,0 +1,57 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.Toolkit.Core
{
public class QueryTextFromValueEventArgs : EventArgs
{
public QueryTextFromValueEventArgs( object value, string text )
{
m_value = value;
m_text = text;
}
#region Value Property
private object m_value;
public object Value
{
get { return m_value; }
}
#endregion Value Property
#region Text Property
private string m_text;
public string Text
{
get { return m_text; }
set { m_text = value; }
}
#endregion Text Property
}
}

70
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/QueryValueFromTextEventArgs.cs

@ -0,0 +1,70 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.Toolkit.Core
{
public class QueryValueFromTextEventArgs : EventArgs
{
public QueryValueFromTextEventArgs( string text, object value )
{
m_text = text;
m_value = value;
}
#region Text Property
private string m_text;
public string Text
{
get { return m_text; }
}
#endregion Text Property
#region Value Property
private object m_value;
public object Value
{
get { return m_value; }
set { m_value = value; }
}
#endregion Value Property
#region HasParsingError Property
private bool m_hasParsingError;
public bool HasParsingError
{
get { return m_hasParsingError; }
set { m_hasParsingError = value; }
}
#endregion HasParsingError Property
}
}

2
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ColorUtilities.cs

@ -184,7 +184,7 @@ namespace Xceed.Wpf.Toolkit.Core.Utilities
}
return Color.FromArgb( 255, ( byte )( r * 255 ), ( byte )( g * 255 ), ( byte )( b * 255 ) );
return Color.FromArgb( 255, ( byte )( Math.Round(r * 255) ), ( byte )( Math.Round(g * 255) ), ( byte )( Math.Round(b * 255) ) );
}
/// <summary>

163
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/NotifyPropertyChangedHelper.cs

@ -0,0 +1,163 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq.Expressions;
namespace Xceed.Wpf.Toolkit.Core.Utilities
{
[DebuggerStepThrough]
internal sealed class NotifyPropertyChangedHelper
{
#region Constructor
internal NotifyPropertyChangedHelper(
INotifyPropertyChanged owner,
Action<string> notifyPropertyChangedDelegate )
{
if( owner == null )
throw new ArgumentNullException( "owner" );
if( notifyPropertyChangedDelegate == null )
throw new ArgumentNullException( "notifyPropertyChangedDelegate" );
m_owner = owner;
m_delegate = notifyPropertyChangedDelegate;
}
#endregion
internal static bool PropertyChanged( string propertyName, PropertyChangedEventArgs e, bool targetPropertyOnly )
{
string target = e.PropertyName;
if( target == propertyName )
return true;
return ( !targetPropertyOnly )
&& ( string.IsNullOrEmpty( target ) );
}
internal static bool PropertyChanged<TOwner, TMember>(
Expression<Func<TMember>> expression,
PropertyChangedEventArgs e,
bool targetPropertyOnly )
{
var body = expression.Body as MemberExpression;
if( body == null )
throw new ArgumentException( "The expression must target a property or field.", "expression" );
return NotifyPropertyChangedHelper.PropertyChanged( body, typeof( TOwner ), e, targetPropertyOnly );
}
internal static bool PropertyChanged<TOwner, TMember>(
Expression<Func<TOwner, TMember>> expression,
PropertyChangedEventArgs e,
bool targetPropertyOnly )
{
var body = expression.Body as MemberExpression;
if( body == null )
throw new ArgumentException( "The expression must target a property or field.", "expression" );
return NotifyPropertyChangedHelper.PropertyChanged( body, typeof( TOwner ), e, targetPropertyOnly );
}
internal void RaisePropertyChanged( string propertyName )
{
ReflectionHelper.ValidatePropertyName( m_owner, propertyName );
this.InvokeDelegate( propertyName );
}
internal void RaisePropertyChanged<TMember>( Expression<Func<TMember>> expression )
{
if( expression == null )
throw new ArgumentNullException( "expression" );
var body = expression.Body as MemberExpression;
if( body == null )
throw new ArgumentException( "The expression must target a property or field.", "expression" );
var propertyName = NotifyPropertyChangedHelper.GetPropertyName( body, m_owner.GetType() );
this.InvokeDelegate( propertyName );
}
internal void HandleReferenceChanged<TMember>( Expression<Func<TMember>> expression, ref TMember localReference, TMember newValue ) where TMember : class
{
if( localReference != newValue )
{
this.ExecutePropertyChanged( expression, ref localReference, newValue );
}
}
internal void HandleEqualityChanged<TMember>( Expression<Func<TMember>> expression, ref TMember localReference, TMember newValue )
{
if( !object.Equals( localReference, newValue ) )
{
this.ExecutePropertyChanged( expression, ref localReference, newValue );
}
}
private void ExecutePropertyChanged<TMember>( Expression<Func<TMember>> expression, ref TMember localReference, TMember newValue )
{
TMember oldValue = localReference;
localReference = newValue;
this.RaisePropertyChanged( expression );
}
internal static string GetPropertyName<TMember>( Expression<Func<TMember>> expression, Type ownerType )
{
var body = expression.Body as MemberExpression;
if( body == null )
throw new ArgumentException( "The expression must target a property or field.", "expression" );
return NotifyPropertyChangedHelper.GetPropertyName( body, ownerType );
}
private static bool PropertyChanged( MemberExpression expression, Type ownerType, PropertyChangedEventArgs e, bool targetPropertyOnly )
{
var propertyName = NotifyPropertyChangedHelper.GetPropertyName( expression, ownerType );
return NotifyPropertyChangedHelper.PropertyChanged( propertyName, e, targetPropertyOnly );
}
private static string GetPropertyName( MemberExpression expression, Type ownerType )
{
var targetType = expression.Expression.Type;
if( !targetType.IsAssignableFrom( ownerType ) )
throw new ArgumentException( "The expression must target a property or field on the appropriate owner.", "expression" );
return ReflectionHelper.GetPropertyOrFieldName( expression );
}
private void InvokeDelegate( string propertyName )
{
m_delegate.Invoke( propertyName );
}
#region Private Fields
private readonly INotifyPropertyChanged m_owner;
private readonly Action<string> m_delegate;
#endregion
}
}

136
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ReflectionHelper.cs

@ -0,0 +1,136 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
namespace Xceed.Wpf.Toolkit.Core.Utilities
{
internal static class ReflectionHelper
{
/// <summary>
/// Check the existence of the specified public instance (i.e. non static) property against
/// the type of the specified source object. If the property is not defined by the type,
/// a debug assertion will fail. Typically used to validate the parameter of a
/// RaisePropertyChanged method.
/// </summary>
/// <param name="sourceObject">The object for which the type will be checked.</param>
/// <param name="propertyName">The name of the property.</param>
[System.Diagnostics.Conditional( "DEBUG" )]
internal static void ValidatePublicPropertyName( object sourceObject, string propertyName )
{
if( sourceObject == null )
throw new ArgumentNullException( "sourceObject" );
if( propertyName == null )
throw new ArgumentNullException( "propertyName" );
System.Diagnostics.Debug.Assert( sourceObject.GetType().GetProperty( propertyName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.Public ) != null,
string.Format( "Public property {0} not found on object of type {1}.", propertyName, sourceObject.GetType().FullName ) );
}
/// <summary>
/// Check the existence of the specified instance (i.e. non static) property against
/// the type of the specified source object. If the property is not defined by the type,
/// a debug assertion will fail. Typically used to validate the parameter of a
/// RaisePropertyChanged method.
/// </summary>
/// <param name="sourceObject">The object for which the type will be checked.</param>
/// <param name="propertyName">The name of the property.</param>
[System.Diagnostics.Conditional( "DEBUG" )]
internal static void ValidatePropertyName( object sourceObject, string propertyName )
{
if( sourceObject == null )
throw new ArgumentNullException( "sourceObject" );
if( propertyName == null )
throw new ArgumentNullException( "propertyName" );
System.Diagnostics.Debug.Assert( sourceObject.GetType().GetProperty( propertyName, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic ) != null,
string.Format( "Public property {0} not found on object of type {1}.", propertyName, sourceObject.GetType().FullName ) );
}
internal static bool TryGetEnumDescriptionAttributeValue( Enum enumeration, out string description )
{
try
{
FieldInfo fieldInfo = enumeration.GetType().GetField( enumeration.ToString() );
DescriptionAttribute[] attributes = fieldInfo.GetCustomAttributes( typeof( DescriptionAttribute ), true ) as DescriptionAttribute[];
if( ( attributes != null ) && ( attributes.Length > 0 ) )
{
description = attributes[ 0 ].Description;
return true;
}
}
catch
{
}
description = String.Empty;
return false;
}
[DebuggerStepThrough]
internal static string GetPropertyOrFieldName( MemberExpression expression )
{
string propertyOrFieldName;
if( !ReflectionHelper.TryGetPropertyOrFieldName( expression, out propertyOrFieldName ) )
throw new InvalidOperationException( "Unable to retrieve the property or field name." );
return propertyOrFieldName;
}
[DebuggerStepThrough]
internal static string GetPropertyOrFieldName<TMember>( Expression<Func<TMember>> expression )
{
string propertyOrFieldName;
if( !ReflectionHelper.TryGetPropertyOrFieldName( expression, out propertyOrFieldName ) )
throw new InvalidOperationException( "Unable to retrieve the property or field name." );
return propertyOrFieldName;
}
[DebuggerStepThrough]
internal static bool TryGetPropertyOrFieldName( MemberExpression expression, out string propertyOrFieldName )
{
propertyOrFieldName = null;
if( expression == null )
return false;
propertyOrFieldName = expression.Member.Name;
return true;
}
[DebuggerStepThrough]
internal static bool TryGetPropertyOrFieldName<TMember>( Expression<Func<TMember>> expression, out string propertyOrFieldName )
{
propertyOrFieldName = null;
if( expression == null )
return false;
return ReflectionHelper.TryGetPropertyOrFieldName( expression.Body as MemberExpression, out propertyOrFieldName );
}
}
}

238
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/TreeHelper.cs

@ -0,0 +1,238 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls.Primitives;
namespace Xceed.Wpf.Toolkit.Core.Utilities
{
internal static class TreeHelper
{
/// <summary>
/// Tries its best to return the specified element's parent. It will
/// try to find, in this order, the VisualParent, LogicalParent, LogicalTemplatedParent.
/// It only works for Visual, FrameworkElement or FrameworkContentElement.
/// </summary>
/// <param name="element">The element to which to return the parent. It will only
/// work if element is a Visual, a FrameworkElement or a FrameworkContentElement.</param>
/// <remarks>If the logical parent is not found (Parent), we check the TemplatedParent
/// (see FrameworkElement.Parent documentation). But, we never actually witnessed
/// this situation.</remarks>
public static DependencyObject GetParent( DependencyObject element )
{
return TreeHelper.GetParent( element, true );
}
private static DependencyObject GetParent( DependencyObject element, bool recurseIntoPopup )
{
if( recurseIntoPopup )
{
// Case 126732 : To correctly detect parent of a popup we must do that exception case
Popup popup = element as Popup;
if( ( popup != null ) && ( popup.PlacementTarget != null ) )
return popup.PlacementTarget;
}
Visual visual = element as Visual;
DependencyObject parent = ( visual == null ) ? null : VisualTreeHelper.GetParent( visual );
if( parent == null )
{
// No Visual parent. Check in the logical tree.
FrameworkElement fe = element as FrameworkElement;
if( fe != null )
{
parent = fe.Parent;
if( parent == null )
{
parent = fe.TemplatedParent;
}
}
else
{
FrameworkContentElement fce = element as FrameworkContentElement;
if( fce != null )
{
parent = fce.Parent;
if( parent == null )
{
parent = fce.TemplatedParent;
}
}
}
}
return parent;
}
/// <summary>
/// This will search for a parent of the specified type.
/// </summary>
/// <typeparam name="T">The type of the element to find</typeparam>
/// <param name="startingObject">The node where the search begins. This element is not checked.</param>
/// <returns>Returns the found element. Null if nothing is found.</returns>
public static T FindParent<T>( DependencyObject startingObject ) where T : DependencyObject
{
return TreeHelper.FindParent<T>( startingObject, false, null );
}
/// <summary>
/// This will search for a parent of the specified type.
/// </summary>
/// <typeparam name="T">The type of the element to find</typeparam>
/// <param name="startingObject">The node where the search begins.</param>
/// <param name="checkStartingObject">Should the specified startingObject be checked first.</param>
/// <returns>Returns the found element. Null if nothing is found.</returns>
public static T FindParent<T>( DependencyObject startingObject, bool checkStartingObject ) where T : DependencyObject
{
return TreeHelper.FindParent<T>( startingObject, checkStartingObject, null );
}
/// <summary>
/// This will search for a parent of the specified type.
/// </summary>
/// <typeparam name="T">The type of the element to find</typeparam>
/// <param name="startingObject">The node where the search begins.</param>
/// <param name="checkStartingObject">Should the specified startingObject be checked first.</param>
/// <param name="additionalCheck">Provide a callback to check additional properties
/// of the found elements. Can be left Null if no additional criteria are needed.</param>
/// <returns>Returns the found element. Null if nothing is found.</returns>
/// <example>Button button = TreeHelper.FindParent&lt;Button&gt;( this, foundChild => foundChild.Focusable );</example>
public static T FindParent<T>( DependencyObject startingObject, bool checkStartingObject, Func<T, bool> additionalCheck ) where T : DependencyObject
{
T foundElement;
DependencyObject parent = ( checkStartingObject ? startingObject : TreeHelper.GetParent( startingObject, true ) );
while( parent != null )
{
foundElement = parent as T;
if( foundElement != null )
{
if( additionalCheck == null )
{
return foundElement;
}
else
{
if( additionalCheck( foundElement ) )
return foundElement;
}
}
parent = TreeHelper.GetParent( parent, true );
}
return null;
}
/// <summary>
/// This will search for a child of the specified type. The search is performed
/// hierarchically, breadth first (as opposed to depth first).
/// </summary>
/// <typeparam name="T">The type of the element to find</typeparam>
/// <param name="parent">The root of the tree to search for. This element itself is not checked.</param>
/// <returns>Returns the found element. Null if nothing is found.</returns>
public static T FindChild<T>( DependencyObject parent ) where T : DependencyObject
{
return TreeHelper.FindChild<T>( parent, null );
}
/// <summary>
/// This will search for a child of the specified type. The search is performed
/// hierarchically, breadth first (as opposed to depth first).
/// </summary>
/// <typeparam name="T">The type of the element to find</typeparam>
/// <param name="parent">The root of the tree to search for. This element itself is not checked.</param>
/// <param name="additionalCheck">Provide a callback to check additional properties
/// of the found elements. Can be left Null if no additional criteria are needed.</param>
/// <returns>Returns the found element. Null if nothing is found.</returns>
/// <example>Button button = TreeHelper.FindChild&lt;Button&gt;( this, foundChild => foundChild.Focusable );</example>
public static T FindChild<T>( DependencyObject parent, Func<T, bool> additionalCheck ) where T : DependencyObject
{
int childrenCount = VisualTreeHelper.GetChildrenCount( parent );
T child;
for( int index = 0; index < childrenCount; index++ )
{
child = VisualTreeHelper.GetChild( parent, index ) as T;
if( child != null )
{
if( additionalCheck == null )
{
return child;
}
else
{
if( additionalCheck( child ) )
return child;
}
}
}
for( int index = 0; index < childrenCount; index++ )
{
child = TreeHelper.FindChild<T>( VisualTreeHelper.GetChild( parent, index ), additionalCheck );
if( child != null )
return child;
}
return null;
}
/// <summary>
/// Returns true if the specified element is a child of parent somewhere in the visual
/// tree. This method will work for Visual, FrameworkElement and FrameworkContentElement.
/// </summary>
/// <param name="element">The element that is potentially a child of the specified parent.</param>
/// <param name="parent">The element that is potentially a parent of the specified element.</param>
public static bool IsDescendantOf( DependencyObject element, DependencyObject parent )
{
return TreeHelper.IsDescendantOf( element, parent, true );
}
/// <summary>
/// Returns true if the specified element is a child of parent somewhere in the visual
/// tree. This method will work for Visual, FrameworkElement and FrameworkContentElement.
/// </summary>
/// <param name="element">The element that is potentially a child of the specified parent.</param>
/// <param name="parent">The element that is potentially a parent of the specified element.</param>
public static bool IsDescendantOf( DependencyObject element, DependencyObject parent, bool recurseIntoPopup )
{
while( element != null )
{
if( element == parent )
return true;
element = TreeHelper.GetParent( element, recurseIntoPopup );
}
return false;
}
}
}

153
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Utilities/ValueChangeHelper.cs

@ -0,0 +1,153 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Collections;
using System.Windows.Data;
namespace Xceed.Wpf.Toolkit.Core.Utilities
{
/// <summary>
/// This helper class will raise events when a specific
/// path value on one or many items changes.
/// </summary>
internal class ValueChangeHelper : DependencyObject
{
#region Value Property
/// <summary>
/// This private property serves as the target of a binding that monitors the value of the binding
/// of each item in the source.
/// </summary>
private static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( ValueChangeHelper ), new UIPropertyMetadata( null, OnValueChanged ) );
private object Value
{
get
{
return ( object )GetValue( ValueProperty );
}
set
{
SetValue( ValueProperty, value );
}
}
private static void OnValueChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args )
{
( ( ValueChangeHelper )sender ).RaiseValueChanged();
}
#endregion
public event EventHandler ValueChanged;
#region Constructor
public ValueChangeHelper(Action changeCallback)
{
if( changeCallback == null )
throw new ArgumentNullException( "changeCallback" );
this.ValueChanged += ( s, args ) => changeCallback();
}
#endregion
#region Methods
public void UpdateValueSource( object sourceItem, string path )
{
BindingBase binding = null;
if( sourceItem != null && path != null )
{
binding = new Binding( path ) { Source = sourceItem };
}
this.UpdateBinding( binding );
}
public void UpdateValueSource( IEnumerable sourceItems, string path )
{
BindingBase binding = null;
if( sourceItems != null && path != null )
{
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = new BlankMultiValueConverter();
foreach( var item in sourceItems )
{
multiBinding.Bindings.Add( new Binding( path ) { Source = item } );
}
binding = multiBinding;
}
this.UpdateBinding( binding );
}
private void UpdateBinding( BindingBase binding )
{
if( binding != null )
{
BindingOperations.SetBinding( this, ValueChangeHelper.ValueProperty, binding );
}
else
{
this.ClearBinding();
}
}
private void ClearBinding()
{
BindingOperations.ClearBinding( this, ValueChangeHelper.ValueProperty );
}
private void RaiseValueChanged()
{
if( this.ValueChanged != null )
{
this.ValueChanged( this, EventArgs.Empty );
}
}
#endregion
#region BlankMultiValueConverter private class
private class BlankMultiValueConverter : IMultiValueConverter
{
public object Convert( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
// We will not use the result anyway. We just want the change notification to kick in.
// Return a new object to have a different value.
return new object();
}
public object[] ConvertBack( object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture )
{
throw new InvalidOperationException();
}
}
#endregion
}
}

10
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DateTimePicker/Themes/Generic.xaml

@ -36,7 +36,14 @@
<GradientStop Color="#FF617584" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="PopupBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush x:Key="DarkBorderBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF617584" Offset="0" />
<GradientStop Color="#FF718597" Offset="0.375" />
<GradientStop Color="#FF8399A9" Offset="0.375" />
<GradientStop Color="#FFA3AEB9" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="PopupBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FFffffff" />
@ -88,6 +95,7 @@
<Style TargetType="{x:Type local:DateTimePicker}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{StaticResource DarkBorderBrush}" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="HorizontalContentAlignment" Value="Right" />

26
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/DateTimeUpDown/Implementation/DateTimeUpDown.cs

@ -163,12 +163,6 @@ namespace Xceed.Wpf.Toolkit
InitializeDateTimeInfoList();
}
protected override DateTime? CoerceValue( DateTime? value )
{
//TODO: implement Minimum and Maximum
return value;
}
protected override void OnIncrement()
{
if( Value.HasValue )
@ -216,18 +210,15 @@ namespace Xceed.Wpf.Toolkit
if( !_processTextChanged )
return;
//TODO: clean this up and make sure it doesn't fire recursively
if( String.IsNullOrEmpty( currentValue ) )
if( !String.IsNullOrEmpty( currentValue ) )
{
Value = null;
return;
DateTime current = Value.HasValue ? Value.Value : DateTime.Parse( DateTime.Now.ToString(), CultureInfo.DateTimeFormat );
DateTime result;
var success = DateTimeParser.TryParse( currentValue, GetFormatString( Format ), current, CultureInfo, out result );
currentValue = result.ToString();
}
DateTime current = Value.HasValue ? Value.Value : DateTime.Parse( DateTime.Now.ToString(), CultureInfo.DateTimeFormat );
DateTime result;
var success = DateTimeParser.TryParse( currentValue, GetFormatString( Format ), current, CultureInfo, out result );
SyncTextAndValueProperties( InputBase.TextProperty, result.ToString( CultureInfo ) );
SyncTextAndValueProperties( true, currentValue );
}
protected override DateTime? ConvertTextToValue( string text )
@ -261,11 +252,6 @@ namespace Xceed.Wpf.Toolkit
base.OnValueChanged( oldValue, newValue );
}
protected override void ValidateValue( DateTime? value )
{
//TODO: implement min/max
}
#endregion //Base Class Overrides
#region Event Hanlders

4
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Magnifier/Implementation/Magnifier.cs

@ -224,8 +224,8 @@ namespace Xceed.Wpf.Toolkit
VisualBrush newBrush = GetTemplateChild( PART_VisualBrush ) as VisualBrush;
// Just create a brush as placeholder even if there is no such brush
// this avoid having to "if" each access to the _visualBrush member.
// Just create a brush as placeholder even if there is no such brush.
// This avoids having to "if" each access to the _visualBrush member.
// Do not keep the current _visualBrush whatsoever to avoid memory leaks.
if( newBrush == null )
{

108
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/AutoCompletingMaskEventArgs.cs

@ -0,0 +1,108 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.Toolkit
{
public class AutoCompletingMaskEventArgs : CancelEventArgs
{
public AutoCompletingMaskEventArgs( MaskedTextProvider maskedTextProvider, int startPosition, int selectionLength, string input )
{
m_autoCompleteStartPosition = -1;
m_maskedTextProvider = maskedTextProvider;
m_startPosition = startPosition;
m_selectionLength = selectionLength;
m_input = input;
}
#region MaskedTextProvider PROPERTY
private MaskedTextProvider m_maskedTextProvider;
public MaskedTextProvider MaskedTextProvider
{
get { return m_maskedTextProvider; }
}
#endregion MaskedTextProvider PROPERTY
#region StartPosition PROPERTY
private int m_startPosition;
public int StartPosition
{
get { return m_startPosition; }
}
#endregion StartPosition PROPERTY
#region SelectionLength PROPERTY
private int m_selectionLength;
public int SelectionLength
{
get { return m_selectionLength; }
}
#endregion SelectionLength PROPERTY
#region Input PROPERTY
private string m_input;
public string Input
{
get { return m_input; }
}
#endregion Input PROPERTY
#region AutoCompleteStartPosition PROPERTY
private int m_autoCompleteStartPosition;
public int AutoCompleteStartPosition
{
get { return m_autoCompleteStartPosition; }
set { m_autoCompleteStartPosition = value; }
}
#endregion AutoCompleteStartPosition PROPERTY
#region AutoCompleteText PROPERTY
private string m_autoCompleteText;
public string AutoCompleteText
{
get { return m_autoCompleteText; }
set { m_autoCompleteText = value; }
}
#endregion AutoCompleteText PROPERTY
}
}

32
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/InsertKeyModeEnum.cs

@ -0,0 +1,32 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.Toolkit
{
public enum InsertKeyMode
{
Default = 0,
Insert = 1,
Overwrite = 2
}
}

33
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskFormatEnum.cs

@ -0,0 +1,33 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace Xceed.Wpf.Toolkit
{
public enum MaskFormat
{
ExcludePromptAndLiterals,
IncludeLiterals,
IncludePrompt,
IncludePromptAndLiterals
}
}

2116
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskedTextBox.cs

File diff suppressed because it is too large

80
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/Implementation/MessageBox.cs

@ -153,6 +153,71 @@ namespace Xceed.Wpf.Toolkit
}
}
public static readonly DependencyProperty ButtonRegionBackgroundProperty = DependencyProperty.Register( "ButtonRegionBackground", typeof( Brush ), typeof( MessageBox ), new PropertyMetadata( null ) );
public Brush ButtonRegionBackground
{
get
{
return ( Brush )GetValue( ButtonRegionBackgroundProperty );
}
set
{
SetValue( ButtonRegionBackgroundProperty, value );
}
}
public static readonly DependencyProperty OkButtonStyleProperty = DependencyProperty.Register( "OkButtonStyle", typeof( Style ), typeof( MessageBox ), new PropertyMetadata( null ) );
public Style OkButtonStyle
{
get
{
return ( Style )GetValue( OkButtonStyleProperty );
}
set
{
SetValue( OkButtonStyleProperty, value );
}
}
public static readonly DependencyProperty CancelButtonStyleProperty = DependencyProperty.Register( "CancelButtonStyle", typeof( Style ), typeof( MessageBox ), new PropertyMetadata( null ) );
public Style CancelButtonStyle
{
get
{
return ( Style )GetValue( CancelButtonStyleProperty );
}
set
{
SetValue( CancelButtonStyleProperty, value );
}
}
public static readonly DependencyProperty YesButtonStyleProperty = DependencyProperty.Register( "YesButtonStyle", typeof( Style ), typeof( MessageBox ), new PropertyMetadata( null ) );
public Style YesButtonStyle
{
get
{
return ( Style )GetValue( YesButtonStyleProperty );
}
set
{
SetValue( YesButtonStyleProperty, value );
}
}
public static readonly DependencyProperty NoButtonStyleProperty = DependencyProperty.Register( "NoButtonStyle", typeof( Style ), typeof( MessageBox ), new PropertyMetadata( null ) );
public Style NoButtonStyle
{
get
{
return ( Style )GetValue( NoButtonStyleProperty );
}
set
{
SetValue( NoButtonStyleProperty, value );
}
}
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register( "ImageSource", typeof( ImageSource ), typeof( MessageBox ), new UIPropertyMetadata( default( ImageSource ) ) );
public ImageSource ImageSource
{
@ -280,6 +345,14 @@ namespace Xceed.Wpf.Toolkit
ChangeVisualState( _button.ToString(), true );
Button closeButton = GetMessageBoxButton( PART_CloseButton );
if( closeButton != null )
closeButton.IsEnabled = !object.Equals( _button, MessageBoxButton.YesNo );
Button okButton = GetMessageBoxButton( PART_OkButton );
if( okButton != null )
okButton.IsCancel = object.Equals( _button, MessageBoxButton.OK );
SetDefaultResult();
}
@ -318,7 +391,6 @@ namespace Xceed.Wpf.Toolkit
/// </summary>
/// <param name="messageText">A System.String that specifies the text to display.</param>
/// <param name="caption">A System.String that specifies the title bar caption to display.</param>
/// <param name="messageBoxStyle">A Style that will be applied to the MessageBox instance.</param>
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
public static MessageBoxResult Show( string messageText, string caption )
{
@ -696,6 +768,10 @@ namespace Xceed.Wpf.Toolkit
MessageBoxResult = MessageBoxResult.Yes;
break;
case PART_CloseButton:
MessageBoxResult = object.Equals( _button, MessageBoxButton.OK )
? MessageBoxResult.OK
: MessageBoxResult.Cancel;
break;
case PART_CancelButton:
MessageBoxResult = MessageBoxResult.Cancel;
break;
@ -704,6 +780,8 @@ namespace Xceed.Wpf.Toolkit
break;
}
e.Handled = true;
Close();
}

43
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/MessageBox/Themes/Generic.xaml

@ -87,7 +87,13 @@
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="Opacity" To=".3"/>
<DoubleAnimation Duration="0" Storyboard.TargetName="Background" Storyboard.TargetProperty="Opacity" To=".3"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="Background" CornerRadius="0,0,2,0" Background="{StaticResource WindowDarkBrush}">
<Border Margin="1,0,1,1" BorderBrush="#59FFFFFF" BorderThickness="1" CornerRadius="0,0,1,0" />
@ -122,6 +128,7 @@
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CaptionForeground" Value="#FF000000" />
<Setter Property="CloseButtonStyle" Value="{StaticResource WindowCloseButtonStyle}" />
<Setter Property="ButtonRegionBackground" Value="#FFF0F0F0" />
<Setter Property="Focusable" Value="False" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
@ -218,10 +225,10 @@
<!-- Borders -->
<Grid x:Name="MessageBoxWindowGrid">
<Border BorderBrush="{TemplateBinding WindowBorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5,5,0,0" Opacity="{TemplateBinding WindowOpacity}" />
<Border BorderBrush="{TemplateBinding WindowBorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5,5,5,5" Opacity="{TemplateBinding WindowOpacity}" />
<Grid Margin="0" Background="{x:Null}">
<Border x:Name="MessageBoxWindow" Margin="1,1,1,1" Background="{TemplateBinding WindowBackground}" CornerRadius="4,4,0,0" Opacity="{TemplateBinding WindowOpacity}" />
<Border BorderBrush="White" BorderThickness="1" CornerRadius="4,4,0,0" Margin="1" Opacity="0.7" />
<Border x:Name="MessageBoxWindow" Margin="1,1,1,1" Background="{TemplateBinding WindowBackground}" CornerRadius="4,4,4,4" Opacity="{TemplateBinding WindowOpacity}" />
<Border BorderBrush="White" BorderThickness="1" CornerRadius="4,4,4,4" Margin="1" Opacity="0.7" />
</Grid>
</Grid>
@ -272,18 +279,20 @@
</Grid>
<!-- Buttons -->
<Grid Grid.Row="1" HorizontalAlignment="Right" Margin="12,0,12,12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="PART_YesButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding YesButtonContent}" />
<Button Grid.Column="1" x:Name="PART_NoButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding NoButtonContent}" />
<Button Grid.Column="2" x:Name="PART_OkButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding OkButtonContent}" />
<Button Grid.Column="3" x:Name="PART_CancelButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding CancelButtonContent}" IsCancel="True" />
</Grid>
<Border Grid.Row="1" Background="{TemplateBinding ButtonRegionBackground}" >
<Grid HorizontalAlignment="Right" Margin="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" x:Name="PART_YesButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding YesButtonContent}" Style="{TemplateBinding YesButtonStyle}"/>
<Button Grid.Column="1" x:Name="PART_NoButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding NoButtonContent}" Style="{TemplateBinding NoButtonStyle}"/>
<Button Grid.Column="2" x:Name="PART_OkButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding OkButtonContent}" Style="{TemplateBinding OkButtonStyle}"/>
<Button Grid.Column="3" x:Name="PART_CancelButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding CancelButtonContent}" Style="{TemplateBinding CancelButtonStyle}" IsCancel="True" />
</Grid>
</Border>
</Grid>
</Border>
</Grid>
@ -310,7 +319,7 @@
<!-- Close Button -->
<Border BorderBrush="#A5FFFFFF" BorderThickness="1,0,1,1" CornerRadius="0,0,3,3" VerticalAlignment="Top" Margin="0,1,7,0" HorizontalAlignment="Right">
<Button x:Name="PART_CloseButton" Style="{TemplateBinding CloseButtonStyle}" Height="17" Width="43" IsTabStop="False" IsCancel="True">
<Button x:Name="PART_CloseButton" Style="{TemplateBinding CloseButtonStyle}" Height="17" Width="43" IsTabStop="False">
<Path Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ByteUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class ByteUpDown : CommonNumericUpDown<byte>
{
#region Constructors
static ByteUpDown()
{
UpdateMetadata( typeof( ByteUpDown ), default( byte ), ( byte )1, byte.MinValue, byte.MaxValue );
}
public ByteUpDown()
: base( Byte.Parse, Decimal.ToByte )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override byte IncrementValue( byte value, byte increment )
{
return ( byte )( value + increment );
}
protected override byte DecrementValue( byte value, byte increment )
{
return ( byte )( value - increment );
}
#endregion //Base Class Overrides
}
}

184
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/CommonNumericUpDown.cs

@ -0,0 +1,184 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
using System.Globalization;
namespace Xceed.Wpf.Toolkit
{
public abstract class CommonNumericUpDown<T> : NumericUpDown<T?> where T : struct, IFormattable, IComparable<T>
{
protected delegate T FromText( string s, NumberStyles style, IFormatProvider provider );
protected delegate T FromDecimal( decimal d );
private FromText _fromText;
private FromDecimal _fromDecimal;
protected CommonNumericUpDown( FromText fromText, FromDecimal fromDecimal )
{
if( fromText == null )
throw new ArgumentNullException( "parseMethod" );
if( fromDecimal == null )
throw new ArgumentNullException( "fromDecimal" );
_fromText = fromText;
_fromDecimal = fromDecimal;
}
protected static void UpdateMetadata( Type type, T? defaultValue, T? increment, T? minValue, T? maxValue )
{
DefaultStyleKeyProperty.OverrideMetadata( type, new FrameworkPropertyMetadata( type ) );
DefaultValueProperty.OverrideMetadata( type, new FrameworkPropertyMetadata( defaultValue ) );
IncrementProperty.OverrideMetadata( type, new FrameworkPropertyMetadata( increment ) );
MaximumProperty.OverrideMetadata( type, new FrameworkPropertyMetadata( maxValue ) );
MinimumProperty.OverrideMetadata( type, new FrameworkPropertyMetadata( minValue ) );
}
private bool IsLowerThan( T? value1, T? value2 )
{
if( value1 == null || value2 == null )
return false;
return ( value1.Value.CompareTo( value2.Value ) < 0 );
}
private bool IsGreaterThan( T? value1, T? value2 )
{
if( value1 == null || value2 == null )
return false;
return ( value1.Value.CompareTo( value2.Value ) > 0 );
}
private bool HandleNullSpin()
{
if( !Value.HasValue )
{
Value = DefaultValue;
return true;
}
else if( !Increment.HasValue )
{
return true;
}
return false;
}
private T? CoerceValue( T value )
{
if( IsLowerThan( value, Minimum ) )
return Minimum;
else if( IsGreaterThan( value, Maximum ) )
return Maximum;
else
return value;
}
#region Base Class Overrides
protected override object OnCoerceValue( object newValue )
{
ValidateMinMax( ( T? )newValue );
return newValue;
}
protected override void OnIncrement()
{
if( !HandleNullSpin() )
{
T result = IncrementValue( Value.Value, Increment.Value );
Value = CoerceValue( result );
}
}
protected override void OnDecrement()
{
if( !HandleNullSpin() )
{
T result = DecrementValue( Value.Value, Increment.Value );
Value = CoerceValue( result );
}
}
protected override T? ConvertTextToValue( string text )
{
T? result = null;
if( String.IsNullOrEmpty( text ) )
return result;
//don't know why someone would format a T as %, but just in case they do.
result = FormatString.Contains( "P" )
? _fromDecimal( ParsePercent( text, CultureInfo ) )
: _fromText( text, NumberStyles.Any, CultureInfo );
ValidateMinMax( result );
return result;
}
protected override string ConvertValueToText()
{
if( Value == null )
return string.Empty;
return Value.Value.ToString( FormatString, CultureInfo );
}
protected override void SetValidSpinDirection()
{
ValidSpinDirections validDirections = ValidSpinDirections.None;
if( IsLowerThan( Value, Maximum ) || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( IsGreaterThan( Value, Minimum ) || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
}
private void ValidateMinMax( T? value )
{
if( IsLowerThan( value, Minimum ) )
throw new ArgumentOutOfRangeException( "Minimum", String.Format( "Value must be greater than MinValue of {0}", Minimum ) );
else if( IsGreaterThan( value, Maximum ) )
throw new ArgumentOutOfRangeException( "Maximum", String.Format( "Value must be less than MaxValue of {0}", Maximum ) );
}
#endregion //Base Class Overrides
#region Abstract Methods
protected abstract T IncrementValue( T value, T increment );
protected abstract T DecrementValue( T value, T increment );
#endregion
}
}

86
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DecimalUpDown.cs

@ -22,98 +22,32 @@ using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class DecimalUpDown : NumericUpDown<decimal?>
public class DecimalUpDown : CommonNumericUpDown<decimal>
{
#region Constructors
static DecimalUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( DecimalUpDown ), new FrameworkPropertyMetadata( typeof( DecimalUpDown ) ) );
DefaultValueProperty.OverrideMetadata( typeof( DecimalUpDown ), new FrameworkPropertyMetadata( default( decimal ) ) );
IncrementProperty.OverrideMetadata( typeof( DecimalUpDown ), new FrameworkPropertyMetadata( 1m ) );
MaximumProperty.OverrideMetadata( typeof( DecimalUpDown ), new FrameworkPropertyMetadata( decimal.MaxValue ) );
MinimumProperty.OverrideMetadata( typeof( DecimalUpDown ), new FrameworkPropertyMetadata( decimal.MinValue ) );
UpdateMetadata( typeof( DecimalUpDown ), default( decimal ), 1m, decimal.MinValue, decimal.MaxValue );
}
#endregion //Constructors
#region Base Class Overrides
protected override decimal? CoerceValue( decimal? value )
{
if( value < Minimum )
return Minimum;
else if( value > Maximum )
return Maximum;
else
return value;
}
protected override void OnIncrement()
{
if( Value.HasValue )
Value += Increment;
else
Value = DefaultValue;
}
protected override void OnDecrement()
public DecimalUpDown()
: base( Decimal.Parse, (d) => d )
{
if( Value.HasValue )
Value -= Increment;
else
Value = DefaultValue;
}
protected override decimal? ConvertTextToValue( string text )
{
decimal? result = null;
if( String.IsNullOrEmpty( text ) )
return result;
try
{
result = FormatString.Contains( "P" ) ? ParsePercent( text, CultureInfo ) : ParseDecimal( text, CultureInfo );
result = CoerceValue( result );
}
catch
{
Text = ConvertValueToText();
return Value;
}
return result;
}
protected override string ConvertValueToText()
{
if( Value == null )
return string.Empty;
#endregion //Constructors
return Value.Value.ToString( FormatString, CultureInfo );
}
#region Base Class Overrides
protected override void SetValidSpinDirection()
protected override decimal IncrementValue( decimal value, decimal increment )
{
ValidSpinDirections validDirections = ValidSpinDirections.None;
if( Value < Maximum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( Value > Minimum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
return value + increment;
}
protected override void ValidateValue( decimal? value )
protected override decimal DecrementValue( decimal value, decimal increment )
{
if( value < Minimum )
Value = Minimum;
else if( value > Maximum )
Value = Maximum;
return value - increment;
}
#endregion //Base Class Overrides

86
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DoubleUpDown.cs

@ -22,98 +22,32 @@ using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class DoubleUpDown : NumericUpDown<double?>
public class DoubleUpDown : CommonNumericUpDown<double>
{
#region Constructors
static DoubleUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( DoubleUpDown ), new FrameworkPropertyMetadata( typeof( DoubleUpDown ) ) );
DefaultValueProperty.OverrideMetadata( typeof( DoubleUpDown ), new FrameworkPropertyMetadata( default( double ) ) );
IncrementProperty.OverrideMetadata( typeof( DoubleUpDown ), new FrameworkPropertyMetadata( 1d ) );
MaximumProperty.OverrideMetadata( typeof( DoubleUpDown ), new FrameworkPropertyMetadata( double.MaxValue ) );
MinimumProperty.OverrideMetadata( typeof( DoubleUpDown ), new FrameworkPropertyMetadata( double.MinValue ) );
UpdateMetadata( typeof( DoubleUpDown ), default( double ), 1d, double.MinValue, double.MaxValue );
}
#endregion //Constructors
#region Base Class Overrides
protected override double? CoerceValue( double? value )
{
if( value < Minimum )
return Minimum;
else if( value > Maximum )
return Maximum;
else
return value;
}
protected override void OnIncrement()
{
if( Value.HasValue )
Value += Increment;
else
Value = DefaultValue;
}
protected override void OnDecrement()
public DoubleUpDown()
: base( Double.Parse, Decimal.ToDouble )
{
if( Value.HasValue )
Value -= Increment;
else
Value = DefaultValue;
}
protected override double? ConvertTextToValue( string text )
{
double? result = null;
if( String.IsNullOrEmpty( text ) )
return result;
try
{
result = FormatString.Contains( "P" ) ? Decimal.ToDouble( ParsePercent( text, CultureInfo ) ) : ParseDouble( text, CultureInfo );
result = CoerceValue( result );
}
catch
{
Text = ConvertValueToText();
return Value;
}
return result;
}
protected override string ConvertValueToText()
{
if( Value == null )
return string.Empty;
#endregion //Constructors
return Value.Value.ToString( FormatString, CultureInfo );
}
#region Base Class Overrides
protected override void SetValidSpinDirection()
protected override double IncrementValue( double value, double increment )
{
ValidSpinDirections validDirections = ValidSpinDirections.None;
if( Value < Maximum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( Value > Minimum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
return value + increment;
}
protected override void ValidateValue( double? value )
protected override double DecrementValue( double value, double increment )
{
if( value < Minimum )
Value = Minimum;
else if( value > Maximum )
Value = Maximum;
return value - increment;
}
#endregion //Base Class Overrides

87
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/IntegerUpDown.cs

@ -22,99 +22,32 @@ using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class IntegerUpDown : NumericUpDown<int?>
public class IntegerUpDown : CommonNumericUpDown<int>
{
#region Constructors
static IntegerUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata( typeof( IntegerUpDown ), new FrameworkPropertyMetadata( typeof( IntegerUpDown ) ) );
DefaultValueProperty.OverrideMetadata( typeof( IntegerUpDown ), new FrameworkPropertyMetadata( 0 ) );
IncrementProperty.OverrideMetadata( typeof( IntegerUpDown ), new FrameworkPropertyMetadata( 1 ) );
MaximumProperty.OverrideMetadata( typeof( IntegerUpDown ), new FrameworkPropertyMetadata( int.MaxValue ) );
MinimumProperty.OverrideMetadata( typeof( IntegerUpDown ), new FrameworkPropertyMetadata( int.MinValue ) );
UpdateMetadata( typeof( IntegerUpDown ), 0, 1, int.MinValue, int.MaxValue );
}
#endregion //Constructors
#region Base Class Overrides
protected override int? CoerceValue( int? value )
{
if( value < Minimum )
return Minimum;
else if( value > Maximum )
return Maximum;
else
return value;
}
protected override void OnIncrement()
{
if( Value.HasValue )
Value += Increment;
else
Value = DefaultValue;
}
protected override void OnDecrement()
public IntegerUpDown()
: base( Int32.Parse, Decimal.ToInt32 )
{
if( Value.HasValue )
Value -= Increment;
else
Value = DefaultValue;
}
protected override int? ConvertTextToValue( string text )
{
int? result = null;
if( String.IsNullOrEmpty( text ) )
return result;
try
{
//don't know why someone would format an integer as %, but just in case they do.
result = FormatString.Contains( "P" ) ? Decimal.ToInt32( ParsePercent( text, CultureInfo ) ) : ParseInt( text, CultureInfo );
result = CoerceValue( result );
}
catch
{
Text = ConvertValueToText();
return Value;
}
return result;
}
protected override string ConvertValueToText()
{
if( Value == null )
return string.Empty;
#endregion //Constructors
return Value.Value.ToString( FormatString, CultureInfo );
}
#region Base Class Overrides
protected override void SetValidSpinDirection()
protected override int IncrementValue( int value, int increment )
{
ValidSpinDirections validDirections = ValidSpinDirections.None;
if( Value < Maximum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( Value > Minimum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
return value + increment;
}
protected override void ValidateValue( int? value )
protected override int DecrementValue( int value, int increment )
{
if( value < Minimum )
Value = Minimum;
else if( value > Maximum )
Value = Maximum;
return value - increment;
}
#endregion //Base Class Overrides

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/LongUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class LongUpDown : CommonNumericUpDown<long>
{
#region Constructors
static LongUpDown()
{
UpdateMetadata( typeof( LongUpDown ), default( long ), 1L, long.MinValue, long.MaxValue );
}
public LongUpDown()
: base( Int64.Parse, Decimal.ToInt64 )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override long IncrementValue( long value, long increment )
{
return value + increment;
}
protected override long DecrementValue( long value, long increment )
{
return value - increment;
}
#endregion //Base Class Overrides
}
}

15
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/NumericUpDown.cs

@ -171,21 +171,6 @@ namespace Xceed.Wpf.Toolkit
#region Methods
protected static decimal ParseDecimal( string text, IFormatProvider cultureInfo )
{
return Decimal.Parse( text, NumberStyles.Any, cultureInfo );
}
protected static double ParseDouble( string text, IFormatProvider cultureInfo )
{
return Double.Parse( text, NumberStyles.Any, cultureInfo );
}
protected static int ParseInt( string text, IFormatProvider cultureInfo )
{
return Int32.Parse( text, NumberStyles.Any, cultureInfo );
}
protected static decimal ParsePercent( string text, IFormatProvider cultureInfo )
{
NumberFormatInfo info = NumberFormatInfo.GetInstance( cultureInfo );

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/SByteUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
internal class SByteUpDown : CommonNumericUpDown<sbyte>
{
#region Constructors
static SByteUpDown()
{
UpdateMetadata( typeof( SByteUpDown ), default( sbyte ), ( sbyte )1, sbyte.MinValue, sbyte.MaxValue );
}
public SByteUpDown()
: base( sbyte.Parse, Decimal.ToSByte )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override sbyte IncrementValue( sbyte value, sbyte increment )
{
return ( sbyte )( value + increment );
}
protected override sbyte DecrementValue( sbyte value, sbyte increment )
{
return ( sbyte )( value - increment );
}
#endregion //Base Class Overrides
}
}

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ShortUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class ShortUpDown : CommonNumericUpDown<short>
{
#region Constructors
static ShortUpDown()
{
UpdateMetadata( typeof( ShortUpDown ), default( short ), ( short )1, short.MinValue, short.MaxValue );
}
public ShortUpDown()
: base( Int16.Parse, Decimal.ToInt16 )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override short IncrementValue( short value, short increment )
{
return ( short )( value + increment );
}
protected override short DecrementValue( short value, short increment )
{
return ( short )( value - increment );
}
#endregion //Base Class Overrides
}
}

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/SingleUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
public class SingleUpDown : CommonNumericUpDown<float>
{
#region Constructors
static SingleUpDown()
{
UpdateMetadata( typeof( SingleUpDown ), default( float ), 1f, float.MinValue, float.MaxValue );
}
public SingleUpDown()
: base( Single.Parse, Decimal.ToSingle )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override float IncrementValue( float value, float increment )
{
return value + increment;
}
protected override float DecrementValue( float value, float increment )
{
return value - increment;
}
#endregion //Base Class Overrides
}
}

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/UIntegerUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
internal class UIntegerUpDown : CommonNumericUpDown<uint>
{
#region Constructors
static UIntegerUpDown()
{
UpdateMetadata( typeof( UIntegerUpDown ), default( uint ), ( uint )1, uint.MinValue, uint.MaxValue );
}
public UIntegerUpDown()
: base( uint.Parse, Decimal.ToUInt32 )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override uint IncrementValue( uint value, uint increment )
{
return ( uint )( value + increment );
}
protected override uint DecrementValue( uint value, uint increment )
{
return ( uint )( value - increment );
}
#endregion //Base Class Overrides
}
}

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ULongUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
internal class ULongUpDown : CommonNumericUpDown<ulong>
{
#region Constructors
static ULongUpDown()
{
UpdateMetadata( typeof( ULongUpDown ), default( ulong ), ( ulong )1, ulong.MinValue, ulong.MaxValue );
}
public ULongUpDown()
: base( ulong.Parse, Decimal.ToUInt64 )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override ulong IncrementValue( ulong value, ulong increment )
{
return ( ulong )( value + increment );
}
protected override ulong DecrementValue( ulong value, ulong increment )
{
return ( ulong )( value - increment );
}
#endregion //Base Class Overrides
}
}

55
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Implementation/UShortUpDown.cs

@ -0,0 +1,55 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Windows;
namespace Xceed.Wpf.Toolkit
{
internal class UShortUpDown : CommonNumericUpDown<ushort>
{
#region Constructors
static UShortUpDown()
{
UpdateMetadata( typeof( UShortUpDown ), default( ushort ), ( ushort )1, ushort.MinValue, ushort.MaxValue );
}
public UShortUpDown()
: base( ushort.Parse, Decimal.ToUInt16 )
{
}
#endregion //Constructors
#region Base Class Overrides
protected override ushort IncrementValue( ushort value, ushort increment )
{
return ( ushort )( value + increment );
}
protected override ushort DecrementValue( ushort value, ushort increment )
{
return ( ushort )( value - increment );
}
#endregion //Base Class Overrides
}
}

67
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/NumericUpDown/Themes/Generic.xaml

@ -20,6 +20,7 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit"
xmlns:prim="clr-namespace:Xceed.Wpf.Toolkit.Primitives"
xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters">
<conv:InverseBoolConverter x:Key="InverseBoolConverter" />
@ -28,13 +29,15 @@
<ContentControl Content="{Binding}" Foreground="Gray" Focusable="False" />
</DataTemplate>
<Style x:Key="NumericUpDown" TargetType="Control">
<Style x:Key="NumericUpDown" TargetType="{x:Type prim:InputBase}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="WatermarkTemplate" Value="{StaticResource DefaultWatermarkTemplate}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Control">
@ -44,7 +47,7 @@
BorderThickness="{TemplateBinding BorderThickness}"
AllowSpin="{Binding AllowSpin, RelativeSource={RelativeSource TemplatedParent}}"
ShowButtonSpinner="{Binding ShowButtonSpinner, RelativeSource={RelativeSource TemplatedParent}}">
<local:WatermarkTextBox x:Name="PART_TextBox"
<local:WatermarkTextBox x:Name="PART_TextBox"
BorderThickness="0"
Background="{TemplateBinding Background}"
ContextMenu="{TemplateBinding ContextMenu}"
@ -63,11 +66,10 @@
TextAlignment="{Binding TextAlignment, RelativeSource={RelativeSource TemplatedParent}}"
TextWrapping="NoWrap"
TabIndex="{TemplateBinding TabIndex}"
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}, UpdateSourceTrigger=PropertyChanged}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Watermark="{Binding Watermark, RelativeSource={RelativeSource TemplatedParent}}"
WatermarkTemplate="{Binding WatermarkTemplate, RelativeSource={RelativeSource TemplatedParent}}" />
</local:ButtonSpinner>
</local:ButtonSpinner>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
@ -81,28 +83,57 @@
<!-- =============================================================================== -->
<!-- DecimalUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:DecimalUpDown}" BasedOn="{StaticResource NumericUpDown}">
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="WatermarkTemplate" Value="{StaticResource DefaultWatermarkTemplate}" />
</Style>
<Style TargetType="{x:Type local:DecimalUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- DoubleUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:DoubleUpDown}" BasedOn="{StaticResource NumericUpDown}">
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="WatermarkTemplate" Value="{StaticResource DefaultWatermarkTemplate}" />
</Style>
<Style TargetType="{x:Type local:DoubleUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- IntegerUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:IntegerUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- ShortUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:ShortUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- LongUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:LongUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- ByteUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:ByteUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- SingleUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:SingleUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- SByteUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:SByteUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- UIntegerUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:UIntegerUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- ULongUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:ULongUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<!-- =============================================================================== -->
<!-- UShortUpDown -->
<!-- =============================================================================== -->
<Style TargetType="{x:Type local:UShortUpDown}" BasedOn="{StaticResource NumericUpDown}" />
<Style TargetType="{x:Type local:IntegerUpDown}" BasedOn="{StaticResource NumericUpDown}">
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="WatermarkTemplate" Value="{StaticResource DefaultWatermarkTemplate}" />
</Style>
</ResourceDictionary>

726
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Obselete/MaskedTextBox/Implementation/MaskedTextBox.cs

@ -0,0 +1,726 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace Xceed.Wpf.Toolkit.Obselete
{
[Obsolete("Legacy implementation of MaskedTextBox. Use Xceed.Wpf.Toolkit.MaskedTextBox instead", false)]
public class MaskedTextBox : TextBox
{
#region Members
/// <summary>
/// Flags if the Text and Value properties are in the process of being sync'd
/// </summary>
private bool _isSyncingTextAndValueProperties;
private bool _isInitialized;
private bool _convertExceptionOccurred = false;
#endregion //Members
#region Properties
protected MaskedTextProvider MaskProvider
{
get;
set;
}
#region IncludePrompt
public static readonly DependencyProperty IncludePromptProperty = DependencyProperty.Register( "IncludePrompt", typeof( bool ), typeof( MaskedTextBox ), new UIPropertyMetadata( false, OnIncludePromptPropertyChanged ) );
public bool IncludePrompt
{
get
{
return ( bool )GetValue( IncludePromptProperty );
}
set
{
SetValue( IncludePromptProperty, value );
}
}
private static void OnIncludePromptPropertyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if( maskedTextBox != null )
maskedTextBox.OnIncludePromptChanged( ( bool )e.OldValue, ( bool )e.NewValue );
}
protected virtual void OnIncludePromptChanged( bool oldValue, bool newValue )
{
ResolveMaskProvider( Mask );
}
#endregion //IncludePrompt
#region IncludeLiterals
public static readonly DependencyProperty IncludeLiteralsProperty = DependencyProperty.Register( "IncludeLiterals", typeof( bool ), typeof( MaskedTextBox ), new UIPropertyMetadata( true, OnIncludeLiteralsPropertyChanged ) );
public bool IncludeLiterals
{
get
{
return ( bool )GetValue( IncludeLiteralsProperty );
}
set
{
SetValue( IncludeLiteralsProperty, value );
}
}
private static void OnIncludeLiteralsPropertyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if( maskedTextBox != null )
maskedTextBox.OnIncludeLiteralsChanged( ( bool )e.OldValue, ( bool )e.NewValue );
}
protected virtual void OnIncludeLiteralsChanged( bool oldValue, bool newValue )
{
ResolveMaskProvider( Mask );
}
#endregion //IncludeLiterals
#region Mask
public static readonly DependencyProperty MaskProperty = DependencyProperty.Register( "Mask", typeof( string ), typeof( MaskedTextBox ), new UIPropertyMetadata( "<>", OnMaskPropertyChanged ) );
public string Mask
{
get
{
return ( string )GetValue( MaskProperty );
}
set
{
SetValue( MaskProperty, value );
}
}
private static void OnMaskPropertyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if( maskedTextBox != null )
maskedTextBox.OnMaskChanged( ( string )e.OldValue, ( string )e.NewValue );
}
protected virtual void OnMaskChanged( string oldValue, string newValue )
{
ResolveMaskProvider( newValue );
UpdateText( 0 );
}
#endregion //Mask
#region PromptChar
public static readonly DependencyProperty PromptCharProperty = DependencyProperty.Register( "PromptChar", typeof( char ), typeof( MaskedTextBox ), new UIPropertyMetadata( '_', OnPromptCharChanged ) );
public char PromptChar
{
get
{
return ( char )GetValue( PromptCharProperty );
}
set
{
SetValue( PromptCharProperty, value );
}
}
private static void OnPromptCharChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if( maskedTextBox != null )
maskedTextBox.OnPromptCharChanged( ( char )e.OldValue, ( char )e.NewValue );
}
protected virtual void OnPromptCharChanged( char oldValue, char newValue )
{
ResolveMaskProvider( Mask );
}
#endregion //PromptChar
#region SelectAllOnGotFocus
public static readonly DependencyProperty SelectAllOnGotFocusProperty = DependencyProperty.Register( "SelectAllOnGotFocus", typeof( bool ), typeof( MaskedTextBox ), new PropertyMetadata( false ) );
public bool SelectAllOnGotFocus
{
get
{
return ( bool )GetValue( SelectAllOnGotFocusProperty );
}
set
{
SetValue( SelectAllOnGotFocusProperty, value );
}
}
#endregion //SelectAllOnGotFocus
#region Text
private static void OnTextChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox inputBase = o as MaskedTextBox;
if( inputBase != null )
inputBase.OnTextChanged( ( string )e.OldValue, ( string )e.NewValue );
}
protected virtual void OnTextChanged( string oldValue, string newValue )
{
if( _isInitialized )
SyncTextAndValueProperties( MaskedTextBox.TextProperty, newValue );
}
#endregion //Text
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( MaskedTextBox ), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnValueChanged ) );
public object Value
{
get
{
return ( object )GetValue( ValueProperty );
}
set
{
SetValue( ValueProperty, value );
}
}
private static void OnValueChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if( maskedTextBox != null )
maskedTextBox.OnValueChanged( ( object )e.OldValue, ( object )e.NewValue );
}
protected virtual void OnValueChanged( object oldValue, object newValue )
{
if( _isInitialized )
SyncTextAndValueProperties( MaskedTextBox.ValueProperty, newValue );
RoutedPropertyChangedEventArgs<object> args = new RoutedPropertyChangedEventArgs<object>( oldValue, newValue );
args.RoutedEvent = MaskedTextBox.ValueChangedEvent;
RaiseEvent( args );
}
#endregion //Value
#region ValueType
public static readonly DependencyProperty ValueTypeProperty = DependencyProperty.Register( "ValueType", typeof( Type ), typeof( MaskedTextBox ), new UIPropertyMetadata( typeof( String ), OnValueTypeChanged ) );
public Type ValueType
{
get
{
return ( Type )GetValue( ValueTypeProperty );
}
set
{
SetValue( ValueTypeProperty, value );
}
}
private static void OnValueTypeChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if( maskedTextBox != null )
maskedTextBox.OnValueTypeChanged( ( Type )e.OldValue, ( Type )e.NewValue );
}
protected virtual void OnValueTypeChanged( Type oldValue, Type newValue )
{
if( _isInitialized )
SyncTextAndValueProperties( MaskedTextBox.TextProperty, Text );
}
#endregion //ValueType
#endregion //Properties
#region Constructors
static MaskedTextBox()
{
TextProperty.OverrideMetadata( typeof( MaskedTextBox ), new FrameworkPropertyMetadata( OnTextChanged ) );
}
public MaskedTextBox()
{
CommandBindings.Add( new CommandBinding( ApplicationCommands.Paste, Paste ) ); //handle paste
CommandBindings.Add( new CommandBinding( ApplicationCommands.Cut, null, CanCut ) ); //surpress cut
}
#endregion //Constructors
#region Base Class Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
ResolveMaskProvider( Mask );
UpdateText( 0 );
}
protected override void OnInitialized( EventArgs e )
{
base.OnInitialized( e );
if( !_isInitialized )
{
_isInitialized = true;
SyncTextAndValueProperties( ValueProperty, Value );
}
}
protected override void OnGotKeyboardFocus( KeyboardFocusChangedEventArgs e )
{
if( SelectAllOnGotFocus )
{
SelectAll();
}
base.OnGotKeyboardFocus( e );
}
protected override void OnPreviewKeyDown( KeyEventArgs e )
{
if( !e.Handled )
{
HandlePreviewKeyDown( e );
}
base.OnPreviewKeyDown( e );
}
protected override void OnPreviewTextInput( TextCompositionEventArgs e )
{
if( !e.Handled )
{
HandlePreviewTextInput( e );
}
base.OnPreviewTextInput( e );
}
#endregion //Base Class Overrides
#region Events
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent( "ValueChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<object> ), typeof( MaskedTextBox ) );
public event RoutedPropertyChangedEventHandler<object> ValueChanged
{
add
{
AddHandler( ValueChangedEvent, value );
}
remove
{
RemoveHandler( ValueChangedEvent, value );
}
}
#endregion //Events
#region Methods
#region Private
private void UpdateText()
{
UpdateText( SelectionStart );
}
private void UpdateText( int position )
{
MaskedTextProvider provider = MaskProvider;
if( provider == null )
throw new InvalidOperationException();
Text = provider.ToDisplayString();
SelectionLength = 0;
SelectionStart = position;
}
private int GetNextCharacterPosition( int startPosition )
{
int position = MaskProvider.FindEditPositionFrom( startPosition, true );
return position == -1 ? startPosition : position;
}
private void ResolveMaskProvider( string mask )
{
//do not create a mask provider if the Mask is empty, which can occur if the IncludePrompt and IncludeLiterals properties
//are set prior to the Mask.
if( String.IsNullOrEmpty( mask ) )
return;
MaskProvider = new MaskedTextProvider( mask )
{
IncludePrompt = this.IncludePrompt,
IncludeLiterals = this.IncludeLiterals,
PromptChar = this.PromptChar,
ResetOnSpace = false //should make this a property
};
}
private object ConvertTextToValue( string text )
{
object convertedValue = null;
Type dataType = ValueType;
string valueToConvert = MaskProvider.ToString().Trim();
try
{
if( valueToConvert.GetType() == dataType || dataType.IsInstanceOfType( valueToConvert ) )
{
convertedValue = valueToConvert;
}
#if !VS2008
else if( String.IsNullOrWhiteSpace( valueToConvert ) )
{
convertedValue = Activator.CreateInstance( dataType );
}
#else
else if ( String.IsNullOrEmpty( valueToConvert ) )
{
convertedValue = Activator.CreateInstance( dataType );
}
#endif
else if( null == convertedValue && valueToConvert is IConvertible )
{
convertedValue = Convert.ChangeType( valueToConvert, dataType );
}
}
catch
{
//if an excpetion occurs revert back to original value
_convertExceptionOccurred = true;
return Value;
}
return convertedValue;
}
private string ConvertValueToText( object value )
{
if( value == null )
value = string.Empty;
if( _convertExceptionOccurred )
{
value = Value;
_convertExceptionOccurred = false;
}
//I have only seen this occur while in Blend, but we need it here so the Blend designer doesn't crash.
if( MaskProvider == null )
return value.ToString();
MaskProvider.Set( value.ToString() );
return MaskProvider.ToDisplayString();
}
private void SyncTextAndValueProperties( DependencyProperty p, object newValue )
{
//prevents recursive syncing properties
if( _isSyncingTextAndValueProperties )
return;
_isSyncingTextAndValueProperties = true;
//this only occures when the user typed in the value
if( MaskedTextBox.TextProperty == p )
{
if( newValue != null )
SetValue( MaskedTextBox.ValueProperty, ConvertTextToValue( newValue.ToString() ) );
}
SetValue( MaskedTextBox.TextProperty, ConvertValueToText( newValue ) );
_isSyncingTextAndValueProperties = false;
}
private void HandlePreviewTextInput( TextCompositionEventArgs e )
{
if( !IsReadOnly )
{
this.InsertText( e.Text );
}
e.Handled = true;
}
private void HandlePreviewKeyDown( KeyEventArgs e )
{
if( e.Key == Key.Delete )
{
e.Handled = IsReadOnly
|| HandleKeyDownDelete();
}
else if( e.Key == Key.Back )
{
e.Handled = IsReadOnly
|| HandleKeyDownBack();
}
else if( e.Key == Key.Space )
{
if( !IsReadOnly )
{
InsertText( " " );
}
e.Handled = true;
}
else if( e.Key == Key.Return || e.Key == Key.Enter )
{
if( !IsReadOnly && AcceptsReturn )
{
this.InsertText( "\r" );
}
// We don't want the OnPreviewTextInput to be triggered for the Return/Enter key
// when it is not accepted.
e.Handled = true;
}
else if( e.Key == Key.Escape )
{
// We don't want the OnPreviewTextInput to be triggered at all for the Escape key.
e.Handled = true;
}
else if( e.Key == Key.Tab )
{
if( AcceptsTab )
{
if( !IsReadOnly )
{
this.InsertText( "\t" );
}
e.Handled = true;
}
}
}
private bool HandleKeyDownDelete()
{
ModifierKeys modifiers = Keyboard.Modifiers;
bool handled = true;
if( modifiers == ModifierKeys.None )
{
if( !RemoveSelectedText() )
{
int position = SelectionStart;
if( position < Text.Length )
{
RemoveText( position, 1 );
UpdateText( position );
}
}
else
{
UpdateText();
}
}
else if( modifiers == ModifierKeys.Control )
{
if( !RemoveSelectedText() )
{
int position = SelectionStart;
RemoveTextToEnd( position );
UpdateText( position );
}
else
{
UpdateText();
}
}
else if( modifiers == ModifierKeys.Shift )
{
if( RemoveSelectedText() )
{
UpdateText();
}
else
{
handled = false;
}
}
else
{
handled = false;
}
return handled;
}
private bool HandleKeyDownBack()
{
ModifierKeys modifiers = Keyboard.Modifiers;
bool handled = true;
if( modifiers == ModifierKeys.None || modifiers == ModifierKeys.Shift )
{
if( !RemoveSelectedText() )
{
int position = SelectionStart;
if( position > 0 )
{
int newPosition = position - 1;
RemoveText( newPosition, 1 );
UpdateText( newPosition );
}
}
else
{
UpdateText();
}
}
else if( modifiers == ModifierKeys.Control )
{
if( !RemoveSelectedText() )
{
RemoveTextFromStart( SelectionStart );
UpdateText( 0 );
}
else
{
UpdateText();
}
}
else
{
handled = false;
}
return handled;
}
private void InsertText( string text )
{
int position = SelectionStart;
MaskedTextProvider provider = MaskProvider;
bool textRemoved = this.RemoveSelectedText();
position = GetNextCharacterPosition( position );
if( !textRemoved && Keyboard.IsKeyToggled( Key.Insert ) )
{
if( provider.Replace( text, position ) )
{
position += text.Length;
}
}
else
{
if( provider.InsertAt( text, position ) )
{
position += text.Length;
}
}
position = GetNextCharacterPosition( position );
this.UpdateText( position );
}
private void RemoveTextFromStart( int endPosition )
{
RemoveText( 0, endPosition );
}
private void RemoveTextToEnd( int startPosition )
{
RemoveText( startPosition, Text.Length - startPosition );
}
private void RemoveText( int position, int length )
{
if( length == 0 )
return;
MaskProvider.RemoveAt( position, position + length - 1 );
}
private bool RemoveSelectedText()
{
int length = SelectionLength;
if( length == 0 )
return false;
int position = SelectionStart;
return MaskProvider.RemoveAt( position, position + length - 1 );
}
#endregion //Private
#endregion //Methods
#region Commands
private void Paste( object sender, RoutedEventArgs e )
{
if( IsReadOnly )
return;
object data = Clipboard.GetData( DataFormats.Text );
if( data != null )
{
string text = data.ToString().Trim();
if( text.Length > 0 )
{
int position = SelectionStart;
MaskProvider.Set( text );
UpdateText( position );
}
}
}
private void CanCut( object sender, CanExecuteRoutedEventArgs e )
{
e.CanExecute = false;
e.Handled = true;
}
#endregion //Commands
}
}

2
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs

@ -75,6 +75,8 @@ using System.Windows.Markup;
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Core.Converters" )]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Core.Input" )]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Core.Utilities")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Chromes")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Primitives")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.PropertyGrid")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.PropertyGrid.Attributes")]

92
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/SelectedObjectConverter.cs

@ -0,0 +1,92 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Data;
using System.Globalization;
using System.ComponentModel;
using System.Windows;
using System.Reflection;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Converters
{
public class SelectedObjectConverter : IValueConverter
{
private const string ValidParameterMessage = @"parameter must be one of the following strings: 'Type', 'TypeName'";
#region IValueConverter Members
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
{
if( parameter == null )
throw new ArgumentNullException( "parameter" );
if( !( parameter is string ) )
throw new ArgumentException( SelectedObjectConverter.ValidParameterMessage );
if( this.CompareParam(parameter, "Type") )
{
return this.ConvertToType( value, culture );
}
else if( this.CompareParam( parameter, "TypeName" ) )
{
return this.ConvertToTypeName( value, culture );
}
else
{
throw new ArgumentException( SelectedObjectConverter.ValidParameterMessage );
}
}
private bool CompareParam(object parameter, string parameterValue )
{
return string.Compare( ( string )parameter, parameterValue, true ) == 0;
}
private object ConvertToType( object value, CultureInfo culture )
{
return ( value != null )
? value.GetType()
: null;
}
private object ConvertToTypeName( object value, CultureInfo culture )
{
if( value == null )
return string.Empty;
Type newType = value.GetType();
DisplayNameAttribute displayNameAttribute = newType.GetCustomAttributes( false ).OfType<DisplayNameAttribute>().FirstOrDefault();
return (displayNameAttribute == null)
? newType.Name
: displayNameAttribute.DisplayName;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
{
throw new NotImplementedException();
}
#endregion
}
}

52
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/UpDownEditors.cs

@ -0,0 +1,52 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using Xceed.Wpf.Toolkit.Primitives;
using System;
namespace Xceed.Wpf.Toolkit.PropertyGrid.Editors
{
public class UpDownEditor<TEditor, TType> : TypeEditor<TEditor> where TEditor : UpDownBase<TType>, new()
{
protected override void SetControlProperties()
{
Editor.BorderThickness = new System.Windows.Thickness( 0 );
}
protected override void SetValueDependencyProperty()
{
ValueProperty = UpDownBase<TType>.ValueProperty;
}
}
public class ByteUpDownEditor : UpDownEditor<ByteUpDown, byte?> { }
public class DecimalUpDownEditor : UpDownEditor<DecimalUpDown, decimal?> { }
public class DoubleUpDownEditor : UpDownEditor<DoubleUpDown, double?> { }
public class IntegerUpDownEditor : UpDownEditor<IntegerUpDown, int?> { }
public class LongUpDownEditor : UpDownEditor<LongUpDown, long?> { }
public class ShortUpDownEditor : UpDownEditor<ShortUpDown, short?> { }
public class SingleUpDownEditor : UpDownEditor<SingleUpDown, float?> { }
public class DateTimeUpDownEditor : UpDownEditor<DateTimeUpDown, DateTime?> { }
}

36
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/IPropertyParent.cs

@ -0,0 +1,36 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal interface IPropertyParent
{
bool IsReadOnly { get; }
object ValueInstance { get; }
EditorDefinitionCollection EditorDefinitions { get; }
}
}

344
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs

@ -30,20 +30,23 @@ using Xceed.Wpf.Toolkit.PropertyGrid.Commands;
using System.Collections.Specialized;
using System.Windows.Media;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
[TemplatePart( Name = PART_DragThumb, Type = typeof( Thumb ) )]
public class PropertyGrid : Control, ISupportInitialize
public class PropertyGrid : Control, ISupportInitialize, IPropertyParent
{
private const string PART_DragThumb = "PART_DragThumb";
#region Members
private Thumb _dragThumb;
private List<PropertyItem> _propertyItemsCache;
private bool _hasPendingSelectedObjectChanged;
private int _initializationCount;
private PropertyItemCollection _properties;
private PropertyDefinitionCollection _propertyDefinitions;
private EditorDefinitionCollection _editorDefinitions;
#endregion //Members
@ -68,7 +71,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region AutoGenerateProperties
public static readonly DependencyProperty AutoGeneratePropertiesProperty = DependencyProperty.Register( "AutoGenerateProperties", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true ) );
public static readonly DependencyProperty AutoGeneratePropertiesProperty = DependencyProperty.Register( "AutoGenerateProperties", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true, OnAutoGeneratePropertiesChanged ) );
public bool AutoGenerateProperties
{
get
@ -81,8 +84,16 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
}
}
private static void OnAutoGeneratePropertiesChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
( ( PropertyGrid )o ).UpdateProperties( true );
}
#endregion //AutoGenerateProperties
#region ShowSummary
public static readonly DependencyProperty ShowSummaryProperty = DependencyProperty.Register( "ShowSummary", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( true ) );
@ -102,26 +113,20 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region EditorDefinitions
public static readonly DependencyProperty EditorDefinitionsProperty = DependencyProperty.Register( "EditorDefinitions", typeof( EditorDefinitionCollection ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnEditorDefinitionsChanged) );
public EditorDefinitionCollection EditorDefinitions
{
get
{
return ( EditorDefinitionCollection )GetValue( EditorDefinitionsProperty );
return _editorDefinitions;
}
set
{
SetValue( EditorDefinitionsProperty, value );
EditorDefinitionCollection oldValue = _editorDefinitions;
_editorDefinitions = value;
this.OnEditorDefinitionsChanged( oldValue, value );
}
}
private static void OnEditorDefinitionsChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyGrid propertyGrid = o as PropertyGrid;
if( propertyGrid != null )
propertyGrid.OnEditorDefinitionsChanged( ( EditorDefinitionCollection )e.OldValue, ( EditorDefinitionCollection )e.NewValue );
}
protected virtual void OnEditorDefinitionsChanged( EditorDefinitionCollection oldValue, EditorDefinitionCollection newValue )
{
if( oldValue != null )
@ -130,7 +135,12 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
if( newValue != null )
newValue.CollectionChanged += new NotifyCollectionChangedEventHandler( OnEditorDefinitionsCollectionChanged );
RefreshPropertyGrid();
UpdateProperties( true );
}
private void OnEditorDefinitionsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
UpdateProperties( true );
}
#endregion //EditorDefinitions
@ -159,8 +169,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnFilterChanged( string oldValue, string newValue )
{
if( Properties != null )
Properties.Filter( newValue );
Properties.Filter( newValue );
}
#endregion //Filter
@ -206,7 +215,9 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnIsCategorizedChanged( bool oldValue, bool newValue )
{
InitializePropertyGrid( newValue );
this.UpdateProperties( false );
this.UpdateThumb();
}
#endregion //IsCategorized
@ -235,23 +246,19 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnNameColumnWidthChanged( double oldValue, double newValue )
{
( ( TranslateTransform )_dragThumb.RenderTransform ).X = newValue;
if( _dragThumb != null )
( ( TranslateTransform )_dragThumb.RenderTransform ).X = newValue;
}
#endregion //NameColumnWidth
#region Properties
private static readonly DependencyPropertyKey PropertiesPropertyKey = DependencyProperty.RegisterReadOnly( "Properties", typeof( PropertyItemCollection ), typeof( PropertyGrid ), new UIPropertyMetadata( null ) );
public PropertyItemCollection Properties
{
get
{
return ( PropertyItemCollection )GetValue( PropertiesPropertyKey.DependencyProperty );
}
private set
{
SetValue( PropertiesPropertyKey, value );
return _properties;
}
}
@ -259,26 +266,20 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region PropertyDefinitions
public static readonly DependencyProperty PropertyDefinitionsProperty = DependencyProperty.Register( "PropertyDefinitions", typeof( PropertyDefinitionCollection ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnPropertyDefinitionsChanged ) );
public PropertyDefinitionCollection PropertyDefinitions
{
get
{
return ( PropertyDefinitionCollection )GetValue( PropertyDefinitionsProperty );
return _propertyDefinitions;
}
set
{
SetValue( PropertyDefinitionsProperty, value );
PropertyDefinitionCollection oldValue = _propertyDefinitions;
_propertyDefinitions = value;
this.OnPropertyDefinitionsChanged( oldValue, value );
}
}
private static void OnPropertyDefinitionsChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyGrid propertyGrid = o as PropertyGrid;
if( propertyGrid != null )
propertyGrid.OnPropertyDefinitionsChanged( ( PropertyDefinitionCollection )e.OldValue, ( PropertyDefinitionCollection )e.NewValue );
}
protected virtual void OnPropertyDefinitionsChanged( PropertyDefinitionCollection oldValue, PropertyDefinitionCollection newValue )
{
if( oldValue != null )
@ -287,11 +288,45 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
if( newValue != null )
newValue.CollectionChanged += new NotifyCollectionChangedEventHandler( OnPropertyDefinitionsCollectionChanged );
RefreshPropertyGrid();
UpdateProperties( true );
}
private void OnPropertyDefinitionsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
UpdateProperties( true );
}
#endregion //PropertyDefinitions
#region IsReadOnly
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register( "IsReadOnly", typeof( bool ), typeof( PropertyGrid ), new UIPropertyMetadata( false, OnIsReadOnlyChanged ) );
public bool IsReadOnly
{
get
{
return ( bool )GetValue( IsReadOnlyProperty );
}
set
{
SetValue( IsReadOnlyProperty, value );
}
}
private static void OnIsReadOnlyChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyGrid propertyGrid = o as PropertyGrid;
if( propertyGrid != null )
{
foreach( PropertyItem propertyItem in propertyGrid.Properties )
{
propertyItem.Editor.IsEnabled = !propertyGrid.IsReadOnly;
}
}
}
#endregion //ReadOnly
#region SelectedObject
public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register( "SelectedObject", typeof( object ), typeof( PropertyGrid ), new UIPropertyMetadata( null, OnSelectedObjectChanged ) );
@ -317,20 +352,15 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnSelectedObjectChanged( object oldValue, object newValue )
{
// We do not want to process the change now if the grid is initializing (ie. BeginInit/EndInit).
_hasPendingSelectedObjectChanged = IsInitializing();
if( IsInitializing() )
return;
if( newValue == null )
ResetPropertyGrid();
else
if( _initializationCount != 0 )
{
SetSelectedObjectNameBinding( newValue );
SelectedObjectType = newValue.GetType();
_propertyItemsCache = GetObjectProperties( newValue );
InitializePropertyGrid( IsCategorized );
_hasPendingSelectedObjectChanged = true;
return;
}
this.UpdateProperties( true );
RaiseEvent( new RoutedPropertyChangedEventArgs<object>( oldValue, newValue, PropertyGrid.SelectedObjectChangedEvent ) );
}
#endregion //SelectedObject
@ -344,7 +374,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
return ( Type )GetValue( SelectedObjectTypeProperty );
}
private set
set
{
SetValue( SelectedObjectTypeProperty, value );
}
@ -359,13 +389,6 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnSelectedObjectTypeChanged( Type oldValue, Type newValue )
{
if( newValue == null )
SelectedObjectTypeName = string.Empty;
else
{
DisplayNameAttribute displayNameAttribute = newValue.GetCustomAttributes( false ).OfType<DisplayNameAttribute>().FirstOrDefault();
SelectedObjectTypeName = displayNameAttribute == null ? newValue.Name : displayNameAttribute.DisplayName;
}
}
#endregion //SelectedObjectType
@ -379,7 +402,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
return ( string )GetValue( SelectedObjectTypeNameProperty );
}
private set
set
{
SetValue( SelectedObjectTypeNameProperty, value );
}
@ -389,19 +412,31 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region SelectedObjectName
public static readonly DependencyProperty SelectedObjectNameProperty = DependencyProperty.Register( "SelectedObjectName", typeof( string ), typeof( PropertyGrid ), new UIPropertyMetadata( string.Empty, OnSelectedObjectNameChanged ) );
public static readonly DependencyProperty SelectedObjectNameProperty = DependencyProperty.Register( "SelectedObjectName", typeof( string ), typeof( PropertyGrid ), new UIPropertyMetadata( string.Empty, OnSelectedObjectNameChanged, OnCoerceSelectedObjectName ) );
public string SelectedObjectName
{
get
{
return ( string )GetValue( SelectedObjectNameProperty );
}
private set
set
{
SetValue( SelectedObjectNameProperty, value );
}
}
private static object OnCoerceSelectedObjectName( DependencyObject o, object baseValue )
{
PropertyGrid propertyGrid = o as PropertyGrid;
if( propertyGrid != null )
{
if( (propertyGrid.SelectedObject is FrameworkElement) && ( String.IsNullOrEmpty( ( String )baseValue ) ))
return "<no name>";
}
return baseValue;
}
private static void OnSelectedObjectNameChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
PropertyGrid propertyGrid = o as PropertyGrid;
@ -411,7 +446,6 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void SelectedObjectNameChanged( string oldValue, string newValue )
{
}
#endregion //SelectedObjectName
@ -443,10 +477,10 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
if( oldValue != null )
oldValue.IsSelected = false;
//if (newValue != null)
// newValue.IsSelected = true;
if( newValue != null )
newValue.IsSelected = true;
RaiseEvent( new RoutedEventArgs( PropertyGrid.SelectedPropertyItemChangedEvent, newValue ) );
RaiseEvent( new RoutedPropertyChangedEventArgs<PropertyItem>( oldValue, newValue, PropertyGrid.SelectedPropertyItemChangedEvent ) );
}
#endregion //SelectedPropertyItem
@ -530,8 +564,11 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
public PropertyGrid()
{
_properties = new PropertyItemCollection( new ObservableCollection<PropertyItem>() );
EditorDefinitions = new EditorDefinitionCollection();
PropertyDefinitions = new PropertyDefinitionCollection();
AddHandler( PropertyItem.ItemSelectionChangedEvent, new RoutedEventHandler( OnItemSelectionChanged ) );
CommandBindings.Add( new CommandBinding( PropertyGridCommands.ClearFilter, ClearFilter, CanClearFilter ) );
}
@ -560,6 +597,8 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
TranslateTransform _moveTransform = new TranslateTransform();
_moveTransform.X = NameColumnWidth;
_dragThumb.RenderTransform = _moveTransform;
this.UpdateThumb();
}
protected override void OnPreviewKeyDown( KeyEventArgs e )
@ -579,7 +618,23 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region Event Handlers
void DragThumb_DragDelta( object sender, DragDeltaEventArgs e )
private void OnItemSelectionChanged( object sender, RoutedEventArgs args )
{
PropertyItem item = ( PropertyItem )args.OriginalSource;
if( item.IsSelected )
{
SelectedPropertyItem = item;
}
else
{
if( object.ReferenceEquals( item, SelectedPropertyItem ) )
{
SelectedPropertyItem = null;
}
}
}
private void DragThumb_DragDelta( object sender, DragDeltaEventArgs e )
{
NameColumnWidth = Math.Max( 0, NameColumnWidth + e.HorizontalChange );
}
@ -602,123 +657,77 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region Methods
private void InitializePropertyGrid( bool isCategorized )
{
LoadProperties( isCategorized );
SetDragThumbMargin( isCategorized );
}
private void LoadProperties( bool isCategorized )
private void UpdateProperties( bool regenerateItems )
{
if( _propertyItemsCache == null )
return;
IEnumerable<PropertyItem> newProperties = null;
if( regenerateItems )
{
newProperties = this.GeneratePropertyItems( this.SelectedObject );
//clear any filters first
Filter = String.Empty;
string defaultPropertyName = PropertyGridUtilities.GetDefaultPropertyName( this.SelectedObject );
this.SelectedPropertyItem = newProperties.FirstOrDefault( ( prop ) => prop.Name.Equals( defaultPropertyName ) );
}
if( isCategorized )
Properties = PropertyGridUtilities.GetCategorizedProperties( _propertyItemsCache );
else
Properties = PropertyGridUtilities.GetAlphabetizedProperties( _propertyItemsCache );
Properties.Update( newProperties, IsCategorized, Filter );
}
private List<PropertyItem> GetObjectProperties( object instance )
private List<PropertyItem> GeneratePropertyItems(object instance)
{
var propertyItems = new List<PropertyItem>();
if( instance == null )
return propertyItems;
try
if( instance != null )
{
PropertyDescriptorCollection descriptors = PropertyGridUtilities.GetPropertyDescriptors( instance );
if( !AutoGenerateProperties )
try
{
List<PropertyDescriptor> specificProperties = new List<PropertyDescriptor>();
if( PropertyDefinitions != null )
PropertyDescriptorCollection descriptors = PropertyGridUtilities.GetPropertyDescriptors( instance );
if( !AutoGenerateProperties )
{
foreach( PropertyDefinition pd in PropertyDefinitions )
List<PropertyDescriptor> specificProperties = new List<PropertyDescriptor>();
if( PropertyDefinitions != null )
{
foreach( PropertyDescriptor descriptor in descriptors )
foreach( PropertyDefinition pd in PropertyDefinitions )
{
if( descriptor.Name == pd.Name )
foreach( PropertyDescriptor descriptor in descriptors )
{
specificProperties.Add( descriptor );
break;
if( descriptor.Name == pd.Name )
{
specificProperties.Add( descriptor );
break;
}
}
}
}
descriptors = new PropertyDescriptorCollection( specificProperties.ToArray() );
}
descriptors = new PropertyDescriptorCollection( specificProperties.ToArray() );
foreach( PropertyDescriptor descriptor in descriptors )
{
if( descriptor.IsBrowsable )
propertyItems.Add( PropertyGridUtilities.CreatePropertyItem( descriptor, this ) );
}
}
foreach( PropertyDescriptor descriptor in descriptors )
catch( Exception )
{
if( descriptor.IsBrowsable )
propertyItems.Add( PropertyGridUtilities.CreatePropertyItem( descriptor, instance, this, descriptor.Name ) );
//TODO: handle this some how
}
}
catch( Exception )
{
//TODO: handle this some how
}
return propertyItems;
}
private void SetSelectedObjectNameBinding( object selectedObject )
private void UpdateThumb()
{
if( selectedObject is FrameworkElement )
if( _dragThumb != null )
{
var binding = new Binding( "Name" );
binding.Source = selectedObject;
binding.Mode = BindingMode.OneWay;
BindingOperations.SetBinding( this, PropertyGrid.SelectedObjectNameProperty, binding );
if( IsCategorized )
_dragThumb.Margin = new Thickness( 6, 0, 0, 0 );
else
_dragThumb.Margin = new Thickness( -1, 0, 0, 0 );
}
}
private void SetDragThumbMargin( bool isCategorized )
{
if( _dragThumb == null )
return;
if( isCategorized )
_dragThumb.Margin = new Thickness( 6, 0, 0, 0 );
else
_dragThumb.Margin = new Thickness( -1, 0, 0, 0 );
}
private void ResetPropertyGrid()
{
SelectedObjectName = String.Empty;
SelectedObjectType = null;
_propertyItemsCache = null;
SelectedPropertyItem = null;
Properties = null;
}
private void OnEditorDefinitionsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
RefreshPropertyGrid();
}
private void OnPropertyDefinitionsCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
{
RefreshPropertyGrid();
}
private void RefreshPropertyGrid()
{
_propertyItemsCache = GetObjectProperties( SelectedObject );
InitializePropertyGrid( IsCategorized );
}
private bool IsInitializing()
{
return _initializationCount != 0;
}
/// <summary>
/// Updates all property values in the PropertyGrid with the data from the SelectedObject
/// </summary>
@ -747,8 +756,8 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
}
}
public static readonly RoutedEvent SelectedPropertyItemChangedEvent = EventManager.RegisterRoutedEvent( "SelectedPropertyItemChanged", RoutingStrategy.Bubble, typeof( RoutedEventHandler ), typeof( PropertyGrid ) );
public event RoutedEventHandler SelectedPropertyItemChanged
public static readonly RoutedEvent SelectedPropertyItemChangedEvent = EventManager.RegisterRoutedEvent( "SelectedPropertyItemChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<PropertyItem> ), typeof( PropertyGrid ) );
public event RoutedPropertyChangedEventHandler<PropertyItem> SelectedPropertyItemChanged
{
add
{
@ -760,6 +769,19 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
}
}
public static readonly RoutedEvent SelectedObjectChangedEvent = EventManager.RegisterRoutedEvent( "SelectedObjectChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<object> ), typeof( PropertyGrid ) );
public event RoutedPropertyChangedEventHandler<object> SelectedObjectChanged
{
add
{
AddHandler( SelectedObjectChangedEvent, value );
}
remove
{
RemoveHandler( SelectedObjectChangedEvent, value );
}
}
#endregion //Events
#region Interfaces
@ -786,12 +808,32 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
if( _hasPendingSelectedObjectChanged )
{
//This will update SelectedObject, Type, Name based on the actual config.
OnSelectedObjectChanged( SelectedObject, SelectedObject );
this.UpdateProperties( true );
_hasPendingSelectedObjectChanged = false;
}
}
#endregion
#region IPropertyParent Members
bool IPropertyParent.IsReadOnly
{
get { return this.IsReadOnly; }
}
object IPropertyParent.ValueInstance
{
get { return this.SelectedObject; }
}
EditorDefinitionCollection IPropertyParent.EditorDefinitions
{
get { return this.EditorDefinitions; }
}
#endregion
#endregion
}

85
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGridUtilities.cs

@ -34,34 +34,17 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
internal static T GetAttribute<T>( PropertyDescriptor property ) where T : Attribute
{
foreach( Attribute att in property.Attributes )
{
var tAtt = att as T;
if( tAtt != null )
return tAtt;
}
return null;
return property.Attributes.OfType<T>().FirstOrDefault();
}
internal static PropertyItemCollection GetAlphabetizedProperties( List<PropertyItem> propertyItems )
{
PropertyItemCollection propertyCollection = new PropertyItemCollection( propertyItems );
propertyCollection.SortBy( "DisplayName", ListSortDirection.Ascending );
return propertyCollection;
}
internal static PropertyItemCollection GetCategorizedProperties( List<PropertyItem> propertyItems )
internal static string GetDefaultPropertyName( object instance )
{
PropertyItemCollection propertyCollection = new PropertyItemCollection( propertyItems );
propertyCollection.GroupBy( "Category" );
propertyCollection.SortBy( "Category", ListSortDirection.Ascending );
propertyCollection.SortBy( "PropertyOrder", ListSortDirection.Ascending );
propertyCollection.SortBy( "DisplayName", ListSortDirection.Ascending );
return propertyCollection;
AttributeCollection attributes = TypeDescriptor.GetAttributes( instance );
DefaultPropertyAttribute defaultPropertyAttribute =( DefaultPropertyAttribute )attributes[ typeof( DefaultPropertyAttribute ) ];
return defaultPropertyAttribute != null ? defaultPropertyAttribute.Name : null;
}
internal static PropertyDescriptorCollection GetPropertyDescriptors( object instance )
{
PropertyDescriptorCollection descriptors;
@ -83,33 +66,31 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
return descriptors;
}
internal static PropertyItem CreatePropertyItem( PropertyDescriptor property, object instance, PropertyGrid grid, string bindingPath )
internal static PropertyItem CreatePropertyItem( PropertyDescriptor property, IPropertyParent propertyParent )
{
return CreatePropertyItem(property, instance, grid, bindingPath, 0);
return CreatePropertyItem( property, propertyParent, 0 );
}
internal static PropertyItem CreatePropertyItem( PropertyDescriptor property, object instance, PropertyGrid grid, string bindingPath, int level )
internal static PropertyItem CreatePropertyItem( PropertyDescriptor property, IPropertyParent propertyParent, int level )
{
PropertyItem propertyItem = new PropertyItem( instance, property, grid, bindingPath, level );
PropertyItem propertyItem = new PropertyItem( property, propertyParent, level );
var binding = new Binding( bindingPath )
var binding = new Binding( property.Name )
{
Source = instance,
Source = propertyParent.ValueInstance,
ValidatesOnExceptions = true,
ValidatesOnDataErrors = true,
Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay
};
propertyItem.SetBinding( PropertyItem.ValueProperty, binding );
propertyItem.Editor = PropertyGridUtilities.GetTypeEditor( propertyItem
, grid.EditorDefinitions
);
propertyItem.Editor = PropertyGridUtilities.GetTypeEditor( propertyItem, propertyParent.EditorDefinitions );
return propertyItem;
}
internal static FrameworkElement GetTypeEditor( PropertyItem propertyItem
, EditorDefinitionCollection editorDefinitions
)
internal static FrameworkElement GetTypeEditor(
PropertyItem propertyItem,
EditorDefinitionCollection editorDefinitions )
{
FrameworkElement editor = null;
@ -125,6 +106,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
if( editor == null )
editor = PropertyGridUtilities.CreateDefaultEditor( propertyItem );
editor.IsEnabled = !propertyItem.PropertyParent.IsReadOnly;
return editor;
}
@ -188,6 +170,22 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
editor = new DoubleUpDownEditor();
else if( propertyItem.PropertyType == typeof( int ) || propertyItem.PropertyType == typeof( int? ) )
editor = new IntegerUpDownEditor();
else if( propertyItem.PropertyType == typeof( short ) || propertyItem.PropertyType == typeof( short? ) )
editor = new ShortUpDownEditor();
else if( propertyItem.PropertyType == typeof( long ) || propertyItem.PropertyType == typeof( long? ) )
editor = new LongUpDownEditor();
else if( propertyItem.PropertyType == typeof( float ) || propertyItem.PropertyType == typeof( float? ) )
editor = new SingleUpDownEditor();
else if( propertyItem.PropertyType == typeof( byte ) || propertyItem.PropertyType == typeof( byte? ) )
editor = new ByteUpDownEditor();
else if( propertyItem.PropertyType == typeof( sbyte ) || propertyItem.PropertyType == typeof( sbyte? ) )
editor = new UpDownEditor<SByteUpDown,sbyte?>();
else if( propertyItem.PropertyType == typeof( uint ) || propertyItem.PropertyType == typeof( uint? ) )
editor = new UpDownEditor<UIntegerUpDown, uint?>();
else if( propertyItem.PropertyType == typeof( ulong ) || propertyItem.PropertyType == typeof( ulong? ) )
editor = new UpDownEditor<ULongUpDown, ulong?>();
else if( propertyItem.PropertyType == typeof( ushort ) || propertyItem.PropertyType == typeof( ushort? ) )
editor = new UpDownEditor<UShortUpDown, ushort?>();
else if( propertyItem.PropertyType == typeof( DateTime ) || propertyItem.PropertyType == typeof( DateTime? ) )
editor = new DateTimeUpDownEditor();
else if( ( propertyItem.PropertyType == typeof( Color ) ) )
@ -198,11 +196,16 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
editor = new TimeSpanEditor();
else if( propertyItem.PropertyType == typeof( FontFamily ) || propertyItem.PropertyType == typeof( FontWeight ) || propertyItem.PropertyType == typeof( FontStyle ) || propertyItem.PropertyType == typeof( FontStretch ) )
editor = new FontComboBoxEditor();
else if( propertyItem.PropertyType == typeof( object ) )
// If any type of object is possible in the property, default to the TextBoxEditor.
// Useful in some case (e.g., Button.Content).
// Can be reconsidered but was the legacy behavior on the PropertyGrid.
editor = new TextBoxEditor();
else
{
Type listType = CollectionEditor.GetListItemType(propertyItem.PropertyType);
Type listType = CollectionEditor.GetListItemType( propertyItem.PropertyType );
if(listType != null)
if( listType != null )
{
if( !listType.IsPrimitive && !listType.Equals( typeof( String ) ) )
editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.CollectionEditor();
@ -210,7 +213,15 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.PrimitiveTypeCollectionEditor();
}
else
editor = new TextBoxEditor();
{
// If the type is not supported, check if there is a converter that supports
// string conversion to the object type. Use TextBox in theses cases.
// Otherwise, return a TextBlock editor since no valid editor exists.
TypeConverter typeConverter = propertyItem.PropertyDescriptor.Converter;
editor = ( typeConverter != null && typeConverter.CanConvertFrom( typeof( string ) ) )
? ( ITypeEditor )new TextBoxEditor()
: ( ITypeEditor )new TextBlockEditor();
}
}
return editor.ResolveEditor( propertyItem );

282
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs

@ -28,50 +28,73 @@ using System.Windows.Input;
using System.Windows.Markup.Primitives;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using Xceed.Wpf.Toolkit.PropertyGrid.Commands;
using System.Collections.ObjectModel;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class PropertyItem : Control
public class PropertyItem : Control, INotifyPropertyChanged, IPropertyParent
{
#region Members
private DependencyPropertyDescriptor _dpDescriptor;
private MarkupObject _markupObject;
private readonly DependencyPropertyDescriptor _dpDescriptor;
private readonly MarkupObject _markupObject;
private readonly NotifyPropertyChangedHelper _propertyChangedHelper;
private string _displayName;
private string _description;
private string _category;
private int _categoryOrder;
private int _propertyOrder;
#endregion //Members
#region Properties
public string BindingPath
{
get;
private set;
}
#region Category
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register( "Category", typeof( string ), typeof( PropertyItem ), new UIPropertyMetadata( string.Empty ) );
public string Category
{
get
{
return ( string )GetValue( CategoryProperty );
return _category;
}
set
{
SetValue( CategoryProperty, value );
_propertyChangedHelper.HandleEqualityChanged( () => Category, ref _category, value );
}
}
#endregion //Category
#region CategoryOrder
public int CategoryOrder
{
get
{
return _categoryOrder;
}
set
{
_propertyChangedHelper.HandleEqualityChanged( () => CategoryOrder, ref _categoryOrder, value );
}
}
#endregion // CategoryOrder
#region Description
public string Description
{
get
{
return PropertyDescriptor.Description;
return _description;
}
set
{
_propertyChangedHelper.HandleEqualityChanged( () => Description, ref _description, value );
}
}
@ -79,16 +102,15 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region DisplayName
public static readonly DependencyProperty DisplayNameProperty = DependencyProperty.Register( "DisplayName", typeof( string ), typeof( PropertyItem ), new UIPropertyMetadata( null ) );
public string DisplayName
{
get
{
return ( string )GetValue( DisplayNameProperty );
return _displayName;
}
set
{
SetValue( DisplayNameProperty, value );
_propertyChangedHelper.HandleEqualityChanged( () => DisplayName, ref _displayName, value );
}
}
@ -129,18 +151,10 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region Instance
private object _instance;
public object Instance
{
get
{
return _instance;
}
private set
{
_instance = value;
_markupObject = MarkupWriter.GetMarkupObjectFor( _instance );
}
get;
private set;
}
#endregion //Instance
@ -154,7 +168,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
get
{
var dependencyObject = Instance as DependencyObject;
var dependencyObject = PropertyParent.ValueInstance as DependencyObject;
if( dependencyObject != null && _dpDescriptor != null )
return BindingOperations.GetBindingExpressionBase( dependencyObject, _dpDescriptor.DependencyProperty ) != null;
@ -203,7 +217,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnIsExpandedChanged( bool oldValue, bool newValue )
{
if( newValue && ( Properties == null || Properties.Count == 0 ) )
if( newValue && Properties.Count == 0 )
{
GetChildProperties();
}
@ -247,8 +261,10 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
public bool IsReadOnly
{
get;
private set;
get
{
return PropertyDescriptor.IsReadOnly;
}
}
#region IsSelected
@ -275,75 +291,66 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnIsSelectedChanged( bool oldValue, bool newValue )
{
if( newValue )
PropertyGrid.SelectedPropertyItem = this;
this.RaiseItemSelectionChangedEvent();
}
#endregion //IsSelected
#region Level
public static readonly DependencyProperty LevelProperty = DependencyProperty.Register( "Level", typeof( int ), typeof( PropertyItem ), new UIPropertyMetadata( 0 ) );
public int Level
{
get
{
return ( int )GetValue( LevelProperty );
}
set
{
SetValue( LevelProperty, value );
}
get;
private set;
}
#endregion //Level
#region Properties
public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register( "Properties", typeof( PropertyItemCollection ), typeof( PropertyItem ), new UIPropertyMetadata( null ) );
public PropertyItemCollection Properties
{
get
{
return ( PropertyItemCollection )GetValue( PropertiesProperty );
}
set
{
SetValue( PropertiesProperty, value );
}
get;
private set;
}
#endregion //Properties
#region PropertyDescriptor
private PropertyDescriptor _propertyDescriptor;
public PropertyDescriptor PropertyDescriptor
{
get
{
return _propertyDescriptor;
}
private set
{
_propertyDescriptor = value;
_dpDescriptor = DependencyPropertyDescriptor.FromProperty( _propertyDescriptor );
}
get;
private set;
}
#endregion //PropertyDescriptor
public PropertyGrid PropertyGrid
#region PropertyParent
internal IPropertyParent PropertyParent
{
get;
private set;
}
#endregion
#region PropertyOrder
public int PropertyOrder
{
get;
set;
} //maybe make a DP
get
{
return _propertyOrder;
}
set
{
_propertyChangedHelper.HandleEqualityChanged( () => PropertyOrder, ref _propertyOrder, value );
}
}
#endregion
#region PropertyType
@ -357,12 +364,16 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#endregion //PropertyType
#region ResetValueCommand
public ICommand ResetValueCommand
{
get;
private set;
}
#endregion
#region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( PropertyItem ), new UIPropertyMetadata( null, OnValueChanged ) );
@ -391,7 +402,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
if( IsInitialized )
{
PropertyGrid.RaiseEvent( new PropertyValueChangedEventArgs( PropertyGrid.PropertyValueChangedEvent, this, oldValue, newValue ) );
RaiseEvent( new PropertyValueChangedEventArgs( PropertyGrid.PropertyValueChangedEvent, this, oldValue, newValue ) );
}
}
@ -406,7 +417,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
get
{
var dependencyObject = Instance as DependencyObject;
var dependencyObject = PropertyParent.ValueInstance as DependencyObject;
if( _dpDescriptor != null && dependencyObject != null )
return DependencyPropertyHelper.GetValueSource( dependencyObject, _dpDescriptor.DependencyProperty ).BaseValueSource;
@ -418,6 +429,25 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#endregion //Properties
#region Events
public event PropertyChangedEventHandler PropertyChanged;
#region ItemSelectionChanged
internal static readonly RoutedEvent ItemSelectionChangedEvent = EventManager.RegisterRoutedEvent(
"ItemSelectedEvent", RoutingStrategy.Bubble, typeof( RoutedEventHandler ), typeof( PropertyItem ) );
// This method raises the Tap event
private void RaiseItemSelectionChangedEvent()
{
RaiseEvent( new RoutedEventArgs( PropertyItem.ItemSelectionChangedEvent ) );
}
#endregion
#endregion
#region Constructors
static PropertyItem()
@ -425,18 +455,26 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyItem ), new FrameworkPropertyMetadata( typeof( PropertyItem ) ) );
}
public PropertyItem( object instance, PropertyDescriptor property, PropertyGrid propertyGrid, string bindingPath, int level )
internal PropertyItem( PropertyDescriptor property, IPropertyParent propertyParent, int level )
{
_propertyChangedHelper = new NotifyPropertyChangedHelper( this, RaisePropertyChanged );
Properties = new PropertyItemCollection( new ObservableCollection<PropertyItem>() );
PropertyParent = propertyParent;
PropertyDescriptor = property;
PropertyGrid = propertyGrid;
Instance = instance;
BindingPath = bindingPath;
Level = level;
SetPropertyDescriptorProperties();
ResolveParenthesisPropertyName();
ResolveExpandableObject();
ResolvePropertyOrder();
Name = PropertyDescriptor.Name;
Category = PropertyDescriptor.Category;
CategoryOrder = 0;
Description = ResolveDescription();
DisplayName = ResolveDisplayName();
HasChildProperties = ResolveExpandableObject();
PropertyOrder = ResolvePropertyOrder();
_dpDescriptor = DependencyPropertyDescriptor.FromProperty( PropertyDescriptor );
_markupObject = MarkupWriter.GetMarkupObjectFor( PropertyParent.ValueInstance );
CommandBindings.Add( new CommandBinding( PropertyItemCommands.ResetValue, ExecuteResetValueCommand, CanExecuteResetValueCommand ) );
AddHandler( Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler( PropertyItem_PreviewMouseDown ), true );
@ -457,8 +495,8 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
private void ExecuteResetValueCommand( object sender, ExecutedRoutedEventArgs e )
{
if( PropertyDescriptor.CanResetValue( Instance ) )
PropertyDescriptor.ResetValue( Instance );
if( PropertyDescriptor.CanResetValue( PropertyParent.ValueInstance ) )
PropertyDescriptor.ResetValue( PropertyParent.ValueInstance );
//TODO: notify UI that the ValueSource may have changed to update the icon
}
@ -467,7 +505,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
bool canExecute = false;
if( PropertyDescriptor.CanResetValue( Instance ) && !PropertyDescriptor.IsReadOnly )
if( PropertyDescriptor.CanResetValue( PropertyParent.ValueInstance ) && !PropertyDescriptor.IsReadOnly )
{
canExecute = true;
}
@ -479,6 +517,14 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region Methods
private void RaisePropertyChanged( string propertyName )
{
if( this.PropertyChanged != null )
{
this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}
private void GetChildProperties()
{
if( Value == null )
@ -494,7 +540,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{
if( descriptor.IsBrowsable )
{
PropertyItem childPropertyItem = PropertyGridUtilities.CreatePropertyItem( descriptor, Instance, PropertyGrid, String.Format( "{0}.{1}", BindingPath, descriptor.Name ), Level + 1 );
PropertyItem childPropertyItem = PropertyGridUtilities.CreatePropertyItem( descriptor, this, Level + 1 );
propertyItems.Add( childPropertyItem );
}
}
@ -504,45 +550,89 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
//TODO: handle this some how
}
Properties = PropertyGridUtilities.GetAlphabetizedProperties( propertyItems );
Properties.Update( propertyItems, false, null );
}
private void ResolveParenthesisPropertyName()
private string ResolveDescription()
{
var attribute = PropertyGridUtilities.GetAttribute<ParenthesizePropertyNameAttribute>( PropertyDescriptor );
//We do not simply rely on the "Description" property of PropertyDescriptor
//since this value is cached bye PropertyDescriptor and the localized version
//(eg. LocalizedDescriptionAttribute) value can dynamicaly change
DescriptionAttribute descriptionAtt = GetAttribute<DescriptionAttribute>();
return ( descriptionAtt != null )
? descriptionAtt.Description
: PropertyDescriptor.Description;
}
private string ResolveDisplayName()
{
string displayName = PropertyDescriptor.DisplayName;
var attribute = GetAttribute<ParenthesizePropertyNameAttribute>();
if( (attribute != null) && attribute.NeedParenthesis )
{
DisplayName = "(" + DisplayName + ")";
displayName = "(" + displayName + ")";
}
return displayName;
}
private void ResolveExpandableObject()
private bool ResolveExpandableObject()
{
var attribute = PropertyGridUtilities.GetAttribute<ExpandableObjectAttribute>( PropertyDescriptor );
bool isExpandable = false;
var attribute = GetAttribute<ExpandableObjectAttribute>();
if( attribute != null )
{
HasChildProperties = true;
IsReadOnly = true;
isExpandable = true;
}
return isExpandable;
}
private void ResolvePropertyOrder()
private int ResolvePropertyOrder()
{
var attrs = PropertyDescriptor.Attributes.OfType<PropertyOrderAttribute>();
if( attrs.Any() )
PropertyOrder = attrs.First().Order;
else
PropertyOrder = 0;
var attribute = GetAttribute<PropertyOrderAttribute>();
// Max Value. Properties with no order will be displayed last.
return ( attribute != null )
? attribute.Order
: int.MaxValue;
}
private void SetPropertyDescriptorProperties()
private T GetAttribute<T>() where T : Attribute
{
Name = PropertyDescriptor.Name;
DisplayName = PropertyDescriptor.DisplayName;
Category = PropertyDescriptor.Category;
IsReadOnly = PropertyDescriptor.IsReadOnly;
return PropertyGridUtilities.GetAttribute<T>( PropertyDescriptor );
}
#endregion //Methods
#region Interfaces
#region IPropertyParent Members
bool IPropertyParent.IsReadOnly
{
get { return PropertyParent.IsReadOnly; }
}
object IPropertyParent.ValueInstance
{
get { return Value; }
}
EditorDefinitionCollection IPropertyParent.EditorDefinitions
{
get { return PropertyParent.EditorDefinitions; }
}
#endregion
#endregion
}
}

68
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItemCollection.cs

@ -21,26 +21,23 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
using System;
using System.Collections.Specialized;
using System.Diagnostics;
namespace Xceed.Wpf.Toolkit.PropertyGrid
{
public class PropertyItemCollection : ObservableCollection<PropertyItem>
public class PropertyItemCollection : ReadOnlyObservableCollection<PropertyItem>
{
public PropertyItemCollection()
{
}
private bool _preventNotification;
public PropertyItemCollection( List<PropertyItem> list )
: base( list )
public PropertyItemCollection(ObservableCollection<PropertyItem> editableCollection)
:base(editableCollection)
{
EditableCollection = editableCollection;
}
public PropertyItemCollection( IEnumerable<PropertyItem> collection )
: base( collection )
{
}
public ObservableCollection<PropertyItem> EditableCollection { get; private set; }
private ICollectionView GetDefaultView()
{
@ -68,5 +65,52 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
return property.DisplayName.ToLower().StartsWith( text.ToLower() );
};
}
protected override void OnCollectionChanged( NotifyCollectionChangedEventArgs args )
{
if( _preventNotification )
return;
base.OnCollectionChanged( args );
}
internal void Update( IEnumerable<PropertyItem> newItems, bool isCategorized, string filter )
{
using( GetDefaultView().DeferRefresh() )
{
_preventNotification = true;
// Replace the collection content with the new items.
if( newItems != null )
{
EditableCollection.Clear();
foreach( var item in newItems )
{
this.EditableCollection.Add( item );
}
}
// Clear view values
ICollectionView view = this.GetDefaultView();
view.GroupDescriptions.Clear();
view.SortDescriptions.Clear();
view.Filter = null;
// Update view values
if( isCategorized )
{
GroupBy( "Category" );
SortBy( "Category", ListSortDirection.Ascending );
}
SortBy( "PropertyOrder", ListSortDirection.Ascending );
SortBy( "DisplayName", ListSortDirection.Ascending );
Filter( filter );
_preventNotification = false;
OnCollectionChanged( new NotifyCollectionChangedEventArgs( NotifyCollectionChangedAction.Reset ) );
}
}
}
}

42
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml

@ -24,7 +24,8 @@
xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters"
xmlns:pgconv="clr-namespace:Xceed.Wpf.Toolkit.PropertyGrid.Converters"
xmlns:utilities="clr-namespace:Xceed.Wpf.Toolkit.Core.Utilities"
xmlns:commands="clr-namespace:Xceed.Wpf.Toolkit.PropertyGrid.Commands">
xmlns:commands="clr-namespace:Xceed.Wpf.Toolkit.PropertyGrid.Commands"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- =============================================================================== -->
<!-- PropertyGrid -->
@ -36,6 +37,8 @@
<pgconv:ValueSourceToImagePathConverter x:Key="ValueSourceToImagePathConverter" />
<pgconv:ValueSourceToToolTipConverter x:Key="ValueSourceToToolTipConverter" />
<x:Static x:Key="EmptyString" Member="sys:String.Empty" />
<SolidColorBrush x:Key="MouseOverBorderBrush" Color="#FFFFB700" />
<LinearGradientBrush x:Key="MouseOverBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="#FFFEFBF4" />
@ -358,7 +361,7 @@
</Border>
<Border BorderThickness="0.5" BorderBrush="#FFF0F0F0" x:Name="PART_Editor" Grid.Column="1" Background="Transparent">
<ContentControl Content="{TemplateBinding Editor}" VerticalAlignment="Center" Focusable="False" IsTabStop="False" />
<ContentControl x:Name="content" Content="{TemplateBinding Editor}" VerticalAlignment="Center" Focusable="False" IsTabStop="False" />
</Border>
<Expander x:Name="_propertyExpander" Grid.ColumnSpan="2" Grid.Row="1" IsExpanded="{TemplateBinding IsExpanded}" Style="{StaticResource PropertyExpanderStyle}" IsEnabled="True">
@ -392,18 +395,27 @@
<Setter TargetName="PART_Name" Property="Background" Value="#43577B" />
<Setter TargetName="PART_Name" Property="TextElement.Foreground" Value="White" />
</Trigger>
</ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" TargetName="content" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type pg:PropertyGrid}">
<Style.Resources>
<pgconv:SelectedObjectConverter x:Key="objectConverter" />
</Style.Resources>
<Setter Property="AdvancedOptionsMenu" Value="{StaticResource DefaultAdvancedOptionsMenu}" />
<Setter Property="Background" Value="#CED4DF" />
<Setter Property="BorderBrush" Value="#43577B" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter Property="SelectedObjectType" Value="{Binding RelativeSource={RelativeSource Self}, Path=SelectedObject, Converter={StaticResource objectConverter}, ConverterParameter=Type}" />
<Setter Property="SelectedObjectTypeName" Value="{Binding RelativeSource={RelativeSource Self}, Path=SelectedObject, Converter={StaticResource objectConverter}, ConverterParameter=TypeName}" />
<Setter Property="SelectedObjectName" Value="{Binding RelativeSource={RelativeSource Self}, Path=SelectedObject.Name, FallbackValue={StaticResource EmptyString}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type pg:PropertyGrid}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
@ -416,17 +428,18 @@
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="6,2,0,4">
<TextBlock Text="{TemplateBinding SelectedObjectTypeName}" FontWeight="Bold" Visibility="{Binding ShowTitle, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Text="{TemplateBinding SelectedObjectName}" Margin="5,0,0,0" Visibility="{Binding ShowTitle, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}" />
<StackPanel Orientation="Horizontal" Margin="6,2,0,4"
Visibility="{Binding ShowTitle, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock Text="{TemplateBinding SelectedObjectTypeName}" FontWeight="Bold" />
<TextBlock Text="{TemplateBinding SelectedObjectName}" Margin="5,0,0,0" />
</StackPanel>
<Grid Grid.Row="1" Margin="4,0,4,4">
<Grid x:Name="toolsContainer" Grid.Row="1" Margin="4,0,4,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Background="#BCC7D8" Margin="4" Visibility="{Binding ShowSortOptions, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid x:Name="sortButtonContainer" Background="#BCC7D8" Margin="4" Visibility="{Binding ShowSortOptions, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel Orientation="Horizontal" Margin="1" >
<RadioButton IsChecked="{Binding IsCategorized, RelativeSource={RelativeSource TemplatedParent}}"
VerticalAlignment="Center"
@ -443,7 +456,7 @@
</StackPanel>
</Grid>
<Border Grid.Column="1" Margin="4,4,0,4" Background="White" BorderBrush="Gray" BorderThickness="1" Visibility="{Binding ShowSearchBox, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<Border x:Name="searchBoxContainer" Grid.Column="1" Margin="4,4,0,4" Background="White" BorderBrush="Gray" BorderThickness="1" Visibility="{Binding ShowSearchBox, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
@ -527,6 +540,15 @@
</StackPanel>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition SourceName="searchBoxContainer" Property="Visibility" Value="Collapsed"/>
<Condition SourceName="sortButtonContainer" Property="Visibility" Value="Collapsed"/>
</MultiTrigger.Conditions>
<Setter TargetName="toolsContainer" Property="Visibility" Value="Collapsed" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>

28
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/RichTextBox/RichTextBox.cs

@ -37,7 +37,6 @@ namespace Xceed.Wpf.Toolkit
public RichTextBox()
{
Loaded += RichTextBox_Loaded;
}
public RichTextBox( System.Windows.Documents.FlowDocument document )
@ -126,6 +125,12 @@ namespace Xceed.Wpf.Toolkit
#region Methods
protected override void OnTextChanged( System.Windows.Controls.TextChangedEventArgs e )
{
base.OnTextChanged( e );
UpdateText();
}
private void UpdateText()
{
_textSetInternally = true;
@ -145,26 +150,5 @@ namespace Xceed.Wpf.Toolkit
}
#endregion //Methods
#region Event Hanlders
private void RichTextBox_Loaded( object sender, RoutedEventArgs e )
{
Binding binding = BindingOperations.GetBinding( this, TextProperty );
if( binding != null )
{
if( binding.UpdateSourceTrigger == UpdateSourceTrigger.Default || binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus )
{
PreviewLostKeyboardFocus += ( o, ea ) => UpdateText();
}
else
{
TextChanged += ( o, ea ) => UpdateText();
}
}
}
#endregion //Event Hanlders
}
}

42
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

@ -193,6 +193,9 @@
<ItemGroup>
<Compile Include="AssemblyVersionInfo.cs" />
<Compile Include="AssemblyVersionInfoCommon.cs" />
<Compile Include="AutoSelectTextBox\Implementation\AutoSelectBehaviorEnum.cs" />
<Compile Include="AutoSelectTextBox\Implementation\AutoSelectTextBox.cs" />
<Compile Include="AutoSelectTextBox\Implementation\QueryMoveFocusEventArgs.cs" />
<Compile Include="BusyIndicator\Implementation\BusyIndicator.cs" />
<Compile Include="ButtonSpinner\Implementation\ButtonSpinner.cs" />
<Compile Include="CalculatorUpDown\Implementation\CalculatorUpDown.cs" />
@ -209,6 +212,9 @@
<Compile Include="Chromes\Implementation\ButtonChrome.cs" />
<Compile Include="CollectionEditors\Implementation\CollectionEditor.cs" />
<Compile Include="CheckComboBox\Implementation\CheckComboBox.cs" />
<Compile Include="Core\Input\IValidateInput.cs" />
<Compile Include="Core\Input\InputValidationErrorEventArgs.cs" />
<Compile Include="Core\Primitives\CachedTextInfo.cs" />
<Compile Include="Core\Converters\ObjectTypeToNameConverter.cs" />
<Compile Include="ColorCanvas\Implementation\ColorCanvas.cs" />
<Compile Include="Core\Converters\CalculatorMemoryToVisibilityConverter.cs" />
@ -230,8 +236,11 @@
<Compile Include="Core\Primitives\Selector.cs" />
<Compile Include="Core\Primitives\SelectorItem.cs" />
<Compile Include="Core\Primitives\ShapeBase.cs" />
<Compile Include="Core\Primitives\ValueRangeTextBox.cs" />
<Compile Include="Core\PropertyChangedEventArgs.cs" />
<Compile Include="Core\PropertyChangedEventHandler.cs" />
<Compile Include="Core\QueryTextFromValueEventArgs.cs" />
<Compile Include="Core\QueryValueFromTextEventArgs.cs" />
<Compile Include="Core\Themes\StaticResourceKey.cs" />
<Compile Include="Core\Utilities\CalculatorUtilities.cs" />
<Compile Include="Core\Utilities\ColorUtilities.cs" />
@ -240,10 +249,14 @@
<Compile Include="Core\Converters\InverseBoolConverter.cs" />
<Compile Include="Core\Converters\SolidColorBrushToColorConverter.cs" />
<Compile Include="Core\Utilities\ContextMenuUtilities.cs" />
<Compile Include="Core\Utilities\TreeHelper.cs" />
<Compile Include="Core\Utilities\ValueChangeHelper.cs" />
<Compile Include="Core\Utilities\DoubleHelper.cs" />
<Compile Include="Core\Utilities\EllipseHelper.cs" />
<Compile Include="Core\Utilities\NotifyPropertyChangedHelper.cs" />
<Compile Include="Core\Utilities\PointHelper.cs" />
<Compile Include="Core\Utilities\RectHelper.cs" />
<Compile Include="Core\Utilities\ReflectionHelper.cs" />
<Compile Include="Core\Utilities\ResourceHelper.cs" />
<Compile Include="Core\Utilities\Segment.cs" />
<Compile Include="Core\Utilities\VisualTreeHelperEx.cs" />
@ -255,9 +268,19 @@
<Compile Include="DateTimeUpDown\Implementation\DateTimeParser.cs" />
<Compile Include="DropDownButton\Implementation\DropDownButton.cs" />
<Compile Include="Magnifier\Implementation\FrameType.cs" />
<Compile Include="MaskedTextBox\Implementation\AutoCompletingMaskEventArgs.cs" />
<Compile Include="MaskedTextBox\Implementation\InsertKeyModeEnum.cs" />
<Compile Include="MaskedTextBox\Implementation\MaskedTextBox.cs" />
<Compile Include="MaskedTextBox\Implementation\MaskFormatEnum.cs" />
<Compile Include="MultiLineTextEditor\Implementation\MultiLineTextEditor.cs" />
<Compile Include="NumericUpDown\Implementation\ByteUpDown.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="NumericUpDown\Implementation\CommonNumericUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\DecimalUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\DoubleUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\SByteUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\SingleUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\IntegerUpDown.cs" />
<Compile Include="Magnifier\Implementation\Converters\BorderThicknessToStrokeThicknessConverter.cs" />
<Compile Include="Magnifier\Implementation\Converters\RadiusConverter.cs" />
@ -265,10 +288,19 @@
<Compile Include="Magnifier\Implementation\MagnifierAdorner.cs" />
<Compile Include="Magnifier\Implementation\MagnifierManager.cs" />
<Compile Include="Core\Primitives\InputBase.cs" />
<Compile Include="MaskedTextBox\Implementation\MaskedTextBox.cs" />
<Compile Include="Obselete\MaskedTextBox\Implementation\MaskedTextBox.cs" />
<Compile Include="MessageBox\Implementation\MessageBox.cs" />
<Compile Include="NumericUpDown\Implementation\LongUpDown.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="NumericUpDown\Implementation\NumericUpDown.cs" />
<Compile Include="CollectionEditors\Implementation\PrimitiveTypeCollectionEditor.cs" />
<Compile Include="NumericUpDown\Implementation\ShortUpDown.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="NumericUpDown\Implementation\UIntegerUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\ULongUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\UShortUpDown.cs" />
<Compile Include="Pie\Implementation\Pie.cs" />
<Compile Include="Pie\Implementation\PieModeEnum.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
@ -280,6 +312,7 @@
<Compile Include="PropertyGrid\Implementation\Attributes\ItemsSourceAttribute.cs" />
<Compile Include="PropertyGrid\Implementation\Attributes\PropertyOrderAttribute.cs" />
<Compile Include="PropertyGrid\Implementation\Commands\PropertyGridCommands.cs" />
<Compile Include="PropertyGrid\Implementation\Converters\SelectedObjectConverter.cs" />
<Compile Include="PropertyGrid\Implementation\Converters\ValueSourceToImagePathConverter.cs" />
<Compile Include="PropertyGrid\Implementation\Converters\ValueSourceToToolTipConverter.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\CheckBoxEditor.cs" />
@ -293,20 +326,18 @@
<Compile Include="PropertyGrid\Implementation\Editors\ComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\EditorDefinition.cs" />
<Compile Include="PropertyGrid\Implementation\EditorDefinitionCollection.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\DateTimeUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\DecimalUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\DoubleUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\EnumComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\FontComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ItemsSourceAttributeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\UpDownEditors.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TimeSpanEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\IntegerUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ITypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\PrimitiveTypeCollectionEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBlockEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Converters\ExpandableObjectMarginConverter.cs" />
<Compile Include="PropertyGrid\Implementation\IPropertyParent.cs" />
<Compile Include="PropertyGrid\Implementation\PropertyDefinition.cs" />
<Compile Include="PropertyGrid\Implementation\PropertyDefinitionCollection.cs" />
<Compile Include="PropertyGrid\Implementation\PropertyGrid.cs" />
@ -432,6 +463,7 @@
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

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

@ -0,0 +1,288 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace Xceed.Wpf.DataGrid
{
/// <summary>
/// This object is used as the dataItem of a VirtualItemInfo when creating a VirtualItemPage and waiting for the
/// fetch callback.
/// </summary>
internal class EmptyDataItem : INotifyPropertyChanged, ICustomTypeDescriptor
{
#region CONSTRUCTORS
internal EmptyDataItem()
: base()
{
}
internal EmptyDataItem( int index, VirtualList parentVirtualList )
: base()
{
if( index < 0 )
throw new ArgumentException( "Index must be greater than or equal to zero.", "index" );
if( parentVirtualList == null )
throw new ArgumentNullException( "parentVirtualList" );
m_index = index;
m_parentVirtualList = parentVirtualList;
}
#endregion CONSTRUCTORS
#region Index Property
public int Index
{
get
{
return m_index;
}
}
#endregion Index Property
#region INTERNAL PROPERTIES
internal VirtualList ParentVirtualList
{
get
{
return m_parentVirtualList;
}
}
#endregion INTERNAL PROPERTIES
#region Indexer
[EditorBrowsable( EditorBrowsableState.Never )]
public object this[ object parameter ]
{
get
{
return null;
}
set
{
}
}
#endregion
#region PRIVATE FIELDS
private int m_index;
private VirtualList m_parentVirtualList;
#endregion PRIVATE FIELDS
#region CONSTANTS
private static readonly EmptyDataItemPropertyDescriptorCollection DefaultEmptyDataItemPropertyDescriptorCollection = new EmptyDataItemPropertyDescriptorCollection();
#endregion CONSTANTS
#region ICustomTypeDescriptor Members
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes( this );
}
public string GetClassName()
{
return TypeDescriptor.GetClassName( this );
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName( this );
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter( this );
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent( this );
}
public PropertyDescriptor GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty( this );
}
public object GetEditor( Type editorBaseType )
{
return TypeDescriptor.GetEditor( this, editorBaseType );
}
public EventDescriptorCollection GetEvents( Attribute[] attributes )
{
return TypeDescriptor.GetEvents( this, attributes );
}
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents( this );
}
public PropertyDescriptorCollection GetProperties( Attribute[] attributes )
{
// We use a custom PropertyDescriptorCollection that will return the same instance
// of an EmptyDataItemPropertyDescriptor for ANY property that will be ask. This is to avoid
// BindingErrors when an EmptyDataItem is used in the grid.
return EmptyDataItem.DefaultEmptyDataItemPropertyDescriptorCollection;
}
public PropertyDescriptorCollection GetProperties()
{
return this.GetProperties( null );
}
public object GetPropertyOwner( PropertyDescriptor pd )
{
return this;
}
#endregion ICustomTypeDescriptor Members
#region EmptyDataItemPropertyDescriptorCollection Class
private class EmptyDataItemPropertyDescriptorCollection : PropertyDescriptorCollection
{
private static readonly EmptyDataItemPropertyDescriptor DefaultEmptyDataItemPropertyDescriptor = new EmptyDataItemPropertyDescriptor();
private static readonly EmptyDataItemPropertyDescriptor[] DefaultEmptyDataItemPropertyDescriptorArray = new EmptyDataItemPropertyDescriptor[]
{
EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor,
};
public EmptyDataItemPropertyDescriptorCollection()
: base( EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptorArray )
{
}
public override PropertyDescriptor Find( string name, bool ignoreCase )
{
return EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor;
}
public override PropertyDescriptor this[ int index ]
{
get
{
return EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor;
}
}
public override PropertyDescriptor this[ string name ]
{
get
{
return EmptyDataItemPropertyDescriptorCollection.DefaultEmptyDataItemPropertyDescriptor;
}
}
}
#endregion EmptyDataItemPropertyDescriptorCollection Class
#region EmptyDataItemPropertyDescriptor Class
private class EmptyDataItemPropertyDescriptor : PropertyDescriptor
{
private const string DefaultPropertyName = "Empty";
private static readonly Type ObjectType = typeof( object );
public EmptyDataItemPropertyDescriptor()
: base( EmptyDataItemPropertyDescriptor.DefaultPropertyName, null )
{
}
public override bool CanResetValue( object component )
{
return false;
}
public override Type ComponentType
{
get
{
return EmptyDataItemPropertyDescriptor.ObjectType;
}
}
public override object GetValue( object component )
{
return null;
}
public override bool IsReadOnly
{
get
{
return false;
}
}
public override Type PropertyType
{
get
{
return EmptyDataItemPropertyDescriptor.ObjectType;
}
}
public override void ResetValue( object component )
{
}
public override void SetValue( object component, object value )
{
}
public override bool ShouldSerializeValue( object component )
{
return false;
}
}
#endregion EmptyDataItemPropertyDescriptor Class
#region INotifyPropertyChanged Members
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { }
remove { }
}
#endregion
}
}

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

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

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

@ -0,0 +1,157 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualListEnumerator : IEnumerator<object>, IEnumerator
{
public VirtualListEnumerator( VirtualList virtualList )
{
if( virtualList == null )
throw new ArgumentNullException( "virtualList" );
m_virtualList = virtualList;
m_version = m_virtualList.PagingManager.Version;
m_orderedFilledVirtualPages =
m_virtualList.TableOfContent.VirtualPages.OrderBy(
virtualPage => virtualPage.StartDataIndex ).Where(
virtualPage => virtualPage.IsFilled ).ToArray();
}
#region INTERNAL PROPERTIES
internal bool BeforeStart
{
get
{
return m_beforeStart;
}
}
internal bool AfterEnd
{
get
{
return m_afterEnd;
}
}
#endregion INTERNAL PROPERTIES
#region IDisposable Members
public void Dispose()
{
m_currentItemInfo = null;
m_orderedFilledVirtualPages = null;
m_virtualList = null;
}
#endregion IDisposable Members
#region IEnumerator<object> Members
public object Current
{
get
{
return ( m_currentItemInfo == null ) ? null : m_currentItemInfo.DataItem;
}
}
#endregion IEnumerator<object> Members
#region IEnumerator Members
object IEnumerator.Current
{
get
{
return ( m_currentItemInfo == null ) ? null : m_currentItemInfo.DataItem;
}
}
public bool MoveNext()
{
if( m_version != m_virtualList.PagingManager.Version )
throw new InvalidOperationException( "TODO: Collection was modified." );
if( m_beforeStart )
m_beforeStart = false;
if( m_currentPageIndex < m_orderedFilledVirtualPages.Length )
{
VirtualPage virtualPage = m_orderedFilledVirtualPages[ m_currentPageIndex ];
m_currentItemInfo = virtualPage[ m_currentItemIndex ];
m_currentItemIndex++;
if( m_currentItemIndex >= virtualPage.Count )
{
m_currentItemIndex = 0;
m_currentPageIndex++;
}
return true;
}
else
{
m_currentItemInfo = null;
m_afterEnd = true;
return false;
}
}
public void Reset()
{
m_currentItemInfo = null;
m_currentItemIndex = 0;
m_currentPageIndex = 0;
m_afterEnd = false;
m_beforeStart = true;
}
#endregion IEnumerator Members
#region PRIVATE FIELDS
private VirtualList m_virtualList;
private VirtualPage[] m_orderedFilledVirtualPages;
private int m_version;
private VirtualizedItemInfo m_currentItemInfo;
private int m_currentPageIndex;
private int m_currentItemIndex;
private bool m_beforeStart;
private bool m_afterEnd;
#endregion PRIVATE FIELDS
}
}

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

@ -0,0 +1,172 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Collections.ObjectModel;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualListTableOfContent : IDisposable
{
internal VirtualListTableOfContent( int initialCapacity )
{
m_virtualPages = new List<VirtualPage>();
m_readonlyVirtualPages = new ReadOnlyCollection<VirtualPage>( m_virtualPages );
m_objectVersusIndexDictionary = new Dictionary<object, int>( initialCapacity );
m_indexVersusPageDictionary = new Dictionary<int, VirtualPage>( initialCapacity );
}
public void AddPage( VirtualPage page )
{
Debug.Assert( !m_virtualPages.Contains( page ) );
m_virtualPages.Add( page );
int itemCount = page.Count;
for( int i = 0; i < itemCount; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = page[ i ];
Debug.Assert( !m_objectVersusIndexDictionary.ContainsKey( virtualizedItemInfo.DataItem ) );
Debug.Assert( !m_indexVersusPageDictionary.ContainsKey( virtualizedItemInfo.Index ) );
m_objectVersusIndexDictionary.Add( virtualizedItemInfo.DataItem, virtualizedItemInfo.Index );
m_indexVersusPageDictionary.Add( virtualizedItemInfo.Index, page );
}
}
public void RemovePage( VirtualPage page )
{
Debug.Assert( m_virtualPages.Contains( page ) );
int itemCount = page.Count;
for( int i = 0; i < itemCount; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = page[ i ];
Debug.Assert( m_objectVersusIndexDictionary.ContainsKey( virtualizedItemInfo.DataItem ) );
Debug.Assert( m_indexVersusPageDictionary.ContainsKey( virtualizedItemInfo.Index ) );
Debug.Assert( m_indexVersusPageDictionary[ virtualizedItemInfo.Index ] == page );
m_objectVersusIndexDictionary.Remove( virtualizedItemInfo.DataItem );
m_indexVersusPageDictionary.Remove( virtualizedItemInfo.Index );
}
m_virtualPages.Remove( page );
}
public int IndexOf( object item )
{
int index;
if( m_objectVersusIndexDictionary.TryGetValue( item, out index ) )
return index;
return -1;
}
public bool TryGetPageForItem( object item, out VirtualPage page )
{
page = null;
int index;
if( m_objectVersusIndexDictionary.TryGetValue( item, out index ) )
return m_indexVersusPageDictionary.TryGetValue( index, out page );
return false;
}
public bool TryGetPageForSourceIndex( int sourceIndex, out VirtualPage page )
{
return m_indexVersusPageDictionary.TryGetValue( sourceIndex, out page );
}
public bool ContainsPageForItem( object item )
{
int index;
if( m_objectVersusIndexDictionary.TryGetValue( item, out index ) )
return m_indexVersusPageDictionary.ContainsKey( index );
return false;
}
public bool ContainsPageForSourceIndex( int sourceIndex )
{
return m_indexVersusPageDictionary.ContainsKey( sourceIndex );
}
public int Count
{
get
{
Debug.Assert( m_objectVersusIndexDictionary.Count == m_indexVersusPageDictionary.Count );
return m_objectVersusIndexDictionary.Count;
}
}
public ReadOnlyCollection<VirtualPage> VirtualPages
{
get
{
return m_readonlyVirtualPages;
}
}
private Dictionary<object, int> m_objectVersusIndexDictionary;
private Dictionary<int, VirtualPage> m_indexVersusPageDictionary;
private List<VirtualPage> m_virtualPages;
private ReadOnlyCollection<VirtualPage> m_readonlyVirtualPages;
#region IDisposable Members
public void Dispose()
{
while( m_virtualPages.Count > 0 )
{
// Remove the page from every Dictionaries and
// also from m_virtualPages
VirtualPage page = m_virtualPages[ 0 ];
this.RemovePage( page );
page.Dispose();
}
Debug.Assert( m_objectVersusIndexDictionary.Count == 0 );
Debug.Assert( m_indexVersusPageDictionary.Count == 0 );
Debug.Assert( m_virtualPages.Count == 0 );
m_objectVersusIndexDictionary.Clear();
m_indexVersusPageDictionary.Clear();
m_virtualPages.Clear();
}
#endregion
}
}

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

@ -0,0 +1,658 @@
/************************************************************************
Extended WPF Toolkit
Copyright (C) 2010-2012 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
This program can be provided to you by Xceed Software Inc. under a
proprietary commercial license agreement for use in non-Open Source
projects. The commercial version of Extended WPF Toolkit also includes
priority technical support, commercial updates, and many additional
useful WPF controls if you license Xceed Business Suite for WPF.
Visit http://xceed.com and follow @datagrid on Twitter.
**********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Threading;
using System.Collections.Specialized;
namespace Xceed.Wpf.DataGrid
{
internal class VirtualPage
: List<VirtualizedItemInfo>, IDisposable
{
#region CONSTRUCTORS
internal static VirtualPage CreateEmptyPage( VirtualList parentVirtualList, int startSourceIndex, int entryCount )
{
if( parentVirtualList == null )
throw new ArgumentNullException( "parentVirtualList" );
if( startSourceIndex < 0 )
throw new ArgumentOutOfRangeException( "startSourceIndex", startSourceIndex, "startSourceIndex must be greater than or equal to zero." );
if( entryCount < 0 )
throw new ArgumentOutOfRangeException( "entryCount", entryCount, "entryCount must be greater than or equal to zero." );
EmptyDataItem[] emptyDataItems = new EmptyDataItem[ entryCount ];
for( int i = 0; i < entryCount; i++ )
{
emptyDataItems[ i ] = new EmptyDataItem( startSourceIndex + i, parentVirtualList );
}
VirtualPage emptyDataItemPage = new VirtualPage( parentVirtualList, startSourceIndex, emptyDataItems );
emptyDataItemPage.IsFilled = false;
return emptyDataItemPage;
}
private VirtualPage( VirtualList parentVirtualList, int startSourceIndex, object[] dataItems )
: base( dataItems.Length )
{
if( parentVirtualList == null )
throw new ArgumentNullException( "parentVirtualList" );
if( startSourceIndex < 0 )
throw new ArgumentOutOfRangeException( "startSourceIndex", startSourceIndex, "startSourceIndex must be greater than or equal to zero." );
m_startDataIndex = startSourceIndex;
m_asyncCommitInfoList = new List<AsyncCommitInfo>();
m_parentVirtualList = parentVirtualList;
int length = dataItems.Length;
for( int i = 0; i < length; i++ )
{
Debug.Assert( dataItems[ i ] != null );
this.Add( new VirtualizedItemInfo( m_startDataIndex + i, dataItems[ i ] ) );
}
this.IsFilled = true;
}
#endregion CONSTRUCTORS
#region RemoveAfterOperation
public bool RemoveAfterOperation
{
get;
set;
}
#endregion
#region IsAborting Property
public bool IsAborting
{
get;
private set;
}
#endregion
#region IsRestarting Property
public bool IsRestarting
{
get;
private set;
}
#endregion
#region IsEmpty Property
public bool IsEmpty
{
get
{
return ( this.Count == 0 );
}
}
#endregion IsEmpty Property
#region IsFilled Property
public bool IsFilled
{
get
{
return m_flags[ ( int )VirtualItemPageFlags.IsFilled ];
}
private set
{
// Wether we are setting PendingFill to True or to False, we should not be touching this property if we are pending commit.
Debug.Assert( !this.IsCommitPending );
m_flags[ ( int )VirtualItemPageFlags.IsFilled ] = value;
}
}
#endregion IsFilled Property
#region IsDisposed Read-Only Property
public bool IsDisposed
{
get
{
return m_flags[ ( int )VirtualItemPageFlags.IsDisposed ];
}
private set
{
m_flags[ ( int )VirtualItemPageFlags.IsDisposed ] = value;
}
}
#endregion
#region IsCommitPending Property
public bool IsCommitPending
{
get
{
return m_asyncCommitInfoList.Count > 0;
}
}
#endregion IsCommitPending Property
#region IsDirty Property
public bool IsDirty
{
get
{
if( !this.IsFilled )
return false;
int count = this.Count;
for( int i = 0; i < count; i++ )
{
if( this[ i ].IsDirty )
return true;
}
return false;
}
}
#endregion IsDirty Property
#region IsLocked Property
public bool IsLocked
{
get
{
return ( m_lockCount > 0 );
}
}
#endregion IsLocked Property
#region IsRemovable
public bool IsRemovable
{
get
{
// A page which IsPendingFill is removable since it hasn't even been filled yet.
return ( ( !this.IsLocked ) && ( !this.IsCommitPending ) );
}
}
#endregion IsRemovable
#region ParentVirtualList Property
public VirtualList ParentVirtualList
{
get
{
return m_parentVirtualList;
}
}
#endregion ParentVirtualList Property
#region StartDataIndex Property
public int StartDataIndex
{
get
{
return m_startDataIndex;
}
}
#endregion StartDataIndex Property
#region EndDataIndex Property
public int EndDataIndex
{
get
{
return m_startDataIndex + ( this.Count - 1 );
}
}
#endregion EndDataIndex Property
#region PUBLIC METHODS
public VirtualizedItemInfo GetVirtualizedItemInfoAtIndex( int sourceIndex )
{
int index = this.SourceIndexToPageEntryIndex( sourceIndex );
if( index != -1 )
return this[ index ];
return null;
}
#if DEBUG
public override string ToString()
{
string representation = string.Empty;
if( !this.IsFilled )
representation += "Fill Pending - ";
if( this.IsEmpty )
{
representation += m_startDataIndex.ToString() + " - EMPTY.";
}
else
{
representation += m_startDataIndex.ToString() + " - " + this.EndDataIndex.ToString();
}
return representation;
}
#endif
public object[] ToItemArray()
{
int count = this.Count;
object[] items = new object[ count ];
for( int i = 0; i < count; i++ )
{
items[ i ] = this[ i ].DataItem;
}
return items;
}
#endregion PUBLIC METHODS
#region PRIVATE CALLBACKS
private void AsyncQueryInfo_BuiltInAbort( AsyncQueryInfo queryInfo )
{
this.ParentVirtualList.PagingManager.OnBuiltInAbort( this, queryInfo );
this.IsAborting = false;
}
private void AsyncQueryInfo_BeginQueryItems( AsyncQueryInfo queryInfo )
{
this.ParentVirtualList.PagingManager.OnQueryItems( this, queryInfo );
}
private void AsyncQueryInfo_AbortQueryItems( AsyncQueryInfo queryInfo )
{
if( this.IsDisposed )
return;
this.ParentVirtualList.PagingManager.OnAbortQueryItems( this, queryInfo );
this.IsAborting = false;
// If the page was removed, it was also disposed.
// This case means the page was not restarting
if( !this.RemoveAfterOperation && this.ParentVirtualList.IsRestarting )
this.Restart();
}
private void AsyncQueryInfo_EndQueryItems( AsyncQueryInfo queryInfo, object[] fetchedItems )
{
if( this.IsDisposed )
return;
Debug.Assert( !this.IsAborting );
this.ParentVirtualList.PagingManager.OnQueryItemsCompleted( this, queryInfo, fetchedItems );
if( this.ParentVirtualList.IsRestarting )
this.Restart();
}
private void AsyncQueryInfo_QueryErrorChanged( AsyncQueryInfo queryInfo )
{
this.ParentVirtualList.PagingManager.OnQueryErrorChanged( this, queryInfo );
if( this.ParentVirtualList.IsRestarting )
this.Restart();
}
private void AsyncCommitInfo_BeginCommitItems( AsyncCommitInfo commitInfo )
{
this.ParentVirtualList.PagingManager.OnCommitItems( this, commitInfo );
}
private void AsyncCommitInfo_EndCommitItems( AsyncCommitInfo commitInfo )
{
this.ParentVirtualList.PagingManager.OnCommitItemsCompleted( this, commitInfo );
if( this.ParentVirtualList.IsRestarting )
this.Restart();
}
private void AsyncCommitInfo_CommitErrorChanged( AsyncCommitInfo commitInfo )
{
this.ParentVirtualList.PagingManager.OnCommitErrorChanged( this, commitInfo );
if( this.ParentVirtualList.IsRestarting )
this.Restart();
}
#endregion PRIVATE CALLBACKS
#region INTERNAL METHODS
/// <summary>
/// Increments the page's lock count.
/// Returns True if the lock count went from 0 to 1, meaning that the page is now considered locked and is not up for removal.
/// </summary>
internal bool LockPage()
{
m_lockCount++;
// Returns True if the page just became locked or False if the call simply incremented the lock count.
return m_lockCount == 1;
}
/// <summary>
/// Decrements the page's lock count.
/// Returns True if the lock count is down to 0, meaning that the page is now considered unlocked and is up for removal.
/// </summary>
internal bool UnlockPage()
{
if( m_lockCount > 0 )
{
m_lockCount--;
}
else
{
// Safety Net. We return False, even though the lock count is reinitialized to zero, since the page did not just become unlocked.
// This can occur when the DataGridVirtualizingCollectionView hits ForceRefresh method restarts the VirtualItemBook, thus getting rid
// of locked and unlocked pages and THEN, the Generator's WeakEventListener of CollectionChanged cleans up its containers which in turn
// tries to unlock a source index which isn't locked at all (since it was cleared when the virtual item book reseted).
m_lockCount = 0;
return false;
}
// Returns True if the page just became unlocked or False if the call simply decremented the lock count.
return m_lockCount == 0;
}
internal void AbortQueryDataOperation()
{
Debug.Assert( !this.IsDisposed );
if( this.IsFilled )
throw new InvalidOperationException( "An attempt was made to abort a query that has already completed." );
if( m_asyncQueryInfo != null )
{
this.IsAborting = true;
m_asyncQueryInfo.AbortQuery();
}
}
internal void QueueQueryData( Dispatcher dispatcher )
{
Debug.Assert( !this.IsDisposed );
Debug.Assert( m_asyncQueryInfo == null );
m_asyncQueryInfo = new AsyncQueryInfo(
dispatcher,
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_BeginQueryItems ),
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_AbortQueryItems ),
new Action<AsyncQueryInfo, object[]>( this.AsyncQueryInfo_EndQueryItems ),
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_QueryErrorChanged ),
new Action<AsyncQueryInfo>( this.AsyncQueryInfo_BuiltInAbort ),
m_startDataIndex,
this.Count );
m_asyncQueryInfo.QueueQuery();
}
internal void EndQueryItems( AsyncQueryInfo asyncQueryInfo, object[] items )
{
Debug.Assert( !this.IsDisposed );
// This can occur when the user notify us that the QueryData is completed for an AsyncQueryInfo.StartIndex that refers to a Page which does exists
// but that was removed, then re-created thus creating another asyncQueryInfo and queuing another QueryData.
// The only way to get rid of this situation would be to keep a ref to the queued asyncQueryInfo even if we get rid of the page and re-link the same instance
// to the newly created page. This optimization could be done in a future version. For now, let's return and the second asyncQueryInfo will take care of filling
// the newly created page.
if( m_asyncQueryInfo != asyncQueryInfo )
{
Debug.Assert( false );
return;
}
if( this.IsFilled )
throw new InvalidOperationException( "An attempt was made to fill a virtual page that is already filled." );
if( items == null )
throw new ArgumentNullException( "items" );
for( int i = 0; i < items.Length; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = this[ i ];
Debug.Assert( virtualizedItemInfo.DataItem is EmptyDataItem );
Debug.Assert( virtualizedItemInfo.Index == ( m_startDataIndex + i ) );
this[ i ].DataItem = items[ i ];
}
this.IsFilled = true;
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Page Filled - " + this.ToString() );
}
internal void QueueCommitData( Dispatcher dispatcher )
{
Debug.Assert( !this.IsDisposed );
int count = this.Count;
List<VirtualizedItemInfo> dirtyItemInfoNotAlreadyPendingCommit = new List<VirtualizedItemInfo>( count );
for( int i = 0; i < count; i++ )
{
VirtualizedItemInfo virtualizedItemInfo = this[ i ];
if( ( virtualizedItemInfo.IsDirty ) && ( !this.IsAsyncCommitInfoQueuedForItem( virtualizedItemInfo.DataItem ) ) )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "QueueCommitData for page " + this.ToString() + " and index " + virtualizedItemInfo.Index );
dirtyItemInfoNotAlreadyPendingCommit.Add( virtualizedItemInfo );
}
}
if( dirtyItemInfoNotAlreadyPendingCommit.Count > 0 )
{
AsyncCommitInfo asyncCommitInfo = new AsyncCommitInfo(
dispatcher,
new Action<AsyncCommitInfo>( this.AsyncCommitInfo_BeginCommitItems ),
new Action<AsyncCommitInfo>( this.AsyncCommitInfo_EndCommitItems ),
new Action<AsyncCommitInfo>( this.AsyncCommitInfo_CommitErrorChanged ),
dirtyItemInfoNotAlreadyPendingCommit.ToArray() );
m_asyncCommitInfoList.Add( asyncCommitInfo );
asyncCommitInfo.BeginCommit();
}
}
internal bool IsAsyncCommitInfoQueuedForItem( object item )
{
int pendingAsyncCommitInfoCount = m_asyncCommitInfoList.Count;
for( int i = 0; i < pendingAsyncCommitInfoCount; i++ )
{
VirtualizedItemInfo[] pendingCommitVirtualizedItemInfos = m_asyncCommitInfoList[ i ].VirtualizedItemInfos;
foreach( VirtualizedItemInfo pendingCommitVirtualizedItemInfo in pendingCommitVirtualizedItemInfos )
{
if( pendingCommitVirtualizedItemInfo.DataItem == item )
return true;
}
}
return false;
}
internal void EndCommitItems( AsyncCommitInfo asyncCommitInfo )
{
Debug.Assert( !this.IsDisposed );
Debug.Assert( m_asyncCommitInfoList.Contains( asyncCommitInfo ) );
VirtualizedItemInfo[] commitedItemInfos = asyncCommitInfo.VirtualizedItemInfos;
for( int i = 0; i < commitedItemInfos.Length; i++ )
{
commitedItemInfos[ i ].OldValues = null;
}
m_asyncCommitInfoList.Remove( asyncCommitInfo );
asyncCommitInfo.Dispose();
}
internal void Restart()
{
if( !this.IsRestarting )
{
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Restart VirtualPage requested for " + this.ToString() );
this.IsRestarting = true;
this.ParentVirtualList.OnVirtualPageRestarting( this );
}
// The page has finished commiting or aborting
if( ( !this.IsCommitPending ) && ( !this.IsAborting ) )
{
this.EndRestart();
}
}
internal void EndRestart()
{
// VirtualPage will be disposed by the VirtualPageManager
// when it removes the page from is m_pageNodeList
Debug.WriteLineIf( VirtualPageManager.DebugDataVirtualization, "Restart VirtualPage completed for " + this.ToString() );
this.IsRestarting = false;
this.ParentVirtualList.OnVirtualPageRestarted( this );
}
#endregion INTERNAL METHODS
#region PRIVATE METHODS
private int SourceIndexToPageEntryIndex( int sourceIndex )
{
if( ( this.Count != 0 ) && ( ( sourceIndex >= m_startDataIndex ) && ( sourceIndex <= this.EndDataIndex ) ) )
return sourceIndex - m_startDataIndex;
return -1;
}
private bool ContainsItem( object item )
{
int count = this.Count;
for( int i = 0; i < count; i++ )
{
if( this[ i ].DataItem == item )
return true;
}
return false;
}
#endregion PRIVATE METHODS
#region PRIVATE FIELDS
private BitVector32 m_flags;
private int m_startDataIndex;
private int m_lockCount;
private VirtualList m_parentVirtualList;
private AsyncQueryInfo m_asyncQueryInfo;
private List<AsyncCommitInfo> m_asyncCommitInfoList;
#endregion PRIVATE FIELDS
#region PRIVATE NESTED ENUMS
[Flags]
private enum VirtualItemPageFlags
{
IsFilled = 1,
IsDisposed = 2,
}
#endregion PRIVATE NESTED ENUMS
#region IDisposable Members
public void Dispose()
{
Debug.Assert( !this.IsDisposed );
Debug.Assert( ( m_asyncCommitInfoList != null ) && ( m_asyncCommitInfoList.Count == 0 ), "Some async commit are not completed while disposing VirtualPage" );
if( m_asyncQueryInfo != null )
{
// We must dispose the AsyncQueryInfo to be sure
// it does not root this VirtualPage instance
m_asyncQueryInfo.Dispose();
m_asyncQueryInfo = null;
}
this.Clear();
m_parentVirtualList = null;
this.IsDisposed = true;
}
#endregion
}
}

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

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

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

Loading…
Cancel
Save