PasswordBox.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / PasswordBox.cs / 1305600 / PasswordBox.cs

                            //---------------------------------------------------------------------------- 
//
// File: PasswordBox.cs
//
// Copyright (C) Microsoft Corporation.  All rights reserved. 
//
// Description: The stock password control. 
// 
//---------------------------------------------------------------------------
 
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Globalization; 
using System.Security;
using System.Text; 
using System.Windows.Media; 
using System.Windows.Data;
using System.Windows.Documents; 
using System.Windows.Automation;
using System.Windows.Automation.Peers;
using System.Windows.Input;
using System.Windows.Navigation; 
using System.Windows.Shapes;
using System.Windows.Threading; 
using MS.Internal; 
using MS.Internal.KnownBoxes;
using System.Security.Permissions; 
using System.Windows.Controls.Primitives;

#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Controls
{ 
    ///  
    /// The stock password control.
    ///  
#if OLD_AUTOMATION
    [Automation(AccessibilityControlType = "Edit")]
#endif
    [TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))] 
    public sealed class PasswordBox : Control, ITextBoxViewHost
#if OLD_AUTOMATION 
        , IAutomationPatternProvider, IAutomationPropertyProvider 
#endif
    { 
        //-----------------------------------------------------
        //
        //  Constructors
        // 
        //-----------------------------------------------------
 
        #region Constructors 

        ///  
        /// Static constructor for PasswordBox.
        /// 
        static PasswordBox()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(typeof(PasswordBox)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(PasswordBox)); 
 
            // PasswordBox properties
            // ------------------ 
            PasswordCharProperty.OverrideMetadata(typeof(PasswordBox),
                    new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPasswordCharChanged)));

            // Declaree listener for Padding property 
            Control.PaddingProperty.OverrideMetadata(typeof(PasswordBox),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPaddingChanged))); 
 
            // Prevent journaling
            NavigationService.NavigationServiceProperty.OverrideMetadata(typeof(PasswordBox), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnParentNavigationServiceChanged))); 

            InputMethod.IsInputMethodEnabledProperty.OverrideMetadata(typeof(PasswordBox),
                    new FrameworkPropertyMetadata(
                            BooleanBoxes.FalseBox, 
                            FrameworkPropertyMetadataOptions.Inherits,
                            null, 
                            // 

                            new CoerceValueCallback(ForceToFalse))); 

            // VSM
            IsEnabledProperty.OverrideMetadata(typeof(PasswordBox), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged)));
            IsMouseOverPropertyKey.OverrideMetadata(typeof(PasswordBox), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); 

            TextBoxBase.SelectionBrushProperty.OverrideMetadata(typeof(PasswordBox), 
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); 
            TextBoxBase.SelectionOpacityProperty.OverrideMetadata(typeof(PasswordBox),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement))); 
            TextBoxBase.CaretBrushProperty.OverrideMetadata(typeof(PasswordBox),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement)));
        }
 
        /// 
        /// Constructor. 
        ///  
        public PasswordBox() : base()
        { 
            Initialize();
        }

        #endregion Constructors 

        //------------------------------------------------------ 
        // 
        //  Public Methods
        // 
        //-----------------------------------------------------

        #region Public Methods
 
        /// 
        /// Replaces the current selection in the passwordbox with the contents 
        /// of the Clipboard 
        /// 
        public void Paste() 
        {
            RoutedCommand command = ApplicationCommands.Paste;
            command.Execute(null, this);
        } 

        ///  
        /// Select all text in the PasswordBox 
        /// 
        public void SelectAll() 
        {
            Selection.Select(TextContainer.Start, TextContainer.End);
        }
 
        /// 
        /// Clear all the content in the PasswordBox control. 
        ///  
        public void Clear()
        { 
            this.Password = String.Empty;
        }

        #endregion Public Methods 

        //------------------------------------------------------ 
        // 
        //  Public Properties
        // 
        //------------------------------------------------------

        #region Public Properties
 
        /// 
        /// Contents of the PasswordBox. 
        ///  
        /// 
        /// Use the SecurePassword property in place of this one when possible. 
        /// Doing so reduces the risk of revealing content that should be kept secret.
        /// 
        /// 
        /// Critical - The getter elevates to unmanaged code and has unsafe code block. 
        ///            The setter calls SetSecurePassword.
        /// 
        /// PublicOK: Does not pass unsafe data to native code. 
        ///           Does not pass 2nd party SecureString to SetSecurePassword.
        /// 
        /// 
        [DefaultValue("")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string Password 
        {
            [SecurityCritical] 
            get 
            {
                string password; 

                using (SecureString securePassword = this.SecurePassword)
                {
                    IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(securePassword); 

                    try 
                    { 
                        unsafe
                        { 
                            password = new string((char*)ptr);
                        }
                    }
                    finally 
                    {
                        System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr); 
                    } 
                }
 
                return password;
            }

            [SecurityCritical] 
            set
            { 
                if (value == null) 
                {
                    value = String.Empty; 
                }

                using (SecureString securePassword = new SecureString())
                { 
                    #pragma warning suppress 6506 // value is set to String.Empty if it was null.
                    for (int i = 0; i < value.Length; i++) 
                    { 
                        securePassword.AppendChar(value[i]);
                    } 

                    SetSecurePassword(securePassword);
                }
            } 
        }
 
        ///  
        /// Contents of the PasswordBox.
        ///  
        /// 
        /// Reading the Password always returns a copy which may be safely
        /// Disposed.
        /// 
        /// Setting the value always stores a copy of the supplied value.
        ///  
        ///  
        /// Do not add public setter, see SetSecurePassword comments.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public SecureString SecurePassword
        {
            get 
            {
                return this.TextContainer.GetPasswordCopy(); 
            } 
        }
 
        /// 
        /// The DependencyID for the PasswordChar property.
        /// Default Value:     '*'
        ///  
        public static readonly DependencyProperty PasswordCharProperty =
                DependencyProperty.RegisterAttached( 
                        "PasswordChar", // Property name 
                        typeof(char), // Property type
                        typeof(PasswordBox), // Property owner 
                        new FrameworkPropertyMetadata('*')); // Flags

        /// 
        /// Character to display instead of the actual password. 
        /// 
        public char PasswordChar 
        { 
            get { return (char) GetValue(PasswordCharProperty); }
            set { SetValue(PasswordCharProperty, value); } 
        }

        /// 
        /// The limit number of characters that the PasswordBox or other editable controls can contain. 
        /// if it is 0, means no-limitation.
        /// User can set this value for some simple single line PasswordBox to restrict the text number. 
        /// By default it is 0. 
        /// 
        ///  
        /// When this property is set to zero, the maximum length of the text that can be entered
        /// in the control is limited only by available memory. You can use this property to restrict
        /// the length of text entered in the control for values such as postal codes and telephone numbers.
        /// You can also use this property to restrict the length of text entered when the data is to be entered 
        /// in a database.
        /// You can limit the text entered into the control to the maximum length of the corresponding field in the database. 
        /// Note:   In code, you can set the value of the Text property to a value that is larger than 
        /// the value specified by the MaxLength property.
        /// This property only affects text entered into the control at runtime. 
        /// 
        public static readonly DependencyProperty MaxLengthProperty =
                TextBox.MaxLengthProperty.AddOwner(typeof(PasswordBox));
 

        ///  
        /// Maximum number of characters the PasswordBox can accept 
        /// 
        [DefaultValue((int)0)] 
        public int MaxLength
        {
            get { return (int) GetValue(MaxLengthProperty); }
            set { SetValue(MaxLengthProperty, value); } 
        }
 
        ///  
        /// 
        ///  
        public static readonly DependencyProperty SelectionBrushProperty =
            TextBoxBase.SelectionBrushProperty.AddOwner(typeof(PasswordBox));

        ///  
        /// 
        ///  
        public Brush SelectionBrush 
        {
            get { return (Brush)GetValue(SelectionBrushProperty); } 
            set { SetValue(SelectionBrushProperty, value); }
        }

        ///  
        /// 
        ///  
        public static readonly DependencyProperty SelectionOpacityProperty = 
            TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(PasswordBox));
 
        /// 
        /// 
        /// 
        public double SelectionOpacity 
        {
            get { return (double)GetValue(SelectionOpacityProperty); } 
            set { SetValue(SelectionOpacityProperty, value); } 
        }
 
        /// 
        /// 
        /// 
        public static readonly DependencyProperty CaretBrushProperty = 
            TextBoxBase.CaretBrushProperty.AddOwner(typeof(PasswordBox));
 
        ///  
        /// 
        ///  
        public Brush CaretBrush
        {
            get { return (Brush)GetValue(CaretBrushProperty); }
            set { SetValue(CaretBrushProperty, value); } 
        }
 
        #endregion Public Properties 

        //----------------------------------------------------- 
        //
        //  Public Events
        //
        //------------------------------------------------------ 

        #region Public Events 
 
        /// 
        /// Event for "Text has changed" 
        /// 
        /// 
        /// Unlike most RoutedEvents on Controls, PasswordChangedEvent does not
        /// have a matching protected virtual OnPasswordChanged method -- 
        /// because PasswordBox is sealed.
        ///  
        public static readonly RoutedEvent PasswordChangedEvent = EventManager.RegisterRoutedEvent( 
            "PasswordChanged", // Event name
            RoutingStrategy.Bubble, // 
            typeof(RoutedEventHandler), //
            typeof(PasswordBox)); //

        ///  
        /// Event fired from this text box when its inner content
        /// has been changed. 
        ///  
        /// 
        /// It is redirected from inner TextContainer.Changed event. 
        /// 
        public event RoutedEventHandler PasswordChanged
        {
            add 
            {
                AddHandler(PasswordChangedEvent, value); 
            } 

            remove 
            {
                RemoveHandler(PasswordChangedEvent, value);
            }
        } 

        #endregion Public Events 
 
        //-----------------------------------------------------
        // 
        //  Protected Methods
        //
        //-----------------------------------------------------
 
        #region Protected Methods
 
        internal override void ChangeVisualState(bool useTransitions) 
        {
            if (!IsEnabled) 
            {
                VisualStates.GoToState(this, useTransitions, VisualStates.StateDisabled, VisualStates.StateNormal);
            }
            else if (IsMouseOver) 
            {
                VisualStates.GoToState(this, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal); 
            } 
            else
            { 
                VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions);
            }

            if (IsKeyboardFocused) 
            {
                VisualStates.GoToState(this, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused); 
            } 
            else
            { 
                VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions);
            }

            base.ChangeVisualState(useTransitions); 
        }
 
        ///  
        /// Creates AutomationPeer ()
        ///  
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            return new PasswordBoxAutomationPeer(this);
        } 

        ///  
        /// Called when the Template's tree has been generated 
        /// 
        public override void OnApplyTemplate() 
        {
            base.OnApplyTemplate();
            AttachToVisualTree();
        } 

        ///  
        /// Template has changed 
        /// 
        ///  
        /// 
        /// 
        /// 
        protected override void OnTemplateChanged(ControlTemplate oldTemplate, ControlTemplate newTemplate) 
        {
            base.OnTemplateChanged(oldTemplate, newTemplate); 
 
            if (oldTemplate!=null && newTemplate!= null && oldTemplate.VisualTree != newTemplate.VisualTree)
            { 
                DetachFromVisualTree();
            }
        }
 
        ///
        ///  
        /// 
        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        { 
            //  always call base.OnPropertyChanged, otherwise Property Engine will not work.
            base.OnPropertyChanged(e);

            if (this.RenderScope != null) 
            {
                FrameworkPropertyMetadata fmetadata = e.Property.GetMetadata(typeof(PasswordBox)) as FrameworkPropertyMetadata; 
                if (fmetadata != null) 
                {
                    if (e.IsAValueChange || e.IsASubPropertyChange) 
                    {
                        if (fmetadata.AffectsMeasure || fmetadata.AffectsArrange ||
                            fmetadata.AffectsParentMeasure || fmetadata.AffectsParentArrange ||
                            e.Property == Control.HorizontalContentAlignmentProperty || e.Property == Control.VerticalContentAlignmentProperty) 
                        {
                            ((TextBoxView)this.RenderScope).Remeasure(); 
                        } 
                        else if (fmetadata.AffectsRender &&
                                (e.IsAValueChange || !fmetadata.SubPropertiesDoNotAffectRender)) 
                        {
                            ((TextBoxView)this.RenderScope).Rerender();
                        }
                    } 
                }
            } 
        } 

        ///  
        ///     Virtual method reporting a key was pressed
        /// 
        protected override void OnKeyDown(KeyEventArgs e)
        { 
            base.OnKeyDown(e);
 
            if (e.Handled) 
            {
                return; 
            }

            _textEditor.OnKeyDown(e);
        } 

        ///  
        ///     Virtual method reporting a key was released 
        /// 
        protected override void OnKeyUp(KeyEventArgs e) 
        {
            base.OnKeyUp(e);

            if (e.Handled) 
            {
                return; 
            } 

            _textEditor.OnKeyUp(e); 
        }

        /// 
        ///     Virtual method reporting text composition 
        /// 
        protected override void OnTextInput(TextCompositionEventArgs e) 
        { 
            base.OnTextInput(e);
 
            if (e.Handled)
            {
                return;
            } 

            _textEditor.OnTextInput(e); 
        } 

        ///  
        ///     Virtual method reporting the mouse button was pressed
        /// 
        protected override void OnMouseDown(MouseButtonEventArgs e)
        { 
            base.OnMouseDown(e);
 
            if (e.Handled) 
            {
                return; 
            }

            _textEditor.OnMouseDown(e);
        } 

        ///  
        ///     Virtual method reporting a mouse move 
        /// 
        protected override void OnMouseMove(MouseEventArgs e) 
        {
            base.OnMouseMove(e);

            if (e.Handled) 
            {
                return; 
            } 

            _textEditor.OnMouseMove(e); 
        }

        /// 
        ///     Virtual method reporting the mouse button was released 
        /// 
        protected override void OnMouseUp(MouseButtonEventArgs e) 
        { 
            base.OnMouseUp(e);
 
            if (e.Handled)
            {
                return;
            } 

            _textEditor.OnMouseUp(e); 
        } 

        ///  
        ///     Virtual method reporting the cursor to display was requested
        /// 
        protected override void OnQueryCursor(QueryCursorEventArgs e)
        { 
            base.OnQueryCursor(e);
 
            if (e.Handled) 
            {
                return; 
            }

            _textEditor.OnQueryCursor(e);
        } 

        ///  
        ///     Virtual method reporting the query continue drag is going to happen 
        /// 
        protected override void OnQueryContinueDrag(QueryContinueDragEventArgs e) 
        {
            base.OnQueryContinueDrag(e);

            if (e.Handled) 
            {
                return; 
            } 

            _textEditor.OnQueryContinueDrag(e); 
        }

        /// 
        ///     Virtual method reporting the give feedback is going to happen 
        /// 
        protected override void OnGiveFeedback(GiveFeedbackEventArgs e) 
        { 
            base.OnGiveFeedback(e);
 
            if (e.Handled)
            {
                return;
            } 

            _textEditor.OnGiveFeedback(e); 
        } 

        ///  
        ///     Virtual method reporting the drag enter is going to happen
        /// 
        protected override void OnDragEnter(DragEventArgs e)
        { 
            base.OnDragEnter(e);
 
            if (e.Handled) 
            {
                return; 
            }

            _textEditor.OnDragEnter(e);
        } 

        ///  
        ///     Virtual method reporting the drag over is going to happen 
        /// 
        protected override void OnDragOver(DragEventArgs e) 
        {
            base.OnDragOver(e);

            if (e.Handled) 
            {
                return; 
            } 

            _textEditor.OnDragOver(e); 
        }

        /// 
        ///     Virtual method reporting the drag leave is going to happen 
        /// 
        protected override void OnDragLeave(DragEventArgs e) 
        { 
            base.OnDragLeave(e);
 
            if (e.Handled)
            {
                return;
            } 

            _textEditor.OnDragLeave(e); 
        } 

        ///  
        ///     Virtual method reporting the drag enter is going to happen
        /// 
        protected override void OnDrop(DragEventArgs e)
        { 
            base.OnDrop(e);
 
            if (e.Handled) 
            {
                return; 
            }

            _textEditor.OnDrop(e);
        } 

        ///  
        ///     Called when ContextMenuOpening is raised on this element. 
        /// 
        /// Event arguments 
        protected override void OnContextMenuOpening(ContextMenuEventArgs e)
        {
            base.OnContextMenuOpening(e);
 
            if (e.Handled)
            { 
                return; 
            }
 
            _textEditor.OnContextMenuOpening(e);
        }

        ///  
        ///     Virtual method reporting that the keyboard is focused on this element
        ///  
        protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) 
        {
            base.OnGotKeyboardFocus(e); 

            if (e.Handled)
            {
                return; 
            }
 
            _textEditor.OnGotKeyboardFocus(e); 
        }
 
        /// 
        ///     Virtual method reporting that the keyboard is no longer focusekeyboard is no longer focuseed
        /// 
        protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) 
        {
            base.OnLostKeyboardFocus(e); 
 
            if (e.Handled)
            { 
                return;
            }

            _textEditor.OnLostKeyboardFocus(e); 
        }
 
        ///  
        ///     This method is invoked when the IsFocused property changes to false
        ///  
        /// RoutedEventArgs
        protected override void OnLostFocus(RoutedEventArgs e)
        {
            base.OnLostFocus(e); 

            if (e.Handled) 
            { 
                return;
            } 

            _textEditor.OnLostFocus(e);
        }
 
        #endregion Protected Methods
 
        //----------------------------------------------------- 
        //
        //  Internal Properties 
        //
        //------------------------------------------------------

        #region Internal Properties 

        // A TextContainer covering the PasswordBox's inner content. 
        internal PasswordTextContainer TextContainer 
        {
            get 
            {
                return _textContainer;
            }
        } 

        ///  
        /// readonly access to internal content control 
        /// 
        internal FrameworkElement RenderScope 
        {
            get
            {
                return _renderScope; 
            }
        } 
 
        internal ScrollViewer ScrollViewer
        { 
            get
            {
                if (_scrollViewer == null)
                { 
                    if (_textEditor != null)
                    { 
                        _scrollViewer = _textEditor._Scroller as ScrollViewer; 
                    }
                } 
                return _scrollViewer;
            }
        }
 
        // ITextContainer holding the Control content.
        ITextContainer ITextBoxViewHost.TextContainer 
        { 
            get
            { 
                return this.TextContainer;
            }
        }
 
        // Set true when typography property values are all default values.
        bool ITextBoxViewHost.IsTypographyDefaultValue 
        { 
            get
            { 
                return true;
            }
        }
 
        #endregion Internal Properties
 
        //----------------------------------------------------- 
        //
        //  Private Methods 
        //
        //------------------------------------------------------

        #region Private Methods 

        // Worker for the ctors, initializes a new PasswordBox instance. 
        private void Initialize() 
        {
            // Register static editing command handlers. 
            // This only has an effect that first time we make the call.
            // We don't use the static ctor because there are cases
            // where another control will want to alias our properties
            // but doesn't need this overhead. 
            TextEditor.RegisterCommandHandlers(typeof(PasswordBox), /*acceptsRichContent:*/false, /*readOnly*/false, /*registerEventListeners*/false);
 
            // Create TextContainer 
            InitializeTextContainer(new PasswordTextContainer(this));
 
            // PasswordBox only accepts plain text, so change TextEditor's default to that.
            _textEditor.AcceptsRichContent = false;

            // PasswordBox does not accetps tabs. 
            _textEditor.AcceptsTab = false;
        } 
 
        // Attaches this control to a new TextContainer.
        private void InitializeTextContainer(PasswordTextContainer textContainer) 
        {
            Invariant.Assert(textContainer != null);

            // Uninitialize previous TextEditor 
            if (_textContainer != null)
            { 
                Invariant.Assert(_textEditor != null); 
                Invariant.Assert(_textEditor.TextContainer == _textContainer);
 
                // Detach existing editor from VisualTree
                DetachFromVisualTree();

                // Discard TextEditor - must release text container 
                _textEditor.OnDetach();
            } 
 
            // Save text container
            _textContainer = textContainer; 

            //
            ((ITextContainer)_textContainer).Changed += new TextContainerChangedEventHandler(OnTextContainerChanged);
 
            // Create a text editor, initialize undo manager for it, and link it to text container
            _textEditor = new TextEditor(_textContainer, this, true); 
        } 

        // Disable IME input unconditionally.  We really can't support 
        // IMEs in this control, because PasswordTextContainer doesn't
        // round-trip content, which breaks the cicero contract.
        // Additionally, from a UI standpoint, we don't want to break
        // user expectations by allowing IME input.  IMEs do cool things 
        // like learn from user corrections, so the same keystroke sequence
        // might produce different text over time. 
        private static object ForceToFalse(DependencyObject d, object value) 
        {
            return BooleanBoxes.FalseBox; 
        }

        /// 
        /// Callback for changes to the PasswordChar property. 
        /// 
        private static void OnPasswordCharChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            PasswordBox passwordBox = (PasswordBox)d;
 
            // Force a layout refresh to display the new char.
            if (passwordBox._renderScope != null)
            {
                passwordBox._renderScope.InvalidateMeasure(); 
            }
        } 
 
        /// 
        /// Handler for text array change notifications. 
        /// 
        /// 
        /// sender
        ///  
        /// 
        /// event args 
        ///  
        private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e)
        { 
            // If only properties on the text changed, don't fire a content change event.
            // This can happen even in a plain text TextBox if we switch logical trees.
            if (!e.HasContentAddedOrRemoved)
            { 
                return;
            } 
 
            RaiseEvent(new RoutedEventArgs(PasswordChangedEvent));
        } 

        /// 
        /// Walk the visual tree until we find a Text control with IsPasswordBoxContent == true
        /// and a ScrollViewer 
        /// 
        private void SetRenderScopeToContentHost(TextBoxView renderScope) 
        { 
            // Clear the content host from previous render scope (if any)
            ClearContentHost(); 

            // Find ContentHostTemplateName in the style
            _passwordBoxContentHost = GetTemplateChild(ContentHostTemplateName) as FrameworkElement;
 
            // Note that we allow ContentHostTemplateName to be optional.
            // This simplifies toolability of our control styling. 
            // When the ContentHostTemplateName is not found or incorrect 
            // PasswordBox goes into disabled state, but does not throw.
 
            // Add renderScope as a child of ContentHostTemplateName
            _renderScope = renderScope;
            if (_passwordBoxContentHost is ScrollViewer)
            { 
                ScrollViewer scrollViewer = (ScrollViewer)_passwordBoxContentHost;
                if (scrollViewer.Content != null) 
                { 
                    throw new NotSupportedException(SR.Get(SRID.TextBoxScrollViewerMarkedAsTextBoxContentMustHaveNoContent));
                } 
                else
                {
                    scrollViewer.Content = _renderScope;
                } 
            }
            else if (_passwordBoxContentHost is Decorator) 
            { 
                Decorator decorator = (Decorator)_passwordBoxContentHost;
                if (decorator.Child != null) 
                {
                    throw new NotSupportedException(SR.Get(SRID.TextBoxDecoratorMarkedAsTextBoxContentMustHaveNoContent));
                }
                else 
                {
                    decorator.Child = _renderScope; // this may replace old render scope in case of upgrade scenario in TextBox 
                } 
            }
            else 
            {
                // When we implement TextContainer setting via TextView interface
                // all text containing element will become allowed here.
                _renderScope = null; 

                // Explicitly not throwing an exception here when content host = null 
                // -- designers need us to support no content scenarios 
                if (_passwordBoxContentHost != null)
                { 
                    _passwordBoxContentHost = null;
                    //
                    throw new NotSupportedException(SR.Get(SRID.PasswordBoxInvalidTextContainer));
                } 
            }
 
            // Attach render scope to TextEditor 
            InitializeRenderScope();
 
            FrameworkElement element = _renderScope;
            while (element != this && element != null)  // checking both just to be safe
            {
                if (element is Border) 
                {
                    _border = (Border)element; 
                } 
                element = element.Parent as FrameworkElement;
            } 
        }

        private void ClearContentHost()
        { 
            // Detach render scope from TextEditor
            UninitializeRenderScope(); 
 
            // Render scope has been created by us,
            // so we need to extract if from visual tree. 
            if (_passwordBoxContentHost is ScrollViewer)
            {
                ((ScrollViewer)_passwordBoxContentHost).Content = null;
            } 
            else if (_passwordBoxContentHost is Decorator)
            { 
                ((Decorator)_passwordBoxContentHost).Child = null; 
            }
            else 
            {
                Invariant.Assert(_passwordBoxContentHost == null, "_passwordBoxContentHost must be null here");
            }
 
            _passwordBoxContentHost = null;
        } 
 
        // Initializes a new render scope.
        private void InitializeRenderScope() 
        {
            if (_renderScope == null)
            {
                return; 
            }
 
            // Attach the renderScope to TextEditor as its ITextView member. 
            ITextView textview = TextEditor.GetTextView(_renderScope);
            _textEditor.TextView = textview; 
            this.TextContainer.TextView = textview;

            if (this.ScrollViewer != null)
            { 
                this.ScrollViewer.CanContentScroll = true;
            } 
        } 

        // Uninitializes a render scope and clears this control's reference. 
        private void UninitializeRenderScope()
        {
            // Clear TextView property in TextEditor
            _textEditor.TextView = null; 
        }
 
        // Resets the selection to the start of the content. 
        // Called after non-TOM changes to the content, like
        // set_Text 
        private void ResetSelection()
        {
            Select(0, 0);
 
            if (this.ScrollViewer != null)
            { 
                this.ScrollViewer.ScrollToHome(); 
            }
        } 

        /// 
        /// Select the text in the given position and length.
        ///  
        private void Select(int start, int length)
        { 
            ITextPointer selectionStart; 
            ITextPointer selectionEnd;
 
            //             VerifyAccess();
            if (start < 0)
            {
                throw new ArgumentOutOfRangeException("start", SR.Get(SRID.ParameterCannotBeNegative)); 
            }
 
            if (length < 0) 
            {
                throw new ArgumentOutOfRangeException("length", SR.Get(SRID.ParameterCannotBeNegative)); 
            }

            // Identify new selection start position
            selectionStart = this.TextContainer.Start.CreatePointer(); 
            while (start-- > 0 && selectionStart.MoveToNextInsertionPosition(LogicalDirection.Forward))
            { 
            } 

            // Identify new selection end position 
            selectionEnd = selectionStart.CreatePointer();
            while (length-- > 0 && selectionEnd.MoveToNextInsertionPosition(LogicalDirection.Forward))
            {
            } 

            Selection.Select(selectionStart, selectionEnd); 
        } 

        ///  
        /// Callback for TextBox.Padding property setting
        /// 
        /// 
        /// TextBoxBase on which the property is changed 
        /// 
        /// event args 
        private static void OnPaddingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            PasswordBox passwordBox = (PasswordBox)d; 

            if (passwordBox.ScrollViewer != null)
            {
                // translate this change into inner property set on ScrollViewer 
                object padding = passwordBox.GetValue(Control.PaddingProperty);
                if (padding is Thickness) 
                { 
                    passwordBox.ScrollViewer.Padding = (Thickness)padding;
                } 
                else
                {
                    passwordBox.ScrollViewer.ClearValue(Control.PaddingProperty);
                } 
            }
        } 
 
        // Set up listener for Navigating event
        private static void OnParentNavigationServiceChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
        {
            PasswordBox passwordBox = (PasswordBox)o;
            NavigationService navService = NavigationService.GetNavigationService(o);
            if (passwordBox._navigationService != null) 
            {
                passwordBox._navigationService.Navigating -= new NavigatingCancelEventHandler(passwordBox.OnNavigating); 
            } 
            if (navService != null)
            { 
                navService.Navigating += new NavigatingCancelEventHandler(passwordBox.OnNavigating);
                passwordBox._navigationService = navService;
            }
            else 
            {
                passwordBox._navigationService = null; 
            } 
        }
 
        // Clear password on navigation to prevent journaling.
        private void OnNavigating(Object sender, NavigatingCancelEventArgs e)
        {
            this.Password = String.Empty; 
        }
 
        ///  
        /// Detaches the editor from old visual tree and attaches it to a new one
        ///  
        private void AttachToVisualTree()
        {
            DetachFromVisualTree();
 
            // Walk the visual tree to find our Text element
            SetRenderScopeToContentHost(new TextBoxView(this)); 
 
            // Attach scroll handler to the new scroll viewer
            // Note that this.ScrollViewer will walk the tree from current TextEditor's render scope up to its ui scope. 
            if (this.ScrollViewer != null)
            {
                this.ScrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden;
                this.ScrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; 
                this.ScrollViewer.Focusable = false;
 
                if (this.ScrollViewer.Background == null) 
                {
                    // prevent hit-testing through padding 
                    this.ScrollViewer.Background = Brushes.Transparent;
                }
                OnPaddingChanged(this, new DependencyPropertyChangedEventArgs());
            } 

            // Set border properties 
            if (_border != null) 
            {
                _border.Style = null; 
            }
        }

        ///  
        /// Clear our layout-specific data, and detach our current renderScope from our text editor.
        ///  
        private void DetachFromVisualTree() 
        {
            if (_textEditor != null) 
            {
                _textEditor.Selection.DetachFromVisualTree();
            }
 
            // Invalidate our cached copy of scroll viewer.
            _scrollViewer = null; 
            _border = null; 

            ClearContentHost(); 
        }

        /// 
        /// Sets the content of the control. 
        /// 
        ///  
        /// Critical - This method indirectly reveals value's SecureString content. 
        ///
        /// This method must never be passed a publicly supplied SecureString as long as we expose 
        /// a plain text get_Password property.
        ///
        /// 1. Attacker sets SecureString value it does not have permission to read.
        /// 2. Attacker reads Password property. 
        /// --> attacker has ----ed open a SecureString without UnmanagedCode permission.
        ///  
        [SecurityCritical] 
        private void SetSecurePassword(SecureString value)
        { 
            this.TextContainer.BeginChange();
            try
            {
                this.TextContainer.SetPassword(value); 
                this.ResetSelection();
            } 
            finally 
            {
                this.TextContainer.EndChange(); 
            }
        }

        ///  
        /// PropertyChanged callback for a property that affects the selection or caret rendering.
        ///  
        private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            PasswordBox passwordBox = (PasswordBox)d; 

            if (passwordBox.Selection != null)
            {
                CaretElement caretElement = passwordBox.Selection.CaretElement; 
                if (caretElement != null)
                { 
                    if (e.Property == CaretBrushProperty) 
                    {
                        caretElement.UpdateCaretBrush(TextSelection.GetCaretBrush(passwordBox.Selection.TextEditor)); 
                    }

                    caretElement.InvalidateVisual();
                } 
            }
        } 
 
        #endregion Private methods
 
        //------------------------------------------------------
        //
        //  Private Properties
        // 
        //-----------------------------------------------------
 
        #region Private Properties 

        ///  
        /// Text Selection (readonly)
        /// 
        private ITextSelection Selection
        { 
            get
            { 
                return _textEditor.Selection; 
            }
        } 


        #endregion Private Properties
 
        //------------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        #region Private Fields

        // TextEditor working in this control instance 
        private TextEditor _textEditor;
 
        // Backing store for the control's content. 
        private PasswordTextContainer _textContainer;
 
        // Encapsulated control that renders our TextContainer.
        private TextBoxView _renderScope;

        // ScrollViewer 
        private ScrollViewer _scrollViewer;
 
        // Border 
        private Border _border;
 
        // An element marked as ContentHostTemplateName which we assign our _renderScope as a child.
        private FrameworkElement _passwordBoxContentHost;

        // Default size for the control. 
        private const int _defaultWidth = 100;
        private const int _defaultHeight = 20; 
 
        // Part name used in the style. The class TemplatePartAttribute should use the same name
        private const string ContentHostTemplateName = "PART_ContentHost"; 

        #endregion Private Fields

        #region DTypeThemeStyleKey 

        // Returns the DependencyObjectType for the registered ThemeStyleKey's default 
        // value. Controls will override this method to return approriate types. 
        internal override DependencyObjectType DTypeThemeStyleKey
        { 
            get { return _dType; }
        }

        private static DependencyObjectType _dType; 

        private NavigationService _navigationService; 
        #endregion DTypeThemeStyleKey 
    }
 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK