Browse Source

1.8.0 Release - .NET 35 branch

pull/1645/head
emartin_cp 13 years ago
parent
commit
751d606bda
  1. 2
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/AssemblyVersionInfo.cs
  2. 31
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/AutoSelectBehaviorEnum.cs
  3. 301
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/AutoSelectTextBox.cs
  4. 76
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/AutoSelectTextBox/Implementation/QueryMoveFocusEventArgs.cs
  5. 22
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs
  6. 73
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/ColorCanvas/Implementation/ColorCanvas.cs
  7. 2
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/ColorCanvas/Themes/Generic.xaml
  8. 2
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/ColorPicker/Implementation/ColorPicker.cs
  9. 4
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Converters/WizardPageButtonVisibilityConverter.cs
  10. 32
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Input/IValidateInput.cs
  11. 46
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Input/InputValidationErrorEventArgs.cs
  12. 57
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Primitives/CachedTextInfo.cs
  13. 557
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs
  14. 12
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Primitives/SelectorItem.cs
  15. 113
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Primitives/UpDownBase.cs
  16. 1192
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Primitives/ValueRangeTextBox.cs
  17. 57
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/QueryTextFromValueEventArgs.cs
  18. 70
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/QueryValueFromTextEventArgs.cs
  19. 2
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Utilities/ColorUtilities.cs
  20. 163
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Utilities/NotifyPropertyChangedHelper.cs
  21. 136
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Utilities/ReflectionHelper.cs
  22. 238
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Utilities/TreeHelper.cs
  23. 153
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Core/Utilities/ValueChangeHelper.cs
  24. 24
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/DateTimePicker/Themes/Generic.xaml
  25. 26
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/DateTimeUpDown/Implementation/DateTimeUpDown.cs
  26. 4
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Magnifier/Implementation/Magnifier.cs
  27. 108
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/AutoCompletingMaskEventArgs.cs
  28. 32
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/InsertKeyModeEnum.cs
  29. 33
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskFormatEnum.cs
  30. 2116
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskedTextBox.cs
  31. 80
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/MessageBox/Implementation/MessageBox.cs
  32. 43
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/MessageBox/Themes/Generic.xaml
  33. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ByteUpDown.cs
  34. 184
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/CommonNumericUpDown.cs
  35. 86
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DecimalUpDown.cs
  36. 86
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DoubleUpDown.cs
  37. 87
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/IntegerUpDown.cs
  38. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/LongUpDown.cs
  39. 15
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/NumericUpDown.cs
  40. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/SByteUpDown.cs
  41. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ShortUpDown.cs
  42. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/SingleUpDown.cs
  43. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/UIntegerUpDown.cs
  44. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/ULongUpDown.cs
  45. 55
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/UShortUpDown.cs
  46. 67
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/NumericUpDown/Themes/Generic.xaml
  47. 726
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Obselete/MaskedTextBox/Implementation/MaskedTextBox.cs
  48. 2
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/Properties/AssemblyInfo.cs
  49. 92
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Converters/SelectedObjectConverter.cs
  50. 52
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/Editors/UpDownEditors.cs
  51. 36
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/IPropertyParent.cs
  52. 344
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs
  53. 85
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGridUtilities.cs
  54. 282
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItem.cs
  55. 68
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItemCollection.cs
  56. 42
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml
  57. 28
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/RichTextBox/RichTextBox.cs
  58. 43
      ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

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

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

31
ExtendedWPFToolkitSolution_35/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_35/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_35/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_35/Src/WPFToolkit.Extended/CheckComboBox/Implementation/CheckComboBox.cs

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

73
ExtendedWPFToolkitSolution_35/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.Core.Utilities;
using Xceed.Wpf.Toolkit.Primitives; using Xceed.Wpf.Toolkit.Primitives;
using System.IO; using System.IO;
using System;
namespace Xceed.Wpf.Toolkit namespace Xceed.Wpf.Toolkit
{ {
[TemplatePart( Name = PART_ColorShadingCanvas, Type = typeof( Canvas ) )] [TemplatePart( Name = PART_ColorShadingCanvas, Type = typeof( Canvas ) )]
[TemplatePart( Name = PART_ColorShadeSelector, Type = typeof( Canvas ) )] [TemplatePart( Name = PART_ColorShadeSelector, Type = typeof( Canvas ) )]
[TemplatePart( Name = PART_SpectrumSlider, Type = typeof( ColorSpectrumSlider ) )] [TemplatePart( Name = PART_SpectrumSlider, Type = typeof( ColorSpectrumSlider ) )]
[TemplatePart( Name = PART_HexadecimalTextBox, Type = typeof( TextBox ) )]
public class ColorCanvas : Control public class ColorCanvas : Control
{ {
private const string PART_ColorShadingCanvas = "PART_ColorShadingCanvas"; private const string PART_ColorShadingCanvas = "PART_ColorShadingCanvas";
private const string PART_ColorShadeSelector = "PART_ColorShadeSelector"; private const string PART_ColorShadeSelector = "PART_ColorShadeSelector";
private const string PART_SpectrumSlider = "PART_SpectrumSlider"; private const string PART_SpectrumSlider = "PART_SpectrumSlider";
private const string PART_HexadecimalTextBox = "PART_HexadecimalTextBox";
#region Private Members #region Private Members
@ -43,6 +46,7 @@ namespace Xceed.Wpf.Toolkit
private Canvas _colorShadingCanvas; private Canvas _colorShadingCanvas;
private Canvas _colorShadeSelector; private Canvas _colorShadeSelector;
private ColorSpectrumSlider _spectrumSlider; private ColorSpectrumSlider _spectrumSlider;
private TextBox _hexadecimalTextBox;
private Point? _currentColorPosition; private Point? _currentColorPosition;
private bool _surpressPropertyChanged; private bool _surpressPropertyChanged;
@ -74,7 +78,7 @@ namespace Xceed.Wpf.Toolkit
protected virtual void OnSelectedColorChanged( Color oldValue, Color newValue ) protected virtual void OnSelectedColorChanged( Color oldValue, Color newValue )
{ {
HexadecimalString = GetFormatedColorString( newValue ); SetHexadecimalStringProperty( GetFormatedColorString( newValue ), false );
UpdateRGBValues( newValue ); UpdateRGBValues( newValue );
UpdateColorShadeSelectorPosition( newValue ); UpdateColorShadeSelectorPosition( newValue );
@ -237,6 +241,8 @@ namespace Xceed.Wpf.Toolkit
string currentColorString = GetFormatedColorString( SelectedColor ); string currentColorString = GetFormatedColorString( SelectedColor );
if( !currentColorString.Equals( newColorString ) ) if( !currentColorString.Equals( newColorString ) )
UpdateSelectedColor( ( Color )ColorConverter.ConvertFromString( newColorString ) ); UpdateSelectedColor( ( Color )ColorConverter.ConvertFromString( newColorString ) );
SetHexadecimalTextBoxTextProperty( newValue );
} }
private static object OnCoerceHexadecimalString( DependencyObject d, object basevalue ) private static object OnCoerceHexadecimalString( DependencyObject d, object basevalue )
@ -251,16 +257,19 @@ namespace Xceed.Wpf.Toolkit
private object OnCoerceHexadecimalString( object newValue ) private object OnCoerceHexadecimalString( object newValue )
{ {
var value = newValue as string; var value = newValue as string;
string retValue = value;
try try
{ {
ColorConverter.ConvertFromString( value ); ColorConverter.ConvertFromString( value );
} }
catch 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." ); throw new InvalidDataException( "Color provided is not in the correct format." );
} }
return value; return retValue;
} }
#endregion //HexadecimalString #endregion //HexadecimalString
@ -289,7 +298,7 @@ namespace Xceed.Wpf.Toolkit
protected virtual void OnUsingAlphaChannelChanged() protected virtual void OnUsingAlphaChannelChanged()
{ {
HexadecimalString = GetFormatedColorString( SelectedColor ); SetHexadecimalStringProperty( GetFormatedColorString( SelectedColor ), false );
} }
#endregion //UsingAlphaChannel #endregion //UsingAlphaChannel
@ -342,17 +351,31 @@ namespace Xceed.Wpf.Toolkit
if( _spectrumSlider != null ) if( _spectrumSlider != null )
_spectrumSlider.ValueChanged += SpectrumSlider_ValueChanged; _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 ); UpdateRGBValues( SelectedColor );
UpdateColorShadeSelectorPosition( 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 ) if( e.Key == Key.Enter && e.OriginalSource is TextBox )
{ {
BindingExpression be = ( ( TextBox )e.OriginalSource ).GetBindingExpression( TextBox.TextProperty ); TextBox textBox = ( TextBox )e.OriginalSource;
be.UpdateSource(); 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 #endregion //Event Handlers
#region Events #region Events
@ -503,7 +532,7 @@ namespace Xceed.Wpf.Toolkit
var currentColor = ColorUtilities.ConvertHsvToRgb( hsv.H, hsv.S, hsv.V ); var currentColor = ColorUtilities.ConvertHsvToRgb( hsv.H, hsv.S, hsv.V );
currentColor.A = A; currentColor.A = A;
SelectedColor = currentColor; SelectedColor = currentColor;
HexadecimalString = GetFormatedColorString( SelectedColor ); SetHexadecimalStringProperty( GetFormatedColorString( SelectedColor ), false );
} }
private string GetFormatedColorString( Color colorToFormat ) private string GetFormatedColorString( Color colorToFormat )
@ -516,6 +545,34 @@ namespace Xceed.Wpf.Toolkit
return ColorUtilities.FormatColorString( stringToFormat, UsingAlphaChannel ); 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 #endregion //Methods
} }
} }

2
ExtendedWPFToolkitSolution_35/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"> <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}}" /> <Rectangle x:Name="SelectedColor" Fill="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorToSolidColorBrushConverter}}" />
</Border> </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> </Grid>
</Border> </Border>

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

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

4
ExtendedWPFToolkitSolution_35/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 ) public object Convert( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{ {
Visibility wizardVisibility = ( Visibility )values[ 0 ]; 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; Visibility visibility = Visibility.Visible;

32
ExtendedWPFToolkitSolution_35/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_35/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_35/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_35/Src/WPFToolkit.Extended/Core/Primitives/Selector.cs

@ -26,16 +26,28 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Input; 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 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 #region Members
private bool _ignoreSetSelectedValue; private bool _surpressItemSelectionChanged;
private bool _surpressSelectionChanged; private bool _ignoreSelectedItemChanged;
private bool _surpressSelectedValueChanged; private bool _ignoreSelectedValueChanged;
private int _ignoreSelectedItemsCollectionChanged;
private int _ignoreSelectedMemberPathValuesChanged;
private IList _selectedItems;
private ValueChangeHelper _selectedMemberPathValuesHelper;
private ValueChangeHelper _valueMemberPathValuesHelper;
#endregion //Members #endregion //Members
@ -43,9 +55,11 @@ namespace Xceed.Wpf.Toolkit.Primitives
public Selector() public Selector()
{ {
SelectedItems = new ObservableCollection<object>(); this.SelectedItems = new ObservableCollection<object>();
AddHandler( Selector.SelectedEvent, new RoutedEventHandler( Selector_ItemSelected ) ); AddHandler( Selector.SelectedEvent, new RoutedEventHandler( ( s, args ) => this.OnItemSelectionChangedCore( args, false ) ) );
AddHandler( Selector.UnSelectedEvent, new RoutedEventHandler( Selector_ItemUnselected ) ); AddHandler( Selector.UnSelectedEvent, new RoutedEventHandler( ( s, args ) => this.OnItemSelectionChangedCore( args, true ) ) );
_selectedMemberPathValuesHelper = new ValueChangeHelper( this.OnSelectedMemberPathValuesChanged );
_valueMemberPathValuesHelper = new ValueChangeHelper( this.OnValueMemberPathValuesChanged );
} }
#endregion //Constructors #endregion //Constructors
@ -88,7 +102,9 @@ namespace Xceed.Wpf.Toolkit.Primitives
#endregion #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 public object SelectedItem
{ {
get 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 private static void OnSelectedItemChanged( DependencyObject sender, DependencyPropertyChangedEventArgs args )
//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 ) ); ( ( 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 public IList SelectedItems
{ {
get 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 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 public string SelectedMemberPath
{ {
get get
@ -129,6 +214,11 @@ namespace Xceed.Wpf.Toolkit.Primitives
} }
} }
private static void OnSelectedMemberPathChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{
( ( Selector )o ).UpdateSelectedMemberPathValuesBindings();
}
#region SelectedValue #region SelectedValue
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register( "SelectedValue", typeof( string ), typeof( Selector ), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedValueChanged ) ); 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 ) protected virtual void OnSelectedValueChanged( string oldValue, string newValue )
{ {
if( _surpressSelectedValueChanged ) if( _ignoreSelectedValueChanged )
return; return;
UpdateSelectedItemsFromSelectedValue(); UpdateFromSelectedValue();
} }
#endregion //SelectedValue #endregion //SelectedValue
@ -178,7 +268,20 @@ namespace Xceed.Wpf.Toolkit.Primitives
private static void OnValueMemberPathChanged( DependencyObject o, DependencyPropertyChangedEventArgs e ) 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 #endregion
@ -199,79 +302,65 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected override void PrepareContainerForItemOverride( DependencyObject element, object item ) protected override void PrepareContainerForItemOverride( DependencyObject element, object item )
{ {
_surpressSelectionChanged = true; base.PrepareContainerForItemOverride( element, item );
_surpressItemSelectionChanged = true;
var selectorItem = element as FrameworkElement; var selectorItem = element as FrameworkElement;
//first try resolving SelectorItem.IsSelected by data binding to the SelectedMemeberPath property selectorItem.SetValue( SelectorItem.IsSelectedProperty, SelectedItems.Contains(item) );
if( !String.IsNullOrEmpty( SelectedMemberPath ) )
_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 ) CollectionChangedEventManager.RemoveListener( oldCollection, this );
{
Mode = BindingMode.TwoWay,
Source = item
};
selectorItem.SetBinding( SelectorItem.IsSelectedProperty, selectedBinding );
} }
//now let's search the SelectedItems for the current item. If it's there then mark it as selected if( newCollection != null )
if( SelectedItems != null )
{ {
foreach( object selectedItem in SelectedItems ) CollectionChangedEventManager.AddListener( newCollection, this );
{
//a match was found so select it and get the hell out of here
if( item.Equals( selectedItem ) )
{
selectorItem.SetValue( SelectorItem.IsSelectedProperty, true );
break;
}
}
} }
base.PrepareContainerForItemOverride( element, item ); this.RemoveUnavailableSelectedItems();
_surpressSelectionChanged = false; this.UpdateSelectedMemberPathValuesBindings();
this.UpdateValueMemberPathValuesBindings();
} }
#endregion //Base Class Overrides #endregion //Base Class Overrides
#region Events #region Events
public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent( "SelectedEvent", 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( SelectedItemChangedEventHandler ), 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 static readonly RoutedEvent ItemSelectionChangedEvent = EventManager.RegisterRoutedEvent( "ItemSelectionChanged", RoutingStrategy.Bubble, typeof( ItemSelectionChangedEventHandler ), typeof( Selector ) );
public event SelectedItemChangedEventHandler SelectedItemChanged public event ItemSelectionChangedEventHandler ItemSelectionChanged
{ {
add add
{ {
AddHandler( SelectedItemChangedEvent, value ); AddHandler( ItemSelectionChangedEvent, value );
} }
remove remove
{ {
RemoveHandler( SelectedItemChangedEvent, value ); RemoveHandler( ItemSelectionChangedEvent, value );
} }
} }
#endregion //Events #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 #region Methods
protected object GetItemValue( object item ) protected object GetItemValue( object item )
{ {
if( !String.IsNullOrEmpty( ValueMemberPath ) && (item != null)) if( !String.IsNullOrEmpty( ValueMemberPath ) && ( item != null ) )
{ {
var property = item.GetType().GetProperty( ValueMemberPath ); var property = item.GetType().GetProperty( ValueMemberPath );
if( property != null ) if( property != null )
@ -281,49 +370,86 @@ namespace Xceed.Wpf.Toolkit.Primitives
return item; 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 ); PropertyInfo prop = this.GetSelectedMemberPathProperty(item);
Update( item, remove );
RaiseSelectedItemChangedEvent( item, !remove ); //inverse the remove paramter to correctly reflect the IsSelected state 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 ) PropertyInfo prop = this.GetSelectedMemberPathProperty(item);
return;
RaiseEvent( new SelectedItemChangedEventArgs( Selector.SelectedItemChangedEvent, this, item, isSelected ) );
if( Command != null ) if( prop != null )
Command.Execute( item ); {
prop.SetValue( item, value, null );
}
} }
protected virtual void Update( object item, bool remove ) private PropertyInfo GetSelectedMemberPathProperty(object item)
{ {
UpdateSelectedItem( item ); PropertyInfo propertyInfo = null;
UpdateSelectedItems( item, remove ); if( !String.IsNullOrEmpty( SelectedMemberPath ) && ( item != null ) )
UpdateSelectedValue(); {
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 ) object item = this.ItemContainerGenerator.ItemFromContainer( ( DependencyObject )args.OriginalSource );
SelectedItems = new ObservableCollection<object>();
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 ); SelectedItems.Remove( item );
} }
else else
@ -331,116 +457,263 @@ namespace Xceed.Wpf.Toolkit.Primitives
if( !SelectedItems.Contains( item ) ) if( !SelectedItems.Contains( item ) )
SelectedItems.Add( 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 this.RemoveUnavailableSelectedItems();
if( _ignoreSetSelectedValue ) 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; 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 #if VS2008
string newValue = String.Join( Delimiter, SelectedItems.Cast<object>().Select( x => GetItemValue( x ).ToString() ).ToArray() ); string newValue = String.Join( Delimiter, SelectedItems.Cast<object>().Select( x => GetItemValue( x ).ToString() ).ToArray() );
#else #else
string newValue = String.Join( Delimiter, SelectedItems.Cast<object>().Select( x => GetItemValue( x ) ) ); string newValue = String.Join( Delimiter, SelectedItems.Cast<object>().Select( x => GetItemValue( x ) ) );
#endif #endif
if( String.IsNullOrEmpty( SelectedValue ) || !SelectedValue.Equals( newValue ) ) if( String.IsNullOrEmpty( SelectedValue ) || !SelectedValue.Equals( newValue ) )
{
_ignoreSelectedValueChanged = true;
SelectedValue = newValue; SelectedValue = newValue;
_ignoreSelectedValueChanged = false;
_surpressSelectedValueChanged = false; }
} }
private void UpdateSelectedItemsFromSelectedValue() /// <summary>
/// Updates the SelectedItem property based on what is present in the SelectedItems property.
/// </summary>
private void UpdateSelectedItem()
{ {
_surpressSelectionChanged = true; if( !SelectedItems.Contains( SelectedItem ) )
{
//first we have to unselect everything _ignoreSelectedItemChanged = true;
ClearSelectedItems(); 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 ); bool? isSelected = this.GetSelectedMemberPathValue( item );
foreach( string value in values ) if( isSelected != null )
{ {
var item = ResolveItemByValue( value ); if( isSelected.Value )
if( item != null )
{ {
SelectedItems.Add( item ); if( !SelectedItems.Contains( item ) )
{
//now try to select it in the list SelectedItems.Add( item );
var selectorItem = ItemContainerGenerator.ContainerFromItem( item ) as SelectorItem; }
if( selectorItem != null ) }
else
{
if( SelectedItems.Contains( item ) )
{ {
if( !selectorItem.IsSelected ) SelectedItems.Remove( item );
selectorItem.IsSelected = true;
} }
} }
} }
} }
_ignoreSelectedItemsCollectionChanged--;
_surpressSelectionChanged = false; 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 ) foreach( object o in ItemsCollection )
SelectedItems.Clear(); {
else bool isSelected = SelectedItems.Contains( o );
SelectedItems = new ObservableCollection<object>();
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; SelectedItems.RemoveAt( i );
if( selectorItem != null ) i--;
{
if( selectorItem.IsSelected )
selectorItem.IsSelected = false;
}
} }
} }
_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 ); SelectedItems.Add( item );
if( property != null )
{
var propertyValue = property.GetValue( item, null );
if( value.Equals( propertyValue.ToString(), StringComparison.InvariantCultureIgnoreCase ) )
return item;
}
} }
} }
} }
_ignoreSelectedItemsCollectionChanged--;
return value; this.UpdateFromSelectedItems();
} }
#endregion //Methods #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 public bool IsSelected
{ {
@ -453,7 +726,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
private set; 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 ) : base( routedEvent, source )
{ {
Item = item; Item = item;

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

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

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

@ -22,12 +22,14 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Input; using System.Windows.Input;
using Xceed.Wpf.Toolkit.Core;
using Xceed.Wpf.Toolkit.Core.Input;
namespace Xceed.Wpf.Toolkit.Primitives namespace Xceed.Wpf.Toolkit.Primitives
{ {
[TemplatePart( Name = PART_TextBox, Type = typeof( TextBox ) )] [TemplatePart( Name = PART_TextBox, Type = typeof( TextBox ) )]
[TemplatePart( Name = PART_Spinner, Type = typeof( Spinner ) )] [TemplatePart( Name = PART_Spinner, Type = typeof( Spinner ) )]
public abstract class UpDownBase<T> : InputBase public abstract class UpDownBase<T> : InputBase, IValidateInput
{ {
#region Members #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 /// Flags if the Text and Value properties are in the process of being sync'd
/// </summary> /// </summary>
private bool _isSyncingTextAndValueProperties; private bool _isSyncingTextAndValueProperties;
private bool _isTextChangedFromUI;
#endregion //Members #endregion //Members
@ -114,7 +117,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
#region Value #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 public T Value
{ {
get 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 ) private static void OnValueChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
{ {
UpDownBase<T> upDownBase = o as UpDownBase<T>; UpDownBase<T> upDownBase = o as UpDownBase<T>;
@ -136,9 +149,7 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected virtual void OnValueChanged( T oldValue, T newValue ) protected virtual void OnValueChanged( T oldValue, T newValue )
{ {
ValidateValue( newValue ); SyncTextAndValueProperties( false, null );
SyncTextAndValueProperties( ValueProperty, string.Empty );
SetValidSpinDirection(); SetValidSpinDirection();
@ -174,6 +185,12 @@ namespace Xceed.Wpf.Toolkit.Primitives
base.OnApplyTemplate(); base.OnApplyTemplate();
TextBox = GetTemplateChild( PART_TextBox ) as TextBox; 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 ) if( Spinner != null )
Spinner.Spin -= OnSpinnerSpin; 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 ) protected override void OnMouseWheel( MouseWheelEventArgs e )
{ {
base.OnMouseWheel( e ); base.OnMouseWheel( e );
@ -234,7 +265,10 @@ namespace Xceed.Wpf.Toolkit.Primitives
protected override void OnTextChanged( string oldValue, string newValue ) protected override void OnTextChanged( string oldValue, string newValue )
{ {
SyncTextAndValueProperties( InputBase.TextProperty, newValue ); if( !_isTextChangedFromUI )
{
SyncTextAndValueProperties( true, Text );
}
} }
#endregion //Base Class Overrides #endregion //Base Class Overrides
@ -251,6 +285,10 @@ namespace Xceed.Wpf.Toolkit.Primitives
#region Events #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. //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 static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent( "ValueChanged", RoutingStrategy.Bubble, typeof( RoutedPropertyChangedEventHandler<object> ), typeof( UpDownBase<T> ) );
public event RoutedPropertyChangedEventHandler<object> ValueChanged public event RoutedPropertyChangedEventHandler<object> ValueChanged
@ -265,6 +303,8 @@ namespace Xceed.Wpf.Toolkit.Primitives
} }
} }
#endregion
#endregion //Events #endregion //Events
#region Methods #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 ) if( _isSyncingTextAndValueProperties )
return; return;
_isSyncingTextAndValueProperties = true; _isSyncingTextAndValueProperties = true;
Exception error = null;
//this only occures when the user typed in the value if( updateValueFromText )
if( InputBase.TextProperty == p )
{ {
Value = ConvertTextToValue( text ); try
{
Value = ConvertTextToValue( Text );
}
catch( Exception e )
{
error = e;
}
} }
Text = ConvertValueToText(); Text = ConvertValueToText();
#if VS2008 if( TextBox != null )
//there is a bug in .NET 3.5 which will not correctly update the textbox text through binding.
if ( TextBox != null )
TextBox.Text = Text; TextBox.Text = Text;
#endif
if( updateValueFromText )
{
if( ( error != null ) && ( InputValidationError != null ) )
{
InputValidationErrorEventArgs args = new InputValidationErrorEventArgs( error.Message );
InputValidationError( this, args );
}
}
_isSyncingTextAndValueProperties = false; _isSyncingTextAndValueProperties = false;
} }
#region Abstract #region Abstract
/// <summary>
/// Coerces the value.
/// </summary>
protected abstract T CoerceValue( T value );
/// <summary> /// <summary>
/// Converts the formatted text to a value. /// Converts the formatted text to a value.
/// </summary> /// </summary>
@ -360,12 +427,6 @@ namespace Xceed.Wpf.Toolkit.Primitives
/// </summary> /// </summary>
protected abstract void SetValidSpinDirection(); 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 //Abstract
#endregion //Methods #endregion //Methods

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

File diff suppressed because it is too large

57
ExtendedWPFToolkitSolution_35/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_35/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_35/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> /// <summary>

163
ExtendedWPFToolkitSolution_35/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_35/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_35/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_35/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
}
}

24
ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/DateTimePicker/Themes/Generic.xaml

@ -19,10 +19,10 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:local="clr-namespace:Xceed.Wpf.Toolkit" xmlns:local="clr-namespace:Xceed.Wpf.Toolkit"
xmlns:chrome="clr-namespace:Xceed.Wpf.Toolkit.Chromes" xmlns:chrome="clr-namespace:Xceed.Wpf.Toolkit.Chromes"
xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters" xmlns:conv="clr-namespace:Xceed.Wpf.Toolkit.Core.Converters">
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit">
<conv:InverseBoolConverter x:Key="InverseBoolConverter" /> <conv:InverseBoolConverter x:Key="InverseBoolConverter" />
@ -37,6 +37,13 @@
<GradientStop Color="#FF617584" Offset="1" /> <GradientStop Color="#FF617584" Offset="1" />
</LinearGradientBrush> </LinearGradientBrush>
<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 x:Key="PopupBackgroundBrush" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops> <LinearGradientBrush.GradientStops>
<GradientStopCollection> <GradientStopCollection>
@ -64,10 +71,15 @@
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" /> <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Grid x:Name="arrowGlyph" IsHitTestVisible="False" Grid.Column="1" Margin="5"> <Grid x:Name="arrowGlyph" IsHitTestVisible="False" Grid.Column="1" Margin="5">
<Path Width="7" Height="4" Data="M 0,1 C0,1 0,0 0,0 0,0 3,0 3,0 3,0 3,1 3,1 3,1 4,1 4,1 4,1 4,0 4,0 4,0 7,0 7,0 7,0 7,1 7,1 7,1 6,1 6,1 6,1 6,2 6,2 6,2 5,2 5,2 5,2 5,3 5,3 5,3 4,3 4,3 4,3 4,4 4,4 4,4 3,4 3,4 3,4 3,3 3,3 3,3 2,3 2,3 2,3 2,2 2,2 2,2 1,2 1,2 1,2 1,1 1,1 1,1 0,1 0,1 z" Fill="#FF000000" /> <Path x:Name="Arrow" Width="7" Height="4" Data="M 0,1 C0,1 0,0 0,0 0,0 3,0 3,0 3,0 3,1 3,1 3,1 4,1 4,1 4,1 4,0 4,0 4,0 7,0 7,0 7,0 7,1 7,1 7,1 6,1 6,1 6,1 6,2 6,2 6,2 5,2 5,2 5,2 5,3 5,3 5,3 4,3 4,3 4,3 4,4 4,4 4,4 3,4 3,4 3,4 3,3 3,3 3,3 2,3 2,3 2,3 2,2 2,2 2,2 1,2 1,2 1,2 1,1 1,1 1,1 0,1 0,1 z" Fill="#FF000000" />
</Grid> </Grid>
</Grid> </Grid>
</Grid> </Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Fill" TargetName="Arrow" Value="#AFAFAF" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>
@ -80,6 +92,7 @@
<Style TargetType="{x:Type local:DateTimePicker}"> <Style TargetType="{x:Type local:DateTimePicker}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" /> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="BorderThickness" Value="1" /> <Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{StaticResource DarkBorderBrush}" />
<Setter Property="Focusable" Value="False" /> <Setter Property="Focusable" Value="False" />
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" /> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="HorizontalContentAlignment" Value="Right" /> <Setter Property="HorizontalContentAlignment" Value="Right" />
@ -96,13 +109,14 @@
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<local:ButtonSpinner x:Name="Spinner" <local:ButtonSpinner x:Name="PART_Spinner"
IsTabStop="False" IsTabStop="False"
Background="{TemplateBinding Background}" Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}" BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
AllowSpin="{TemplateBinding AllowSpin}" AllowSpin="{TemplateBinding AllowSpin}"
ShowButtonSpinner="{TemplateBinding ShowButtonSpinner}"> ShowButtonSpinner="{TemplateBinding ShowButtonSpinner}">
<local:WatermarkTextBox x:Name="TextBox" <local:WatermarkTextBox x:Name="PART_TextBox"
BorderThickness="0" BorderThickness="0"
Background="Transparent" Background="Transparent"
FontFamily="{TemplateBinding FontFamily}" FontFamily="{TemplateBinding FontFamily}"

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

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

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

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

108
ExtendedWPFToolkitSolution_35/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_35/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_35/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_35/Src/WPFToolkit.Extended/MaskedTextBox/Implementation/MaskedTextBox.cs

File diff suppressed because it is too large

80
ExtendedWPFToolkitSolution_35/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 static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register( "ImageSource", typeof( ImageSource ), typeof( MessageBox ), new UIPropertyMetadata( default( ImageSource ) ) );
public ImageSource ImageSource public ImageSource ImageSource
{ {
@ -280,6 +345,14 @@ namespace Xceed.Wpf.Toolkit
ChangeVisualState( _button.ToString(), true ); 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(); SetDefaultResult();
} }
@ -318,7 +391,6 @@ namespace Xceed.Wpf.Toolkit
/// </summary> /// </summary>
/// <param name="messageText">A System.String that specifies the text to display.</param> /// <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="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> /// <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 ) public static MessageBoxResult Show( string messageText, string caption )
{ {
@ -696,6 +768,10 @@ namespace Xceed.Wpf.Toolkit
MessageBoxResult = MessageBoxResult.Yes; MessageBoxResult = MessageBoxResult.Yes;
break; break;
case PART_CloseButton: case PART_CloseButton:
MessageBoxResult = object.Equals( _button, MessageBoxButton.OK )
? MessageBoxResult.OK
: MessageBoxResult.Cancel;
break;
case PART_CancelButton: case PART_CancelButton:
MessageBoxResult = MessageBoxResult.Cancel; MessageBoxResult = MessageBoxResult.Cancel;
break; break;
@ -704,6 +780,8 @@ namespace Xceed.Wpf.Toolkit
break; break;
} }
e.Handled = true;
Close(); Close();
} }

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

@ -87,7 +87,13 @@
</ObjectAnimationUsingKeyFrames> </ObjectAnimationUsingKeyFrames>
</Storyboard> </Storyboard>
</VisualState> </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> </VisualStateManager.VisualStateGroups>
<Border x:Name="Background" CornerRadius="0,0,2,0" Background="{StaticResource WindowDarkBrush}"> <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 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="BorderThickness" Value="1" />
<Setter Property="CaptionForeground" Value="#FF000000" /> <Setter Property="CaptionForeground" Value="#FF000000" />
<Setter Property="CloseButtonStyle" Value="{StaticResource WindowCloseButtonStyle}" /> <Setter Property="CloseButtonStyle" Value="{StaticResource WindowCloseButtonStyle}" />
<Setter Property="ButtonRegionBackground" Value="#FFF0F0F0" />
<Setter Property="Focusable" Value="False" /> <Setter Property="Focusable" Value="False" />
<Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="HorizontalContentAlignment" Value="Left" /> <Setter Property="HorizontalContentAlignment" Value="Left" />
@ -218,10 +225,10 @@
<!-- Borders --> <!-- Borders -->
<Grid x:Name="MessageBoxWindowGrid"> <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}"> <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 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,0,0" Margin="1" Opacity="0.7" /> <Border BorderBrush="White" BorderThickness="1" CornerRadius="4,4,4,4" Margin="1" Opacity="0.7" />
</Grid> </Grid>
</Grid> </Grid>
@ -272,18 +279,20 @@
</Grid> </Grid>
<!-- Buttons --> <!-- Buttons -->
<Grid Grid.Row="1" HorizontalAlignment="Right" Margin="12,0,12,12"> <Border Grid.Row="1" Background="{TemplateBinding ButtonRegionBackground}" >
<Grid.ColumnDefinitions> <Grid HorizontalAlignment="Right" Margin="12">
<ColumnDefinition Width="Auto" /> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" />
<Button Grid.Column="0" x:Name="PART_YesButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding YesButtonContent}" /> </Grid.ColumnDefinitions>
<Button Grid.Column="1" x:Name="PART_NoButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding NoButtonContent}" /> <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="2" x:Name="PART_OkButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding OkButtonContent}" /> <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="3" x:Name="PART_CancelButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding CancelButtonContent}" IsCancel="True" /> <Button Grid.Column="2" x:Name="PART_OkButton" MinWidth="65" Margin="6,0,0,0" Visibility="Collapsed" Content="{TemplateBinding OkButtonContent}" Style="{TemplateBinding OkButtonStyle}"/>
</Grid> <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> </Grid>
</Border> </Border>
</Grid> </Grid>
@ -310,7 +319,7 @@
<!-- Close Button --> <!-- Close Button -->
<Border BorderBrush="#A5FFFFFF" BorderThickness="1,0,1,1" CornerRadius="0,0,3,3" VerticalAlignment="Top" Margin="0,1,7,0" HorizontalAlignment="Right"> <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" <Path Height="10"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"

55
ExtendedWPFToolkitSolution_35/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_35/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_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/DecimalUpDown.cs

@ -22,98 +22,32 @@ using System.Windows;
namespace Xceed.Wpf.Toolkit namespace Xceed.Wpf.Toolkit
{ {
public class DecimalUpDown : NumericUpDown<decimal?> public class DecimalUpDown : CommonNumericUpDown<decimal>
{ {
#region Constructors #region Constructors
static DecimalUpDown() static DecimalUpDown()
{ {
DefaultStyleKeyProperty.OverrideMetadata( typeof( DecimalUpDown ), new FrameworkPropertyMetadata( typeof( DecimalUpDown ) ) ); UpdateMetadata( typeof( DecimalUpDown ), default( decimal ), 1m, decimal.MinValue, decimal.MaxValue );
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 ) );
} }
#endregion //Constructors public DecimalUpDown()
: base( Decimal.Parse, (d) => d )
#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()
{ {
if( Value.HasValue )
Value -= Increment;
else
Value = DefaultValue;
} }
protected override decimal? ConvertTextToValue( string text ) #endregion //Constructors
{
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;
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; return value + increment;
if( Value < Maximum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( Value > Minimum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
} }
protected override void ValidateValue( decimal? value ) protected override decimal DecrementValue( decimal value, decimal increment )
{ {
if( value < Minimum ) return value - increment;
Value = Minimum;
else if( value > Maximum )
Value = Maximum;
} }
#endregion //Base Class Overrides #endregion //Base Class Overrides

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

@ -22,98 +22,32 @@ using System.Windows;
namespace Xceed.Wpf.Toolkit namespace Xceed.Wpf.Toolkit
{ {
public class DoubleUpDown : NumericUpDown<double?> public class DoubleUpDown : CommonNumericUpDown<double>
{ {
#region Constructors #region Constructors
static DoubleUpDown() static DoubleUpDown()
{ {
DefaultStyleKeyProperty.OverrideMetadata( typeof( DoubleUpDown ), new FrameworkPropertyMetadata( typeof( DoubleUpDown ) ) ); UpdateMetadata( typeof( DoubleUpDown ), default( double ), 1d, double.MinValue, double.MaxValue );
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 ) );
} }
#endregion //Constructors public DoubleUpDown()
: base( Double.Parse, Decimal.ToDouble )
#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()
{ {
if( Value.HasValue )
Value -= Increment;
else
Value = DefaultValue;
} }
protected override double? ConvertTextToValue( string text ) #endregion //Constructors
{
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;
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; return value + increment;
if( Value < Maximum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( Value > Minimum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
} }
protected override void ValidateValue( double? value ) protected override double DecrementValue( double value, double increment )
{ {
if( value < Minimum ) return value - increment;
Value = Minimum;
else if( value > Maximum )
Value = Maximum;
} }
#endregion //Base Class Overrides #endregion //Base Class Overrides

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

@ -22,99 +22,32 @@ using System.Windows;
namespace Xceed.Wpf.Toolkit namespace Xceed.Wpf.Toolkit
{ {
public class IntegerUpDown : NumericUpDown<int?> public class IntegerUpDown : CommonNumericUpDown<int>
{ {
#region Constructors #region Constructors
static IntegerUpDown() static IntegerUpDown()
{ {
DefaultStyleKeyProperty.OverrideMetadata( typeof( IntegerUpDown ), new FrameworkPropertyMetadata( typeof( IntegerUpDown ) ) ); UpdateMetadata( typeof( IntegerUpDown ), 0, 1, int.MinValue, int.MaxValue );
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 ) );
} }
#endregion //Constructors public IntegerUpDown()
: base( Int32.Parse, Decimal.ToInt32 )
#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()
{ {
if( Value.HasValue )
Value -= Increment;
else
Value = DefaultValue;
} }
protected override int? ConvertTextToValue( string text ) #endregion //Constructors
{
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;
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; return value + increment;
if( Value < Maximum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Increase;
if( Value > Minimum || !Value.HasValue )
validDirections = validDirections | ValidSpinDirections.Decrease;
if( Spinner != null )
Spinner.ValidSpinDirection = validDirections;
} }
protected override void ValidateValue( int? value ) protected override int DecrementValue( int value, int increment )
{ {
if( value < Minimum ) return value - increment;
Value = Minimum;
else if( value > Maximum )
Value = Maximum;
} }
#endregion //Base Class Overrides #endregion //Base Class Overrides

55
ExtendedWPFToolkitSolution_35/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_35/Src/WPFToolkit.Extended/NumericUpDown/Implementation/NumericUpDown.cs

@ -171,21 +171,6 @@ namespace Xceed.Wpf.Toolkit
#region Methods #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 ) protected static decimal ParsePercent( string text, IFormatProvider cultureInfo )
{ {
NumberFormatInfo info = NumberFormatInfo.GetInstance( cultureInfo ); NumberFormatInfo info = NumberFormatInfo.GetInstance( cultureInfo );

55
ExtendedWPFToolkitSolution_35/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_35/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_35/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_35/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_35/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_35/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_35/Src/WPFToolkit.Extended/NumericUpDown/Themes/Generic.xaml

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

726
ExtendedWPFToolkitSolution_35/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_35/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")]
[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.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.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.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")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.PropertyGrid.Attributes")] [assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.PropertyGrid.Attributes")]

92
ExtendedWPFToolkitSolution_35/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_35/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_35/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_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyGrid.cs

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

85
ExtendedWPFToolkitSolution_35/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 internal static T GetAttribute<T>( PropertyDescriptor property ) where T : Attribute
{ {
foreach( Attribute att in property.Attributes ) return property.Attributes.OfType<T>().FirstOrDefault();
{
var tAtt = att as T;
if( tAtt != null )
return tAtt;
}
return null;
} }
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 ); AttributeCollection attributes = TypeDescriptor.GetAttributes( instance );
propertyCollection.GroupBy( "Category" ); DefaultPropertyAttribute defaultPropertyAttribute =( DefaultPropertyAttribute )attributes[ typeof( DefaultPropertyAttribute ) ];
propertyCollection.SortBy( "Category", ListSortDirection.Ascending ); return defaultPropertyAttribute != null ? defaultPropertyAttribute.Name : null;
propertyCollection.SortBy( "PropertyOrder", ListSortDirection.Ascending );
propertyCollection.SortBy( "DisplayName", ListSortDirection.Ascending );
return propertyCollection;
} }
internal static PropertyDescriptorCollection GetPropertyDescriptors( object instance ) internal static PropertyDescriptorCollection GetPropertyDescriptors( object instance )
{ {
PropertyDescriptorCollection descriptors; PropertyDescriptorCollection descriptors;
@ -83,33 +66,31 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
return descriptors; 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, ValidatesOnExceptions = true,
ValidatesOnDataErrors = true, ValidatesOnDataErrors = true,
Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay Mode = propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay
}; };
propertyItem.SetBinding( PropertyItem.ValueProperty, binding ); propertyItem.SetBinding( PropertyItem.ValueProperty, binding );
propertyItem.Editor = PropertyGridUtilities.GetTypeEditor( propertyItem propertyItem.Editor = PropertyGridUtilities.GetTypeEditor( propertyItem, propertyParent.EditorDefinitions );
, grid.EditorDefinitions
);
return propertyItem; return propertyItem;
} }
internal static FrameworkElement GetTypeEditor( PropertyItem propertyItem internal static FrameworkElement GetTypeEditor(
, EditorDefinitionCollection editorDefinitions PropertyItem propertyItem,
) EditorDefinitionCollection editorDefinitions )
{ {
FrameworkElement editor = null; FrameworkElement editor = null;
@ -125,6 +106,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
if( editor == null ) if( editor == null )
editor = PropertyGridUtilities.CreateDefaultEditor( propertyItem ); editor = PropertyGridUtilities.CreateDefaultEditor( propertyItem );
editor.IsEnabled = !propertyItem.PropertyParent.IsReadOnly;
return editor; return editor;
} }
@ -188,6 +170,22 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
editor = new DoubleUpDownEditor(); editor = new DoubleUpDownEditor();
else if( propertyItem.PropertyType == typeof( int ) || propertyItem.PropertyType == typeof( int? ) ) else if( propertyItem.PropertyType == typeof( int ) || propertyItem.PropertyType == typeof( int? ) )
editor = new IntegerUpDownEditor(); 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? ) ) else if( propertyItem.PropertyType == typeof( DateTime ) || propertyItem.PropertyType == typeof( DateTime? ) )
editor = new DateTimeUpDownEditor(); editor = new DateTimeUpDownEditor();
else if( ( propertyItem.PropertyType == typeof( Color ) ) ) else if( ( propertyItem.PropertyType == typeof( Color ) ) )
@ -198,11 +196,16 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
editor = new TimeSpanEditor(); editor = new TimeSpanEditor();
else if( propertyItem.PropertyType == typeof( FontFamily ) || propertyItem.PropertyType == typeof( FontWeight ) || propertyItem.PropertyType == typeof( FontStyle ) || propertyItem.PropertyType == typeof( FontStretch ) ) else if( propertyItem.PropertyType == typeof( FontFamily ) || propertyItem.PropertyType == typeof( FontWeight ) || propertyItem.PropertyType == typeof( FontStyle ) || propertyItem.PropertyType == typeof( FontStretch ) )
editor = new FontComboBoxEditor(); 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 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 ) ) ) if( !listType.IsPrimitive && !listType.Equals( typeof( String ) ) )
editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.CollectionEditor(); 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(); editor = new Xceed.Wpf.Toolkit.PropertyGrid.Editors.PrimitiveTypeCollectionEditor();
} }
else 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 ); return editor.ResolveEditor( propertyItem );

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

@ -28,50 +28,73 @@ using System.Windows.Input;
using System.Windows.Markup.Primitives; using System.Windows.Markup.Primitives;
using Xceed.Wpf.Toolkit.PropertyGrid.Attributes; using Xceed.Wpf.Toolkit.PropertyGrid.Attributes;
using Xceed.Wpf.Toolkit.PropertyGrid.Commands; using Xceed.Wpf.Toolkit.PropertyGrid.Commands;
using System.Collections.ObjectModel;
using Xceed.Wpf.Toolkit.Core.Utilities;
namespace Xceed.Wpf.Toolkit.PropertyGrid namespace Xceed.Wpf.Toolkit.PropertyGrid
{ {
public class PropertyItem : Control public class PropertyItem : Control, INotifyPropertyChanged, IPropertyParent
{ {
#region Members #region Members
private DependencyPropertyDescriptor _dpDescriptor; private readonly DependencyPropertyDescriptor _dpDescriptor;
private MarkupObject _markupObject; 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 #endregion //Members
#region Properties #region Properties
public string BindingPath
{
get;
private set;
}
#region Category #region Category
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register( "Category", typeof( string ), typeof( PropertyItem ), new UIPropertyMetadata( string.Empty ) );
public string Category public string Category
{ {
get get
{ {
return ( string )GetValue( CategoryProperty ); return _category;
} }
set set
{ {
SetValue( CategoryProperty, value ); _propertyChangedHelper.HandleEqualityChanged( () => Category, ref _category, value );
} }
} }
#endregion //Category #endregion //Category
#region CategoryOrder
public int CategoryOrder
{
get
{
return _categoryOrder;
}
set
{
_propertyChangedHelper.HandleEqualityChanged( () => CategoryOrder, ref _categoryOrder, value );
}
}
#endregion // CategoryOrder
#region Description #region Description
public string Description public string Description
{ {
get get
{ {
return PropertyDescriptor.Description; return _description;
}
set
{
_propertyChangedHelper.HandleEqualityChanged( () => Description, ref _description, value );
} }
} }
@ -79,16 +102,15 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region DisplayName #region DisplayName
public static readonly DependencyProperty DisplayNameProperty = DependencyProperty.Register( "DisplayName", typeof( string ), typeof( PropertyItem ), new UIPropertyMetadata( null ) );
public string DisplayName public string DisplayName
{ {
get get
{ {
return ( string )GetValue( DisplayNameProperty ); return _displayName;
} }
set set
{ {
SetValue( DisplayNameProperty, value ); _propertyChangedHelper.HandleEqualityChanged( () => DisplayName, ref _displayName, value );
} }
} }
@ -129,18 +151,10 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region Instance #region Instance
private object _instance;
public object Instance public object Instance
{ {
get get;
{ private set;
return _instance;
}
private set
{
_instance = value;
_markupObject = MarkupWriter.GetMarkupObjectFor( _instance );
}
} }
#endregion //Instance #endregion //Instance
@ -154,7 +168,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{ {
get get
{ {
var dependencyObject = Instance as DependencyObject; var dependencyObject = PropertyParent.ValueInstance as DependencyObject;
if( dependencyObject != null && _dpDescriptor != null ) if( dependencyObject != null && _dpDescriptor != null )
return BindingOperations.GetBindingExpressionBase( dependencyObject, _dpDescriptor.DependencyProperty ) != 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 ) protected virtual void OnIsExpandedChanged( bool oldValue, bool newValue )
{ {
if( newValue && ( Properties == null || Properties.Count == 0 ) ) if( newValue && Properties.Count == 0 )
{ {
GetChildProperties(); GetChildProperties();
} }
@ -247,8 +261,10 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
public bool IsReadOnly public bool IsReadOnly
{ {
get; get
private set; {
return PropertyDescriptor.IsReadOnly;
}
} }
#region IsSelected #region IsSelected
@ -275,75 +291,66 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
protected virtual void OnIsSelectedChanged( bool oldValue, bool newValue ) protected virtual void OnIsSelectedChanged( bool oldValue, bool newValue )
{ {
if( newValue ) this.RaiseItemSelectionChangedEvent();
PropertyGrid.SelectedPropertyItem = this;
} }
#endregion //IsSelected #endregion //IsSelected
#region Level #region Level
public static readonly DependencyProperty LevelProperty = DependencyProperty.Register( "Level", typeof( int ), typeof( PropertyItem ), new UIPropertyMetadata( 0 ) );
public int Level public int Level
{ {
get get;
{ private set;
return ( int )GetValue( LevelProperty );
}
set
{
SetValue( LevelProperty, value );
}
} }
#endregion //Level #endregion //Level
#region Properties #region Properties
public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register( "Properties", typeof( PropertyItemCollection ), typeof( PropertyItem ), new UIPropertyMetadata( null ) );
public PropertyItemCollection Properties public PropertyItemCollection Properties
{ {
get get;
{ private set;
return ( PropertyItemCollection )GetValue( PropertiesProperty );
}
set
{
SetValue( PropertiesProperty, value );
}
} }
#endregion //Properties #endregion //Properties
#region PropertyDescriptor #region PropertyDescriptor
private PropertyDescriptor _propertyDescriptor;
public PropertyDescriptor PropertyDescriptor public PropertyDescriptor PropertyDescriptor
{ {
get get;
{ private set;
return _propertyDescriptor;
}
private set
{
_propertyDescriptor = value;
_dpDescriptor = DependencyPropertyDescriptor.FromProperty( _propertyDescriptor );
}
} }
#endregion //PropertyDescriptor #endregion //PropertyDescriptor
public PropertyGrid PropertyGrid #region PropertyParent
internal IPropertyParent PropertyParent
{ {
get; get;
private set; private set;
} }
#endregion
#region PropertyOrder
public int PropertyOrder public int PropertyOrder
{ {
get; get
set; {
} //maybe make a DP return _propertyOrder;
}
set
{
_propertyChangedHelper.HandleEqualityChanged( () => PropertyOrder, ref _propertyOrder, value );
}
}
#endregion
#region PropertyType #region PropertyType
@ -357,12 +364,16 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#endregion //PropertyType #endregion //PropertyType
#region ResetValueCommand
public ICommand ResetValueCommand public ICommand ResetValueCommand
{ {
get; get;
private set; private set;
} }
#endregion
#region Value #region Value
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof( object ), typeof( PropertyItem ), new UIPropertyMetadata( null, OnValueChanged ) ); 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 ) 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 get
{ {
var dependencyObject = Instance as DependencyObject; var dependencyObject = PropertyParent.ValueInstance as DependencyObject;
if( _dpDescriptor != null && dependencyObject != null ) if( _dpDescriptor != null && dependencyObject != null )
return DependencyPropertyHelper.GetValueSource( dependencyObject, _dpDescriptor.DependencyProperty ).BaseValueSource; return DependencyPropertyHelper.GetValueSource( dependencyObject, _dpDescriptor.DependencyProperty ).BaseValueSource;
@ -418,6 +429,25 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#endregion //Properties #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 #region Constructors
static PropertyItem() static PropertyItem()
@ -425,18 +455,26 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
DefaultStyleKeyProperty.OverrideMetadata( typeof( PropertyItem ), new FrameworkPropertyMetadata( typeof( PropertyItem ) ) ); 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; PropertyDescriptor = property;
PropertyGrid = propertyGrid;
Instance = instance;
BindingPath = bindingPath;
Level = level; Level = level;
SetPropertyDescriptorProperties();
ResolveParenthesisPropertyName(); Name = PropertyDescriptor.Name;
ResolveExpandableObject(); Category = PropertyDescriptor.Category;
ResolvePropertyOrder(); 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 ) ); CommandBindings.Add( new CommandBinding( PropertyItemCommands.ResetValue, ExecuteResetValueCommand, CanExecuteResetValueCommand ) );
AddHandler( Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler( PropertyItem_PreviewMouseDown ), true ); AddHandler( Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler( PropertyItem_PreviewMouseDown ), true );
@ -457,8 +495,8 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
private void ExecuteResetValueCommand( object sender, ExecutedRoutedEventArgs e ) private void ExecuteResetValueCommand( object sender, ExecutedRoutedEventArgs e )
{ {
if( PropertyDescriptor.CanResetValue( Instance ) ) if( PropertyDescriptor.CanResetValue( PropertyParent.ValueInstance ) )
PropertyDescriptor.ResetValue( Instance ); PropertyDescriptor.ResetValue( PropertyParent.ValueInstance );
//TODO: notify UI that the ValueSource may have changed to update the icon //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; bool canExecute = false;
if( PropertyDescriptor.CanResetValue( Instance ) && !PropertyDescriptor.IsReadOnly ) if( PropertyDescriptor.CanResetValue( PropertyParent.ValueInstance ) && !PropertyDescriptor.IsReadOnly )
{ {
canExecute = true; canExecute = true;
} }
@ -479,6 +517,14 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
#region Methods #region Methods
private void RaisePropertyChanged( string propertyName )
{
if( this.PropertyChanged != null )
{
this.PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}
private void GetChildProperties() private void GetChildProperties()
{ {
if( Value == null ) if( Value == null )
@ -494,7 +540,7 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
{ {
if( descriptor.IsBrowsable ) 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 ); propertyItems.Add( childPropertyItem );
} }
} }
@ -504,45 +550,89 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
//TODO: handle this some how //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 ) 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 ) if( attribute != null )
{ {
HasChildProperties = true; isExpandable = true;
IsReadOnly = true;
} }
return isExpandable;
} }
private void ResolvePropertyOrder() private int ResolvePropertyOrder()
{ {
var attrs = PropertyDescriptor.Attributes.OfType<PropertyOrderAttribute>(); var attribute = GetAttribute<PropertyOrderAttribute>();
if( attrs.Any() )
PropertyOrder = attrs.First().Order; // Max Value. Properties with no order will be displayed last.
else return ( attribute != null )
PropertyOrder = 0; ? attribute.Order
: int.MaxValue;
} }
private void SetPropertyDescriptorProperties() private T GetAttribute<T>() where T : Attribute
{ {
Name = PropertyDescriptor.Name; return PropertyGridUtilities.GetAttribute<T>( PropertyDescriptor );
DisplayName = PropertyDescriptor.DisplayName;
Category = PropertyDescriptor.Category;
IsReadOnly = PropertyDescriptor.IsReadOnly;
} }
#endregion //Methods #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_35/Src/WPFToolkit.Extended/PropertyGrid/Implementation/PropertyItemCollection.cs

@ -21,26 +21,23 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Windows.Data; using System.Windows.Data;
using System;
using System.Collections.Specialized;
using System.Diagnostics;
namespace Xceed.Wpf.Toolkit.PropertyGrid 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 ) public PropertyItemCollection(ObservableCollection<PropertyItem> editableCollection)
: base( list ) :base(editableCollection)
{ {
EditableCollection = editableCollection;
} }
public PropertyItemCollection( IEnumerable<PropertyItem> collection )
: base( collection )
{
} public ObservableCollection<PropertyItem> EditableCollection { get; private set; }
private ICollectionView GetDefaultView() private ICollectionView GetDefaultView()
{ {
@ -68,5 +65,52 @@ namespace Xceed.Wpf.Toolkit.PropertyGrid
return property.DisplayName.ToLower().StartsWith( text.ToLower() ); 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_35/Src/WPFToolkit.Extended/PropertyGrid/Themes/Generic.xaml

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

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

@ -37,7 +37,6 @@ namespace Xceed.Wpf.Toolkit
public RichTextBox() public RichTextBox()
{ {
Loaded += RichTextBox_Loaded;
} }
public RichTextBox( System.Windows.Documents.FlowDocument document ) public RichTextBox( System.Windows.Documents.FlowDocument document )
@ -126,6 +125,12 @@ namespace Xceed.Wpf.Toolkit
#region Methods #region Methods
protected override void OnTextChanged( System.Windows.Controls.TextChangedEventArgs e )
{
base.OnTextChanged( e );
UpdateText();
}
private void UpdateText() private void UpdateText()
{ {
_textSetInternally = true; _textSetInternally = true;
@ -145,26 +150,5 @@ namespace Xceed.Wpf.Toolkit
} }
#endregion //Methods #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
} }
} }

43
ExtendedWPFToolkitSolution_35/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

@ -193,6 +193,9 @@
<ItemGroup> <ItemGroup>
<Compile Include="AssemblyVersionInfo.cs" /> <Compile Include="AssemblyVersionInfo.cs" />
<Compile Include="AssemblyVersionInfoCommon.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="BusyIndicator\Implementation\BusyIndicator.cs" />
<Compile Include="ButtonSpinner\Implementation\ButtonSpinner.cs" /> <Compile Include="ButtonSpinner\Implementation\ButtonSpinner.cs" />
<Compile Include="CalculatorUpDown\Implementation\CalculatorUpDown.cs" /> <Compile Include="CalculatorUpDown\Implementation\CalculatorUpDown.cs" />
@ -209,6 +212,9 @@
<Compile Include="Chromes\Implementation\ButtonChrome.cs" /> <Compile Include="Chromes\Implementation\ButtonChrome.cs" />
<Compile Include="CollectionEditors\Implementation\CollectionEditor.cs" /> <Compile Include="CollectionEditors\Implementation\CollectionEditor.cs" />
<Compile Include="CheckComboBox\Implementation\CheckComboBox.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="Core\Converters\ObjectTypeToNameConverter.cs" />
<Compile Include="ColorCanvas\Implementation\ColorCanvas.cs" /> <Compile Include="ColorCanvas\Implementation\ColorCanvas.cs" />
<Compile Include="Core\Converters\CalculatorMemoryToVisibilityConverter.cs" /> <Compile Include="Core\Converters\CalculatorMemoryToVisibilityConverter.cs" />
@ -230,8 +236,11 @@
<Compile Include="Core\Primitives\Selector.cs" /> <Compile Include="Core\Primitives\Selector.cs" />
<Compile Include="Core\Primitives\SelectorItem.cs" /> <Compile Include="Core\Primitives\SelectorItem.cs" />
<Compile Include="Core\Primitives\ShapeBase.cs" /> <Compile Include="Core\Primitives\ShapeBase.cs" />
<Compile Include="Core\Primitives\ValueRangeTextBox.cs" />
<Compile Include="Core\PropertyChangedEventArgs.cs" /> <Compile Include="Core\PropertyChangedEventArgs.cs" />
<Compile Include="Core\PropertyChangedEventHandler.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\Themes\StaticResourceKey.cs" />
<Compile Include="Core\Utilities\CalculatorUtilities.cs" /> <Compile Include="Core\Utilities\CalculatorUtilities.cs" />
<Compile Include="Core\Utilities\ColorUtilities.cs" /> <Compile Include="Core\Utilities\ColorUtilities.cs" />
@ -240,10 +249,14 @@
<Compile Include="Core\Converters\InverseBoolConverter.cs" /> <Compile Include="Core\Converters\InverseBoolConverter.cs" />
<Compile Include="Core\Converters\SolidColorBrushToColorConverter.cs" /> <Compile Include="Core\Converters\SolidColorBrushToColorConverter.cs" />
<Compile Include="Core\Utilities\ContextMenuUtilities.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\DoubleHelper.cs" />
<Compile Include="Core\Utilities\EllipseHelper.cs" /> <Compile Include="Core\Utilities\EllipseHelper.cs" />
<Compile Include="Core\Utilities\NotifyPropertyChangedHelper.cs" />
<Compile Include="Core\Utilities\PointHelper.cs" /> <Compile Include="Core\Utilities\PointHelper.cs" />
<Compile Include="Core\Utilities\RectHelper.cs" /> <Compile Include="Core\Utilities\RectHelper.cs" />
<Compile Include="Core\Utilities\ReflectionHelper.cs" />
<Compile Include="Core\Utilities\ResourceHelper.cs" /> <Compile Include="Core\Utilities\ResourceHelper.cs" />
<Compile Include="Core\Utilities\Segment.cs" /> <Compile Include="Core\Utilities\Segment.cs" />
<Compile Include="Core\Utilities\VisualTreeHelperEx.cs" /> <Compile Include="Core\Utilities\VisualTreeHelperEx.cs" />
@ -255,9 +268,19 @@
<Compile Include="DateTimeUpDown\Implementation\DateTimeParser.cs" /> <Compile Include="DateTimeUpDown\Implementation\DateTimeParser.cs" />
<Compile Include="DropDownButton\Implementation\DropDownButton.cs" /> <Compile Include="DropDownButton\Implementation\DropDownButton.cs" />
<Compile Include="Magnifier\Implementation\FrameType.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="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\DecimalUpDown.cs" />
<Compile Include="NumericUpDown\Implementation\DoubleUpDown.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="NumericUpDown\Implementation\IntegerUpDown.cs" />
<Compile Include="Magnifier\Implementation\Converters\BorderThicknessToStrokeThicknessConverter.cs" /> <Compile Include="Magnifier\Implementation\Converters\BorderThicknessToStrokeThicknessConverter.cs" />
<Compile Include="Magnifier\Implementation\Converters\RadiusConverter.cs" /> <Compile Include="Magnifier\Implementation\Converters\RadiusConverter.cs" />
@ -265,10 +288,19 @@
<Compile Include="Magnifier\Implementation\MagnifierAdorner.cs" /> <Compile Include="Magnifier\Implementation\MagnifierAdorner.cs" />
<Compile Include="Magnifier\Implementation\MagnifierManager.cs" /> <Compile Include="Magnifier\Implementation\MagnifierManager.cs" />
<Compile Include="Core\Primitives\InputBase.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="MessageBox\Implementation\MessageBox.cs" />
<Compile Include="NumericUpDown\Implementation\LongUpDown.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="NumericUpDown\Implementation\NumericUpDown.cs" /> <Compile Include="NumericUpDown\Implementation\NumericUpDown.cs" />
<Compile Include="CollectionEditors\Implementation\PrimitiveTypeCollectionEditor.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\Pie.cs" />
<Compile Include="Pie\Implementation\PieModeEnum.cs" /> <Compile Include="Pie\Implementation\PieModeEnum.cs" />
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
@ -280,6 +312,7 @@
<Compile Include="PropertyGrid\Implementation\Attributes\ItemsSourceAttribute.cs" /> <Compile Include="PropertyGrid\Implementation\Attributes\ItemsSourceAttribute.cs" />
<Compile Include="PropertyGrid\Implementation\Attributes\PropertyOrderAttribute.cs" /> <Compile Include="PropertyGrid\Implementation\Attributes\PropertyOrderAttribute.cs" />
<Compile Include="PropertyGrid\Implementation\Commands\PropertyGridCommands.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\ValueSourceToImagePathConverter.cs" />
<Compile Include="PropertyGrid\Implementation\Converters\ValueSourceToToolTipConverter.cs" /> <Compile Include="PropertyGrid\Implementation\Converters\ValueSourceToToolTipConverter.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\CheckBoxEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\CheckBoxEditor.cs" />
@ -293,20 +326,18 @@
<Compile Include="PropertyGrid\Implementation\Editors\ComboBoxEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\ComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\EditorDefinition.cs" /> <Compile Include="PropertyGrid\Implementation\EditorDefinition.cs" />
<Compile Include="PropertyGrid\Implementation\EditorDefinitionCollection.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\EnumComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\FontComboBoxEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\FontComboBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ItemsSourceAttributeEditor.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\TimeSpanEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\IntegerUpDownEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\ITypeEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\ITypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\PrimitiveTypeCollectionEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\PrimitiveTypeCollectionEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBlockEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\TextBlockEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TextBoxEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\TextBoxEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Editors\TypeEditor.cs" /> <Compile Include="PropertyGrid\Implementation\Editors\TypeEditor.cs" />
<Compile Include="PropertyGrid\Implementation\Converters\ExpandableObjectMarginConverter.cs" /> <Compile Include="PropertyGrid\Implementation\Converters\ExpandableObjectMarginConverter.cs" />
<Compile Include="PropertyGrid\Implementation\IPropertyParent.cs" />
<Compile Include="PropertyGrid\Implementation\PropertyDefinition.cs" /> <Compile Include="PropertyGrid\Implementation\PropertyDefinition.cs" />
<Compile Include="PropertyGrid\Implementation\PropertyDefinitionCollection.cs" /> <Compile Include="PropertyGrid\Implementation\PropertyDefinitionCollection.cs" />
<Compile Include="PropertyGrid\Implementation\PropertyGrid.cs" /> <Compile Include="PropertyGrid\Implementation\PropertyGrid.cs" />
@ -334,7 +365,6 @@
<Compile Include="TimePicker\Implementation\TimeFormat.cs" /> <Compile Include="TimePicker\Implementation\TimeFormat.cs" />
<Compile Include="TimePicker\Implementation\TimeItem.cs" /> <Compile Include="TimePicker\Implementation\TimeItem.cs" />
<Compile Include="TimePicker\Implementation\TimePicker.cs" /> <Compile Include="TimePicker\Implementation\TimePicker.cs" />
<Compile Include="Utils\Exceptions\ThrowException.cs" />
<Compile Include="VisualStates.cs" /> <Compile Include="VisualStates.cs" />
<Compile Include="MessageBox\Implementation\VisualStates.MessageBox.cs" /> <Compile Include="MessageBox\Implementation\VisualStates.MessageBox.cs" />
<Compile Include="WatermarkTextBox\Implementation\WatermarkTextBox.cs" /> <Compile Include="WatermarkTextBox\Implementation\WatermarkTextBox.cs" />
@ -433,6 +463,7 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
</PropertyGroup> </PropertyGroup>

Loading…
Cancel
Save