All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

724 lines
19 KiB

/*************************************************************************************
Toolkit for WPF
Copyright (C) 2007-2020 Xceed Software Inc.
This program is provided to you under the terms of the XCEED SOFTWARE, INC.
COMMUNITY LICENSE AGREEMENT (for non-commercial use) as published at
https://github.com/xceedsoftware/wpftoolkit/blob/master/license.md
For more features, controls, and fast professional support,
pick up the Plus Edition at https://xceed.com/xceed-toolkit-plus-for-wpf/
Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids
***********************************************************************************/
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 )
{
UpdateMaskProvider( 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 )
{
UpdateMaskProvider( 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 )
{
UpdateMaskProvider( 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 )
{
UpdateMaskProvider( 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();
UpdateMaskProvider( 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 UpdateMaskProvider( 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
}
}