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
{
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string BaseVersion = "1.7";
public const string BaseVersion = "1.8";
[System.Diagnostics.CodeAnalysis.SuppressMessage( "Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields" )]
public const string Version = BaseVersion +
_XceedVersionInfoCommon.Build;

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

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

2
ExtendedWPFToolkitSolution_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">
<Rectangle x:Name="SelectedColor" Fill="{Binding SelectedColor, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ColorToSolidColorBrushConverter}}" />
</Border>
<TextBox Grid.Column="1" Text="{Binding HexadecimalString, RelativeSource={RelativeSource TemplatedParent}}" Margin="2,0,2,0" VerticalAlignment="Center" Style="{StaticResource ColorCanvasTextBoxStyle}" />
<TextBox x:Name="PART_HexadecimalTextBox" Grid.Column="1" Margin="2,0,2,0" VerticalAlignment="Center" Style="{StaticResource ColorCanvasTextBoxStyle}" />
</Grid>
</Border>

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

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

4
ExtendedWPFToolkitSolution_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 )
{
Visibility wizardVisibility = ( Visibility )values[ 0 ];
WizardPageButtonVisibility wizardPageVisibility = ( WizardPageButtonVisibility )values[ 1 ];
WizardPageButtonVisibility wizardPageVisibility = ( (values[ 1 ] == null) || (values[ 1 ] == DependencyProperty.UnsetValue) )
? WizardPageButtonVisibility.Hidden
: ( WizardPageButtonVisibility )values[ 1 ];
Visibility visibility = Visibility.Visible;

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

12
ExtendedWPFToolkitSolution_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 )
{
if( newValue )
RaiseSelectionChangedEvent( new RoutedEventArgs( Selector.SelectedEvent, this ) );
this.RaiseEvent( new RoutedEventArgs( Selector.SelectedEvent, this ) );
else
RaiseSelectionChangedEvent( new RoutedEventArgs( Selector.UnSelectedEvent, this ) );
this.RaiseEvent( new RoutedEventArgs( Selector.UnSelectedEvent, this ) );
}
internal Selector ParentSelector
@ -95,13 +95,5 @@ namespace Xceed.Wpf.Toolkit.Primitives
#endregion //Event Hanlders
#region Methods
private void RaiseSelectionChangedEvent( RoutedEventArgs e )
{
base.RaiseEvent( e );
}
#endregion //Methods
}
}

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

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

1192
ExtendedWPFToolkitSolution_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>

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

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

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

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

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

108
ExtendedWPFToolkitSolution_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 ImageSource ImageSource
{
@ -280,6 +345,14 @@ namespace Xceed.Wpf.Toolkit
ChangeVisualState( _button.ToString(), true );
Button closeButton = GetMessageBoxButton( PART_CloseButton );
if( closeButton != null )
closeButton.IsEnabled = !object.Equals( _button, MessageBoxButton.YesNo );
Button okButton = GetMessageBoxButton( PART_OkButton );
if( okButton != null )
okButton.IsCancel = object.Equals( _button, MessageBoxButton.OK );
SetDefaultResult();
}
@ -318,7 +391,6 @@ namespace Xceed.Wpf.Toolkit
/// </summary>
/// <param name="messageText">A System.String that specifies the text to display.</param>
/// <param name="caption">A System.String that specifies the title bar caption to display.</param>
/// <param name="messageBoxStyle">A Style that will be applied to the MessageBox instance.</param>
/// <returns>A System.Windows.MessageBoxResult value that specifies which message box button is clicked by the user.</returns>
public static MessageBoxResult Show( string messageText, string caption )
{
@ -696,6 +768,10 @@ namespace Xceed.Wpf.Toolkit
MessageBoxResult = MessageBoxResult.Yes;
break;
case PART_CloseButton:
MessageBoxResult = object.Equals( _button, MessageBoxButton.OK )
? MessageBoxResult.OK
: MessageBoxResult.Cancel;
break;
case PART_CancelButton:
MessageBoxResult = MessageBoxResult.Cancel;
break;
@ -704,6 +780,8 @@ namespace Xceed.Wpf.Toolkit
break;
}
e.Handled = true;
Close();
}

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

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

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

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

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

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

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

55
ExtendedWPFToolkitSolution_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
protected static decimal ParseDecimal( string text, IFormatProvider cultureInfo )
{
return Decimal.Parse( text, NumberStyles.Any, cultureInfo );
}
protected static double ParseDouble( string text, IFormatProvider cultureInfo )
{
return Double.Parse( text, NumberStyles.Any, cultureInfo );
}
protected static int ParseInt( string text, IFormatProvider cultureInfo )
{
return Int32.Parse( text, NumberStyles.Any, cultureInfo );
}
protected static decimal ParsePercent( string text, IFormatProvider cultureInfo )
{
NumberFormatInfo info = NumberFormatInfo.GetInstance( cultureInfo );

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

726
ExtendedWPFToolkitSolution_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.Core.Converters" )]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Core.Input" )]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Core.Utilities")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Chromes")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.Primitives")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.PropertyGrid")]
[assembly: XmlnsDefinition("http://schemas.xceed.com/wpf/xaml/toolkit", "Xceed.Wpf.Toolkit.PropertyGrid.Attributes")]

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

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

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

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

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

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

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

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

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

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

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

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

Loading…
Cancel
Save