Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / Primitives / TextBoxBase.cs / 1305600 / TextBoxBase.cs
//---------------------------------------------------------------------------- // // File: TextBoxBase.cs // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: The base class for TextBox and RichTextBox. // //--------------------------------------------------------------------------- namespace System.Windows.Controls.Primitives { using MS.Internal; using System.Threading; using System.Collections.ObjectModel; using System.ComponentModel; // DefaultValue using System.Security; using System.Security.Permissions; using System.Windows.Automation; // TextPattern using System.Windows.Automation.Provider; // AutomationProvider using System.Windows.Data; // Binding using System.Windows.Documents; // TextEditor using System.Windows.Input; // MouseButtonEventArgs using System.Windows.Markup; // XamlDesignerSerializer using MS.Internal.Documents; // Undo using System.Windows.Media; // VisualTreeHelper //----------------------------------------------------- // // Public Enumerations // //----------------------------------------------------- #region Public Enumerations #endregion Public Enumerations ////// The base class for text editing controls. /// [Localizability(LocalizationCategory.Text)] [TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))] public abstract class TextBoxBase : Control { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// Static constructor - provides metadata for some properties /// static TextBoxBase() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxBase), new FrameworkPropertyMetadata(typeof(TextBoxBase))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(TextBoxBase)); // Declaree listener for Padding property Control.PaddingProperty.OverrideMetadata(typeof(TextBoxBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnScrollViewerPropertyChanged))); // Listner for InputMethod enabled/disabled property // TextEditor needs to set the document manager focus. InputMethod.IsInputMethodEnabledProperty.OverrideMetadata(typeof(TextBoxBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnInputMethodEnabledPropertyChanged))); IsEnabledProperty.OverrideMetadata(typeof(TextBoxBase), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); IsMouseOverPropertyKey.OverrideMetadata(typeof(TextBoxBase), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); } ////// Constructor. /// internal TextBoxBase() : base() { // Subclass is expected to do three things: // a) Register class command handlers // b) create TextContainer and call InitializeTextContainer // c) configure TextEditor by setting appropriate properties CoerceValue(HorizontalScrollBarVisibilityProperty); // Security team really wants to set AllowDrop property value as "False" // not to generate the security exception that can be happened in the // partial trust environment. if (!SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode))) { AllowDrop = false; } } #endregion Constructors //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods ////// Appends text to the current text of text box /// You can use this method to add text to the existing text /// in the control instead of using the concatenation operator /// (+) to concatenate text to the Text property /// /// /// The text to append to the current contents of the text box /// ////// For RichTextBox this method works similar to TextRange.set_Text: /// every NewLine combination will insert a new Paragraph element. /// public void AppendText(string textData) { if (textData == null) { return; } TextRange range = new TextRange(_textContainer.End, _textContainer.End); range.Text = textData; // Note that in RichTextBox this assignment will convert NewLines into Paragraphs } ////// Called when the Template's tree has been generated /// public override void OnApplyTemplate() { base.OnApplyTemplate(); AttachToVisualTree(); } ////// Copy the current selection in the text box to the clipboard /// ////// Critical - Calls TextEditorCopyPaste.Copy which sets data on the clipboard. /// PublicOK - Indicates that this was not a user-initiated call, so TextEditorCopyPaste.Copy will /// check for clipboard permission. /// [SecurityCritical] public void Copy() { TextEditorCopyPaste.Copy(this.TextEditor, false); } ////// Moves the current selection in the textbox to the clipboard /// ////// Critical - Calls TextEditorCopyPaste.Cut which sets data on the clipboard. /// PublicOK - Indicates that this was not a user-initiated call, so TextEditorCopyPaste.Cut will /// check for clipboard permission. /// [SecurityCritical] public void Cut() { TextEditorCopyPaste.Cut(this.TextEditor, false); } ////// Replaces the current selection in the textbox with the contents /// of the Clipboard /// public void Paste() { TextEditorCopyPaste.Paste(this.TextEditor); } ////// Select all text in the TextBox /// public void SelectAll() { using (this.TextSelectionInternal.DeclareChangeBlock()) { TextSelectionInternal.Select(_textContainer.Start, _textContainer.End); } } ////// Scroll content by one line to the left. /// public void LineLeft() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.LineLeft(); } } ////// Scroll content by one line to the right. /// public void LineRight() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.LineRight(); } } ////// Scroll content by one page to the left. /// public void PageLeft() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageLeft(); } } ////// Scroll content by one page to the right. /// public void PageRight() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageRight(); } } ////// Scroll content by one line to the top. /// public void LineUp() { UpdateLayout(); DoLineUp(); } ////// Scroll content by one line to the bottom. /// public void LineDown() { UpdateLayout(); DoLineDown(); } ////// Scroll content by one page to the top. /// public void PageUp() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageUp(); } } ////// Scroll content by one page to the bottom. /// public void PageDown() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageDown(); } } ////// Vertically scroll to the beginning of the content. /// public void ScrollToHome() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToHome(); } } ////// Vertically scroll to the end of the content. /// public void ScrollToEnd() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToEnd(); } } ////// Scroll horizontally to the specified offset. /// public void ScrollToHorizontalOffset(double offset) { if (Double.IsNaN(offset)) { throw new ArgumentOutOfRangeException("offset"); } if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToHorizontalOffset(offset); } } ////// Scroll vertically to the specified offset. /// public void ScrollToVerticalOffset(double offset) { if (Double.IsNaN(offset)) { throw new ArgumentOutOfRangeException("offset"); } if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToVerticalOffset(offset); } } ////// Undo the most recent undo unit on the stack. /// ////// true if undo succeeds, false otherwise (including when the stack is empty) /// public bool Undo() { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && undoManager.UndoCount > undoManager.MinUndoStackCount) { this.TextEditor.Undo(); return true; } return false; } ////// Redo the most recent undo unit on the stack. /// ////// true if redo succeeds, false otherwise (including when the stack is empty) /// public bool Redo() { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && undoManager.RedoCount > 0) { this.TextEditor.Redo(); return true; } return false; } ////// Lock the most recently added undo unit, preventing it from being reopened. /// ////// This method is intended to be called by an application when a non-text undo unit is added /// to the application's own undo stack on top of a text undo unit. By calling this method, /// the next text undo unit will not attempt to merge with the previous one. /// public void LockCurrentUndoUnit() { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { // find the deepest open unit, and lock the last unit added to it IParentUndoUnit openedUnit = undoManager.OpenedUnit; if (openedUnit != null) { while (openedUnit.OpenedUnit != null) { openedUnit = openedUnit.OpenedUnit; } if (openedUnit.LastUnit is IParentUndoUnit) { openedUnit.OnNextAdd(); } } else if (undoManager.LastUnit is IParentUndoUnit) { ((IParentUndoUnit)undoManager.LastUnit).OnNextAdd(); // } } } //......................................................... // // Change Notifications // //......................................................... ////// Begins a change block. /// public void BeginChange() { this.TextEditor.Selection.BeginChange(); } ////// Ends a change block. /// public void EndChange() { if (this.TextEditor.Selection.ChangeBlockLevel == 0) { throw new InvalidOperationException(SR.Get(SRID.TextBoxBase_UnmatchedEndChange)); } this.TextEditor.Selection.EndChange(); } ////// Creates and returns a change block /// ///IDisposable public IDisposable DeclareChangeBlock() { return this.TextEditor.Selection.DeclareChangeBlock(); } #endregion Public Methods //----------------------------------------------------- // // Public Properties // //------------------------------------------------------ #region Public Properties ////// Alias for TextEditor.IsReadOnly dependency property. /// Enables editing within this textbox. /// public static readonly DependencyProperty IsReadOnlyProperty = TextEditor.IsReadOnlyProperty.AddOwner( typeof(TextBoxBase), new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnVisualStatePropertyChanged))); ////// Whether or not the Textbox is read-only /// public bool IsReadOnly { get { return (bool) GetValue(TextEditor.IsReadOnlyProperty); } set { SetValue(TextEditor.IsReadOnlyProperty, value); } } ////// DependencyProperty backing IsReadOnlyCaretVisible. /// public static readonly DependencyProperty IsReadOnlyCaretVisibleProperty = DependencyProperty.Register("IsReadOnlyCaretVisible", typeof(bool), typeof(TextBoxBase), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsReadOnlyCaretVisiblePropertyChanged))); ////// Whether or not the caret is visible when the textbox is read-only. /// public bool IsReadOnlyCaretVisible { get { return (bool)GetValue(IsReadOnlyCaretVisibleProperty); } set { SetValue(IsReadOnlyCaretVisibleProperty, value); } } ////// Indicates if VK_Return character is accepted as a normal new-line character, if it is true, it will insert a new-line to the textbox /// or other editable controls, if it is false, it will not insert a new-line character to the controls's content, but just /// activates the control with focus. /// /// Default: true. /// TextBox and/or RichTextBox need to set this value appropriately /// public static readonly DependencyProperty AcceptsReturnProperty = KeyboardNavigation.AcceptsReturnProperty.AddOwner(typeof(TextBoxBase)); ////// Whether or not the Textbox accepts newlines /// public bool AcceptsReturn { get { return (bool) GetValue(AcceptsReturnProperty); } set { SetValue(AcceptsReturnProperty, value); } } ////// Indicates if VK_TAB character is accepted as a normal tab char, if it is true, it will insert a tab character to the control's content, /// otherwise, it will not insert new tab to the content of control, instead, it will navigate the focus to the next IsTabStop control. /// /// Default: false. /// /// TextBox and RichTextBox need to set the value appropriately. /// public static readonly DependencyProperty AcceptsTabProperty = DependencyProperty.Register( "AcceptsTab", // Property name typeof(bool), // Property type typeof(TextBoxBase), // Property owner new FrameworkPropertyMetadata(false /*default value*/)); ////// Whether or not the Textbox accepts tabs /// public bool AcceptsTab { get { return (bool) GetValue(AcceptsTabProperty); } set { SetValue(AcceptsTabProperty, value); } } ////// Access to all spelling options. /// public SpellCheck SpellCheck { get { return new SpellCheck(this); } } ////// Exposes ScrollViewer's HorizontalScrollBarVisibility property /// Default: Hidden /// public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = ScrollViewer.HorizontalScrollBarVisibilityProperty.AddOwner( typeof(TextBoxBase), new FrameworkPropertyMetadata( ScrollBarVisibility.Hidden, new PropertyChangedCallback(OnScrollViewerPropertyChanged))); // PropertyChangedCallback ////// Whether or not a horizontal scrollbar is shown /// public ScrollBarVisibility HorizontalScrollBarVisibility { get { return (ScrollBarVisibility) GetValue(HorizontalScrollBarVisibilityProperty); } set { SetValue(HorizontalScrollBarVisibilityProperty, value); } } ////// Exposes ScrollViewer's VerticalScrollBarVisibility property /// Default: Hidden /// public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = ScrollViewer.VerticalScrollBarVisibilityProperty.AddOwner( typeof(TextBoxBase), new FrameworkPropertyMetadata(ScrollBarVisibility.Hidden, new PropertyChangedCallback(OnScrollViewerPropertyChanged))); ////// Whether or not a vertical scrollbar is shown /// public ScrollBarVisibility VerticalScrollBarVisibility { get { return (ScrollBarVisibility) GetValue(VerticalScrollBarVisibilityProperty); } set { SetValue(VerticalScrollBarVisibilityProperty, value); } } ////// Horizontal size of scrollable content; 0.0 if TextBox is non-scrolling /// public double ExtentWidth { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ExtentWidth : 0.0; } } ////// Vertical size of scrollable content; 0.0 if TextBox is non-scrolling /// public double ExtentHeight { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ExtentHeight : 0.0; } } ////// Horizontal size of scroll area; 0.0 if TextBox is non-scrolling /// public double ViewportWidth { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ViewportWidth : 0.0; } } ////// Vertical size of scroll area; 0.0 if TextBox is non-scrolling /// public double ViewportHeight { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ViewportHeight : 0.0; } } ////// Actual HorizontalOffset contains the ScrollViewer's current horizontal offset. /// This is a computed value, depending on the state of ScrollViewer, its Viewport, Extent /// and previous scrolling commands. /// public double HorizontalOffset { get { return (this.ScrollViewer != null) ? this.ScrollViewer.HorizontalOffset : 0.0; } } ////// Actual VerticalOffset contains the ScrollViewer's current vertical offset. /// This is a computed value, depending on the state of ScrollViewer, its Viewport, Extent /// and previous scrolling commands. /// public double VerticalOffset { get { return (this.ScrollViewer != null) ? this.ScrollViewer.VerticalOffset : 0.0; } } ////// Can the most recent action on the text box be undone? Since we will frequently be called /// during a TextChanged event when the undo stack hasn't yet been modified to reflect the /// pending change, just looking at the UndoCount isn't sufficient. TextEditor caches /// the pending undo action with us so we can refer to it now. /// public bool CanUndo { get { UndoManager undoManager; undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && (_pendingUndoAction != UndoAction.Clear && (undoManager.UndoCount > undoManager.MinUndoStackCount || (undoManager.State != UndoState.Undo && _pendingUndoAction == UndoAction.Create)))) { return true; } else { return false; } } } ////// Can the most recent undone action on the text box be redone? /// public bool CanRedo { get { UndoManager undoManager; undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && (_pendingUndoAction != UndoAction.Clear && (undoManager.RedoCount > 0 || (undoManager.State == UndoState.Undo && _pendingUndoAction == UndoAction.Create)))) { return true; } else { return false; } } } ////// Enables or disabled undo support on this Control. /// ////// Defaults to true. /// /// The control's undo record is cleared when this property transitions /// to false. /// public static readonly DependencyProperty IsUndoEnabledProperty = DependencyProperty.Register("IsUndoEnabled", typeof(bool), typeof(TextBoxBase), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnIsUndoEnabledChanged))); ////// Enables or disabled undo support on this Control. /// ////// Defaults to true. /// /// The control's undo record is cleared when this property transitions /// to false. /// public bool IsUndoEnabled { get { return (bool)GetValue(IsUndoEnabledProperty); } set { SetValue(IsUndoEnabledProperty, value); } } ////// Sets the number of actions stored in the undo queue. /// ////// The value must be >= -1. /// /// -1 sets the storage to "infinite", limited only by available memory. /// 0 disables undo. /// /// Setting any value will clear the existing queue. /// /// An InvalidOperationException is thrown if the value is set inside to /// context of a BeginChange/EndChange pair while IsUndoEnabled is true /// (ie, you may not set this property while an undo unit is open). /// /// The default value is -1. /// public static readonly DependencyProperty UndoLimitProperty = DependencyProperty.Register("UndoLimit", typeof(int), typeof(TextBoxBase), new FrameworkPropertyMetadata(UndoManager.UndoLimitDefaultValue, new PropertyChangedCallback(OnUndoLimitChanged)), new ValidateValueCallback(UndoLimitValidateValue)); ////// public int UndoLimit { get { return (int)GetValue(UndoLimitProperty); } set { SetValue(UndoLimitProperty, value); } } ////// /// The DependencyID for the AutoWordSelection property. /// Flags: Can be used in style rules /// Default Value: false /// public static readonly DependencyProperty AutoWordSelectionProperty = DependencyProperty.Register( "AutoWordSelection", // Property name typeof(bool), // Property type typeof(TextBoxBase), // Property owner new FrameworkPropertyMetadata(false)); ////// Whether or not dragging with the mouse automatically selects words /// public bool AutoWordSelection { get { return (bool)GetValue(AutoWordSelectionProperty); } set { SetValue(AutoWordSelectionProperty, value); } } ////// Brush used for selection fill. /// ////// If set to null, the selection will not be rendered. /// public static readonly DependencyProperty SelectionBrushProperty = DependencyProperty.Register("SelectionBrush", typeof(Brush), typeof(TextBoxBase), new FrameworkPropertyMetadata(GetDefaultSelectionBrush(), new PropertyChangedCallback(UpdateCaretElement))); ////// public Brush SelectionBrush { get { return (Brush)GetValue(SelectionBrushProperty); } set { SetValue(SelectionBrushProperty, value); } } ////// /// Opacity used for drawing the selection. /// ////// The opacity of SelectionBrush will also be respected (multiplied with this one during render). /// public static readonly DependencyProperty SelectionOpacityProperty = DependencyProperty.Register("SelectionOpacity", typeof(double), typeof(TextBoxBase), new FrameworkPropertyMetadata(0.4, new PropertyChangedCallback(UpdateCaretElement))); ////// public double SelectionOpacity { get { return (double)GetValue(SelectionOpacityProperty); } set { SetValue(SelectionOpacityProperty, value); } } ////// /// Brush used for the caret. /// ////// If set to null, the default behavior of setting the caret color to the inverse of the background color will be used. /// public static readonly DependencyProperty CaretBrushProperty = DependencyProperty.Register("CaretBrush", typeof(Brush), typeof(TextBoxBase), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(UpdateCaretElement))); ////// 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" /// public static readonly RoutedEvent TextChangedEvent = EventManager.RegisterRoutedEvent( "TextChanged", // Event name RoutingStrategy.Bubble, // typeof(TextChangedEventHandler), // typeof(TextBoxBase)); // ////// Event fired from this text box when its inner content /// has been changed. /// ////// The event itself is defined on TextEditor. /// public event TextChangedEventHandler TextChanged { add { AddHandler(TextChangedEvent, value); } remove { RemoveHandler(TextChangedEvent, value); } } ////// Event for "Selection has changed" /// public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent( "SelectionChanged", // Event name RoutingStrategy.Bubble, // typeof(RoutedEventHandler), // typeof(TextBoxBase)); // ////// Event fired from this text box when its selection has been changed. /// public event RoutedEventHandler SelectionChanged { add { AddHandler(SelectionChangedEvent, value); } remove { RemoveHandler(SelectionChangedEvent, value); } } #endregion Public Events //----------------------------------------------------- // // Protected Methods // //------------------------------------------------------ #region Protected Methods internal override void ChangeVisualState(bool useTransitions) { // See ButtonBase.ChangeVisualState. // This method should be exactly like it, except we have a ReadOnly state instead of Pressed if (!IsEnabled) { VisualStateManager.GoToState(this, VisualStates.StateDisabled, useTransitions); } else if (IsReadOnly) { VisualStateManager.GoToState(this, VisualStates.StateReadOnly, useTransitions); } else if (IsMouseOver) { VisualStateManager.GoToState(this, VisualStates.StateMouseOver, useTransitions); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } if (IsKeyboardFocused) { VisualStateManager.GoToState(this, VisualStates.StateFocused, useTransitions); } else { VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions); } base.ChangeVisualState(useTransitions); } ////// Called when content in this Control changes. /// Raises the TextChanged event. /// /// protected virtual void OnTextChanged(TextChangedEventArgs e) { RaiseEvent(e); } ////// Called when the caret or selection changes position. /// Raises the SelectionChanged event. /// /// protected virtual void OnSelectionChanged(RoutedEventArgs e) { RaiseEvent(e); } ////// 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(); } } ////// ScrollViewer marks all mouse wheel events as handled, even if no scrolling occurs. This means that /// when mousewheeling through a document, if the cursor happens to land on a textbox, scrolling will /// stop when the textbox reaches the end of its content. We want the scroll event to continue to the /// outer control in such a case so that outer control continues scrolling. /// /// MouseWheelEventArgs protected override void OnMouseWheel(MouseWheelEventArgs e) { if (e == null) { throw new ArgumentNullException("e"); } if (this.ScrollViewer != null) { // Only raise the event on ScrollViewer if we're actually going to scroll if ((e.Delta > 0 && VerticalOffset != 0) /* scrolling up */ || (e.Delta < 0 && VerticalOffset < this.ScrollViewer.ScrollableHeight) /* scrolling down */ ) { Invariant.Assert(this.RenderScope is IScrollInfo); if (e.Delta > 0) { ((IScrollInfo)this.RenderScope).MouseWheelUp(); } else { ((IScrollInfo)this.RenderScope).MouseWheelDown(); } e.Handled = true; } } base.OnMouseWheel(e); } ////// Virtual method reporting a key was pressed /// protected override void OnPreviewKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnPreviewKeyDown(e); } } ////// Virtual method reporting a key was pressed /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnKeyDown(e); } } ////// Virtual method reporting a key was released /// protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnKeyUp(e); } } ////// Virtual method reporting text composition /// protected override void OnTextInput(TextCompositionEventArgs e) { base.OnTextInput(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnTextInput(e); } } ////// Virtual method reporting the mouse button was pressed /// protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnMouseDown(e); } } ////// Virtual method reporting a mouse move /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnMouseMove(e); } } ////// Virtual method reporting the mouse button was released /// protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (e.Handled) { return; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _textEditor.OnLostFocus(e); } } // Allocates the initial render scope for this control. internal abstract FrameworkElement CreateRenderScope(); ////// Handler for TextContainer.Changed event. Raises the TextChanged event on UiScope. /// for editing controls. /// /// /// sender /// /// /// event args /// internal virtual 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 && !e.HasLocalPropertyValueChange) { return; } UndoManager undoManager = UndoManager.GetUndoManager(this); UndoAction undoAction; if (undoManager != null) // Will be null for controls like PasswordBox that don't use undo. { if (_textEditor.UndoState == UndoState.Redo) { undoAction = UndoAction.Redo; } else if (_textEditor.UndoState == UndoState.Undo) { undoAction = UndoAction.Undo; } else if (undoManager.OpenedUnit == null) { undoAction = UndoAction.Clear; } else if (undoManager.LastReopenedUnit == undoManager.OpenedUnit) { undoAction = UndoAction.Merge; } else { undoAction = UndoAction.Create; } } else { undoAction = UndoAction.Create; } // The undo stack hasn't yet been modified by this change, so CanUndo will not // necessarily yield the correct result if queried during the TextChange event. // Store the undo action in the uiScope, so CanUndo can // reference it to provide the correct result. _pendingUndoAction = undoAction; try { OnTextChanged(new TextChangedEventArgs(TextChangedEvent, undoAction, new ReadOnlyCollection(e.Changes.Values))); } finally { _pendingUndoAction = UndoAction.None; } } #endregion Protected Methods //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods // Attaches this control to a new TextContainer. internal void InitializeTextContainer(TextContainer textContainer) { Invariant.Assert(textContainer != null); Invariant.Assert(textContainer.TextSelection == null); // Uninitialize previous TextEditor if (_textContainer != null) { Invariant.Assert(_textEditor != null); Invariant.Assert(_textEditor.TextContainer == _textContainer); Invariant.Assert(_textEditor.TextContainer.TextSelection == _textEditor.Selection); // Detach existing editor from VisualTree DetachFromVisualTree(); // Discard TextEditor - must release text container _textEditor.OnDetach(); } // Save text container _textContainer = textContainer; _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); _textEditor.Selection.Changed += new EventHandler(OnSelectionChangedInternal); // Init a default undo limit. UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { undoManager.UndoLimit = this.UndoLimit; } // Delay raising automation events until the automation subsystem is activated by a client. // ISSUE-2005/01/23-vsmirnov - Adding an event listener to AutomationProvider apparently // causes memory leaks because TextBoxBase is never released. I comment it out for now just // to fix the build break (perf DRT failure). Need to find a right fix later. // AutomationProvider.Activated += new AutomationActivatedEventHandler(OnAutomationActivated); } /// /// Returns a TextPosition matching the specified pixel coordinates. /// /// /// Pixel coordinate to hittest with. /// point is expected to be in the coordinate space of this TextBox. /// /// /// If true, heuristics are applied to find the closest character /// position to point, even if point does not intersect any character /// bounding box. /// ////// A TextPosition and its orientation matching the specified pixel. /// May return null if snapToText is false and point does not fall /// within any character bounding box. /// internal TextPointer GetTextPositionFromPointInternal(Point point, bool snapToText) { TextPointer position; // Transform to content coordinates. GeneralTransform transform = this.TransformToDescendant(this.RenderScope); if (transform != null) { transform.TryTransform(point, out point); } if (TextEditor.GetTextView(this.RenderScope).Validate(point)) { position = (TextPointer)TextEditor.GetTextView(this.RenderScope).GetTextPositionFromPoint(point, snapToText); } else { position = snapToText ? this.TextContainer.Start : null; } return position; } ////// Retrieves the height and offset, in pixels, of the edge of /// the object/character represented by position. /// /// /// Position of an object/character. /// /// /// Receives the bounding box. /// ////// Returns false if no layout is available. In this case rect will be set empty. /// ////// Coordinates of the return value are relative to this TextBox. /// /// Rect.Width is always 0. /// /// If the content is empty, then this method returns the expected /// height of a character, if placed at the specified position. /// internal bool GetRectangleFromTextPosition(TextPointer position, out Rect rect) { Point offset; if (position == null) { throw new ArgumentNullException("position"); } // Validate layout information on TextView if (TextEditor.GetTextView(this.RenderScope).Validate(position)) { // Get the rect in local content coordinates. rect = TextEditor.GetTextView(this.RenderScope).GetRectangleFromTextPosition(position); // Transform to RichTextBox control coordinates. offset = new Point(0, 0); GeneralTransform transform = this.TransformToDescendant(this.RenderScope); if (transform != null) { transform.TryTransform(offset, out offset); } rect.X -= offset.X; rect.Y -= offset.Y; } else { rect = Rect.Empty; } return rect != Rect.Empty; } ////// Detaches the editor from old visual tree and attaches it to a new one /// internal virtual void AttachToVisualTree() { DetachFromVisualTree(); // Walk the visual tree to find our Text element SetRenderScopeToContentHost(); // Set properties on ScrollViewer // 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.ScrollChanged += new ScrollChangedEventHandler(OnScrollChanged); // SetValue(TextEditor.PageHeightProperty, this.ScrollViewer.ViewportHeight); // Need to make scroll viewer non-focusable, otherwise it will eat keyboard navigation from editor this.ScrollViewer.Focusable = false; // Prevent mouse wheel scrolling from breaking when there's no more content in the direction of the scroll this.ScrollViewer.HandlesMouseWheelScrolling = false; if (this.ScrollViewer.Background == null) { // prevent hit-testing through padding this.ScrollViewer.Background = Brushes.Transparent; } OnScrollViewerPropertyChanged(this, new DependencyPropertyChangedEventArgs(ScrollViewer.HorizontalScrollBarVisibilityProperty, null /* old value */, this.GetValue(HorizontalScrollBarVisibilityProperty))); OnScrollViewerPropertyChanged(this, new DependencyPropertyChangedEventArgs(ScrollViewer.VerticalScrollBarVisibilityProperty, null /* old value */, this.GetValue(VerticalScrollBarVisibilityProperty))); OnScrollViewerPropertyChanged(this, new DependencyPropertyChangedEventArgs(ScrollViewer.PaddingProperty, null /* old value */, this.GetValue(PaddingProperty))); } else { ClearValue(TextEditor.PageHeightProperty); } } // Do the work of line up. Can be overridden by subclass to implement true line up. internal virtual void DoLineUp() { if (this.ScrollViewer != null) { this.ScrollViewer.LineUp(); } } // Do the work of line down. Can be overridden by subclass to implement true line down. internal virtual void DoLineDown() { if (this.ScrollViewer != null) { this.ScrollViewer.LineDown(); } } ////// When RenderScope is FlowDocumentView, events can bypass our nested ScrollViewer. /// We want to make sure that ScrollViewer-- and any other elements in our style-- /// always gets a `crack at mouse events. /// internal override void AddToEventRouteCore(EventRoute route, RoutedEventArgs args) { base.AddToEventRouteCore(route, args); // Walk up the tree from the RenderScope to this, adding each element to the route Visual visual = this.RenderScope; while (visual != this && visual != null) { if (visual is UIElement) { ((UIElement)visual).AddToEventRoute(route, args); } visual = VisualTreeHelper.GetParent(visual) as Visual; } } ////// Helper method to update the IsUndoEnabled flag within UndoManager /// attached to the TextBox. /// /// /// New Value of IsUndoEnabled flag. /// internal void ChangeUndoEnabled(bool value) { // if (this.TextSelectionInternal.ChangeBlockLevel > 0) { throw new InvalidOperationException(SR.Get(SRID.TextBoxBase_CantSetIsUndoEnabledInsideChangeBlock)); } UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { if (!value && undoManager.IsEnabled) { undoManager.Clear(); } undoManager.IsEnabled = value; } } ////// Helper method to update the UndoLimit in UndoManager /// attached to the TextBox. /// /// /// New Value of UndoLimit. /// internal void ChangeUndoLimit(object value) { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { if (undoManager.OpenedUnit != null) { // throw new InvalidOperationException(SR.Get(SRID.TextBoxBase_CantSetIsUndoEnabledInsideChangeBlock)); } int limit; if (value == DependencyProperty.UnsetValue) { limit = UndoManager.UndoLimitDefaultValue; } else { limit = (int)value; } undoManager.UndoLimit = limit; } } #endregion Internal Methods //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- #region Internal Properties ////// Access to the ScrollViewer in textbox style /// internal ScrollViewer ScrollViewer { get { if (_scrollViewer == null) { if (_textEditor != null) { // TextEditor's _Scroller property finds a ScrollViewer found // by a tree walk from the editor's render scope within ui scope. _scrollViewer = _textEditor._Scroller as ScrollViewer; } } return _scrollViewer; } } ////// Text Selection (readonly) /// internal TextSelection TextSelectionInternal { get { return (TextSelection)_textEditor.Selection; } } ////// A TextContainer covering the TextBox's inner content. /// Never returns null, throws SystemException if unavailable. /// internal TextContainer TextContainer { get { return _textContainer; } } ////// readonly access to internal content control /// internal FrameworkElement RenderScope { get { return _renderScope; } } // Expose _pendingUndoAction for DrtEditing.exe, via reflection. internal UndoAction PendingUndoAction { get { return _pendingUndoAction; } set { _pendingUndoAction = value; } } // TextEditor attached to this control. internal TextEditor TextEditor { get { return _textEditor; } } // True if style has been applied to the control and // ContentHostTemplateName was successfully found in it. internal bool IsContentHostAvailable { get { return _textBoxContentHost != null; } } #endregion Internal Properties //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods ////// Clear our layout-specific data, and detach our current renderScope from our text editor. /// private void DetachFromVisualTree() { if (_textEditor != null) { _textEditor.Selection.DetachFromVisualTree(); } // Detach scroll handler from old 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.ScrollChanged -= new ScrollChangedEventHandler(OnScrollChanged); } // Invalidate our cached copy of scroll viewer. _scrollViewer = null; ClearContentHost(); } // Initializes a new render scope. private void InitializeRenderScope() { if (_renderScope == null) { return; } // Map the TextContainer and TextView. ITextView textView = (ITextView)((IServiceProvider)_renderScope).GetService(typeof(ITextView)); this.TextContainer.TextView = textView; _textEditor.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; // Remove our content from the renderScope if (_renderScope is TextBoxView) { // Nothing to do. } else if (_renderScope is FlowDocumentView) { if (((FlowDocumentView)_renderScope).Document != null) { ((FlowDocumentView)_renderScope).Document.Uninitialize(); ((FlowDocumentView)_renderScope).Document = null; } } else { Invariant.Assert(_renderScope == null, "_renderScope must be null here"); } } ////// Creates the default brush used for selection rendering. /// private static Brush GetDefaultSelectionBrush() { Brush selectionBrush = new SolidColorBrush(SystemColors.HighlightColor); selectionBrush.Freeze(); return selectionBrush; } ////// Callback for PageHeight GetValue. /// /// /// dependency object /// ////// private static object OnPageHeightGetValue(DependencyObject d) { return ((TextBoxBase)d).ViewportHeight; } ////// Finds an element in a style temaplte marked as ContentHostTemplateName /// where our render scope must be placed as a child. /// private void SetRenderScopeToContentHost() { FrameworkElement renderScope = CreateRenderScope(); // Clear the content host from previous render scope (if any) ClearContentHost(); // Find ContentHostTemplateName in the style _textBoxContentHost = 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 // TextBox goes into disabled state, but not throw. // Add renderScope as a child of ContentHostTemplateName _renderScope = renderScope; if (_textBoxContentHost is ScrollViewer) { ScrollViewer scrollViewer = (ScrollViewer)_textBoxContentHost; if (scrollViewer.Content != null) { _renderScope = null; _textBoxContentHost = null; // throw new NotSupportedException(SR.Get(SRID.TextBoxScrollViewerMarkedAsTextBoxContentMustHaveNoContent)); } else { scrollViewer.Content = _renderScope; // this may replace old render scope in case of upgrade scenario in TextBox } } else if (_textBoxContentHost is Decorator) { Decorator decorator = (Decorator)_textBoxContentHost; if (decorator.Child != null) { _renderScope = null; _textBoxContentHost = 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 (_textBoxContentHost != null) { _textBoxContentHost = null; // throw new NotSupportedException(SR.Get(SRID.TextBoxInvalidTextContainer)); } } // Attach render scope to TextEditor InitializeRenderScope(); } 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 (_textBoxContentHost is ScrollViewer) { ((ScrollViewer)_textBoxContentHost).Content = null; } else if (_textBoxContentHost is Decorator) { ((Decorator)_textBoxContentHost).Child = null; } else { Invariant.Assert(_textBoxContentHost == null, "_textBoxContentHost must be null here"); } _textBoxContentHost = null; } ////// PropertyChanged handler for IsReadOnlyCaretVisibleProperty. /// private static void OnIsReadOnlyCaretVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; textBox.TextSelectionInternal.UpdateCaretState(CaretScrollMethod.None); ((ITextSelection)textBox.TextSelectionInternal).RefreshCaret(); } ////// Handler for ScrollViewer's OnScrollChanged event. /// internal virtual void OnScrollChanged(object sender, ScrollChangedEventArgs e) { // if (e.ViewportHeightChange != 0) { SetValue(TextEditor.PageHeightProperty, e.ViewportHeight); } } ////// TextSelection.Moved event listener. /// private void OnSelectionChangedInternal(object sender, EventArgs e) { #if OLD_AUTOMATION // It the automation subsystem is active, notify automation clients // about the selection change. if (AutomationProvider.IsActive) { RaiseSelectionChangedEvent(); } #endif OnSelectionChanged(new RoutedEventArgs(SelectionChangedEvent)); } #if OLD_AUTOMATION ////// A helper to raise AutomationEvents. /// The reason this method is standalone with MethodImplOptions.NoInlining is to avoid /// loading UIAutomation unless there's a client already present. /// [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private void RaiseSelectionChangedEvent() { AutomationProvider.RaiseAutomationEvent(TextPatternIdentifiers.TextSelectionChangedEvent, this); } #endif /// // 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; } } ////// Callback for changed ScrollViewer properties, forwarding values from TextBoxBase to ScrollViewer. /// /// /// TextBoxBase on which the property is changed /// /// event args internal static void OnScrollViewerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = d as TextBoxBase; if (textBox != null && textBox.ScrollViewer != null) { object value = e.NewValue; if (value == DependencyProperty.UnsetValue) { textBox.ScrollViewer.ClearValue(e.Property); } else { textBox.ScrollViewer.SetValue(e.Property, value); } } } // Callback for IsUndoEnabledProperty changes. private static void OnIsUndoEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; textBox.ChangeUndoEnabled((bool)e.NewValue); } ////// private static bool UndoLimitValidateValue(object value) { return ((int)value) >= -1; } // Callback for UndoLimitProperty changes. private static void OnUndoLimitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; textBox.ChangeUndoLimit(e.NewValue); } ////// /// Callback for changed InputMethodEnabled properties /// /// /// TextBoxBase on which the property is changed /// /// event args ////// Critical:This code register command handlers for texteditor related events and commands (OnGotFocus) /// TreatAsSafe: This just hooks up methods that are internal to this class /// [SecurityCritical,SecurityTreatAsSafe] private static void OnInputMethodEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; if ((textBox.TextEditor != null) && (textBox.TextEditor.TextStore != null)) { bool value = (bool)e.NewValue; if (value) { if (Keyboard.FocusedElement == textBox) { // Call TextStore.OnGotFocus() to set up the focus dim correctly. textBox.TextEditor.TextStore.OnGotFocus(); } } } } ////// PropertyChanged callback for a property that affects the selection or caret rendering. /// private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBoxBase = (TextBoxBase)d; if (textBoxBase.TextSelectionInternal != null) { CaretElement caretElement = textBoxBase.TextSelectionInternal.CaretElement; if (caretElement != null) { if (e.Property == CaretBrushProperty) { caretElement.UpdateCaretBrush(TextSelection.GetCaretBrush(textBoxBase.TextEditor)); } caretElement.InvalidateVisual(); } } } #endregion Private methods //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Fields private static DependencyObjectType _dType; // Text content owned by this TextBox. // private TextContainer _textContainer; // Text editor private TextEditor _textEditor; // An element marked as TextBoxContentto which we assign our _renderScope as a anonymous child. // In case when TextBoxContent is not an anonymouse child this member is null. private FrameworkElement _textBoxContentHost; // Encapsulated control that holds/implements our TextContainer. private FrameworkElement _renderScope; // ScrollViewer private ScrollViewer _scrollViewer; /// When TextEditor fires a TextChanged event, listeners may want to use the event to /// update their Undo/Redo UI. But the undo stack hasn't yet been modified by the event, /// so querying that stack won't give us the information we need to report correctly. /// TextBoxBase therefore caches the UndoAction here, so that CanUndo can reference it /// and make the right determination. private UndoAction _pendingUndoAction; // Part name used in the style. The class TemplatePartAttribute should use the same name internal const string ContentHostTemplateName = "PART_ContentHost"; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // File: TextBoxBase.cs // // Copyright (C) Microsoft Corporation. All rights reserved. // // Description: The base class for TextBox and RichTextBox. // //--------------------------------------------------------------------------- namespace System.Windows.Controls.Primitives { using MS.Internal; using System.Threading; using System.Collections.ObjectModel; using System.ComponentModel; // DefaultValue using System.Security; using System.Security.Permissions; using System.Windows.Automation; // TextPattern using System.Windows.Automation.Provider; // AutomationProvider using System.Windows.Data; // Binding using System.Windows.Documents; // TextEditor using System.Windows.Input; // MouseButtonEventArgs using System.Windows.Markup; // XamlDesignerSerializer using MS.Internal.Documents; // Undo using System.Windows.Media; // VisualTreeHelper //----------------------------------------------------- // // Public Enumerations // //----------------------------------------------------- #region Public Enumerations #endregion Public Enumerations ////// The base class for text editing controls. /// [Localizability(LocalizationCategory.Text)] [TemplatePart(Name = "PART_ContentHost", Type = typeof(FrameworkElement))] public abstract class TextBoxBase : Control { //------------------------------------------------------ // // Constructors // //----------------------------------------------------- #region Constructors ////// Static constructor - provides metadata for some properties /// static TextBoxBase() { DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBoxBase), new FrameworkPropertyMetadata(typeof(TextBoxBase))); _dType = DependencyObjectType.FromSystemTypeInternal(typeof(TextBoxBase)); // Declaree listener for Padding property Control.PaddingProperty.OverrideMetadata(typeof(TextBoxBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnScrollViewerPropertyChanged))); // Listner for InputMethod enabled/disabled property // TextEditor needs to set the document manager focus. InputMethod.IsInputMethodEnabledProperty.OverrideMetadata(typeof(TextBoxBase), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnInputMethodEnabledPropertyChanged))); IsEnabledProperty.OverrideMetadata(typeof(TextBoxBase), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); IsMouseOverPropertyKey.OverrideMetadata(typeof(TextBoxBase), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); } ////// Constructor. /// internal TextBoxBase() : base() { // Subclass is expected to do three things: // a) Register class command handlers // b) create TextContainer and call InitializeTextContainer // c) configure TextEditor by setting appropriate properties CoerceValue(HorizontalScrollBarVisibilityProperty); // Security team really wants to set AllowDrop property value as "False" // not to generate the security exception that can be happened in the // partial trust environment. if (!SecurityHelper.CallerHasPermissionWithAppDomainOptimization(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode))) { AllowDrop = false; } } #endregion Constructors //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods ////// Appends text to the current text of text box /// You can use this method to add text to the existing text /// in the control instead of using the concatenation operator /// (+) to concatenate text to the Text property /// /// /// The text to append to the current contents of the text box /// ////// For RichTextBox this method works similar to TextRange.set_Text: /// every NewLine combination will insert a new Paragraph element. /// public void AppendText(string textData) { if (textData == null) { return; } TextRange range = new TextRange(_textContainer.End, _textContainer.End); range.Text = textData; // Note that in RichTextBox this assignment will convert NewLines into Paragraphs } ////// Called when the Template's tree has been generated /// public override void OnApplyTemplate() { base.OnApplyTemplate(); AttachToVisualTree(); } ////// Copy the current selection in the text box to the clipboard /// ////// Critical - Calls TextEditorCopyPaste.Copy which sets data on the clipboard. /// PublicOK - Indicates that this was not a user-initiated call, so TextEditorCopyPaste.Copy will /// check for clipboard permission. /// [SecurityCritical] public void Copy() { TextEditorCopyPaste.Copy(this.TextEditor, false); } ////// Moves the current selection in the textbox to the clipboard /// ////// Critical - Calls TextEditorCopyPaste.Cut which sets data on the clipboard. /// PublicOK - Indicates that this was not a user-initiated call, so TextEditorCopyPaste.Cut will /// check for clipboard permission. /// [SecurityCritical] public void Cut() { TextEditorCopyPaste.Cut(this.TextEditor, false); } ////// Replaces the current selection in the textbox with the contents /// of the Clipboard /// public void Paste() { TextEditorCopyPaste.Paste(this.TextEditor); } ////// Select all text in the TextBox /// public void SelectAll() { using (this.TextSelectionInternal.DeclareChangeBlock()) { TextSelectionInternal.Select(_textContainer.Start, _textContainer.End); } } ////// Scroll content by one line to the left. /// public void LineLeft() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.LineLeft(); } } ////// Scroll content by one line to the right. /// public void LineRight() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.LineRight(); } } ////// Scroll content by one page to the left. /// public void PageLeft() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageLeft(); } } ////// Scroll content by one page to the right. /// public void PageRight() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageRight(); } } ////// Scroll content by one line to the top. /// public void LineUp() { UpdateLayout(); DoLineUp(); } ////// Scroll content by one line to the bottom. /// public void LineDown() { UpdateLayout(); DoLineDown(); } ////// Scroll content by one page to the top. /// public void PageUp() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageUp(); } } ////// Scroll content by one page to the bottom. /// public void PageDown() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.PageDown(); } } ////// Vertically scroll to the beginning of the content. /// public void ScrollToHome() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToHome(); } } ////// Vertically scroll to the end of the content. /// public void ScrollToEnd() { if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToEnd(); } } ////// Scroll horizontally to the specified offset. /// public void ScrollToHorizontalOffset(double offset) { if (Double.IsNaN(offset)) { throw new ArgumentOutOfRangeException("offset"); } if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToHorizontalOffset(offset); } } ////// Scroll vertically to the specified offset. /// public void ScrollToVerticalOffset(double offset) { if (Double.IsNaN(offset)) { throw new ArgumentOutOfRangeException("offset"); } if (this.ScrollViewer != null) { UpdateLayout(); this.ScrollViewer.ScrollToVerticalOffset(offset); } } ////// Undo the most recent undo unit on the stack. /// ////// true if undo succeeds, false otherwise (including when the stack is empty) /// public bool Undo() { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && undoManager.UndoCount > undoManager.MinUndoStackCount) { this.TextEditor.Undo(); return true; } return false; } ////// Redo the most recent undo unit on the stack. /// ////// true if redo succeeds, false otherwise (including when the stack is empty) /// public bool Redo() { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && undoManager.RedoCount > 0) { this.TextEditor.Redo(); return true; } return false; } ////// Lock the most recently added undo unit, preventing it from being reopened. /// ////// This method is intended to be called by an application when a non-text undo unit is added /// to the application's own undo stack on top of a text undo unit. By calling this method, /// the next text undo unit will not attempt to merge with the previous one. /// public void LockCurrentUndoUnit() { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { // find the deepest open unit, and lock the last unit added to it IParentUndoUnit openedUnit = undoManager.OpenedUnit; if (openedUnit != null) { while (openedUnit.OpenedUnit != null) { openedUnit = openedUnit.OpenedUnit; } if (openedUnit.LastUnit is IParentUndoUnit) { openedUnit.OnNextAdd(); } } else if (undoManager.LastUnit is IParentUndoUnit) { ((IParentUndoUnit)undoManager.LastUnit).OnNextAdd(); // } } } //......................................................... // // Change Notifications // //......................................................... ////// Begins a change block. /// public void BeginChange() { this.TextEditor.Selection.BeginChange(); } ////// Ends a change block. /// public void EndChange() { if (this.TextEditor.Selection.ChangeBlockLevel == 0) { throw new InvalidOperationException(SR.Get(SRID.TextBoxBase_UnmatchedEndChange)); } this.TextEditor.Selection.EndChange(); } ////// Creates and returns a change block /// ///IDisposable public IDisposable DeclareChangeBlock() { return this.TextEditor.Selection.DeclareChangeBlock(); } #endregion Public Methods //----------------------------------------------------- // // Public Properties // //------------------------------------------------------ #region Public Properties ////// Alias for TextEditor.IsReadOnly dependency property. /// Enables editing within this textbox. /// public static readonly DependencyProperty IsReadOnlyProperty = TextEditor.IsReadOnlyProperty.AddOwner( typeof(TextBoxBase), new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.Inherits, new PropertyChangedCallback(OnVisualStatePropertyChanged))); ////// Whether or not the Textbox is read-only /// public bool IsReadOnly { get { return (bool) GetValue(TextEditor.IsReadOnlyProperty); } set { SetValue(TextEditor.IsReadOnlyProperty, value); } } ////// DependencyProperty backing IsReadOnlyCaretVisible. /// public static readonly DependencyProperty IsReadOnlyCaretVisibleProperty = DependencyProperty.Register("IsReadOnlyCaretVisible", typeof(bool), typeof(TextBoxBase), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsReadOnlyCaretVisiblePropertyChanged))); ////// Whether or not the caret is visible when the textbox is read-only. /// public bool IsReadOnlyCaretVisible { get { return (bool)GetValue(IsReadOnlyCaretVisibleProperty); } set { SetValue(IsReadOnlyCaretVisibleProperty, value); } } ////// Indicates if VK_Return character is accepted as a normal new-line character, if it is true, it will insert a new-line to the textbox /// or other editable controls, if it is false, it will not insert a new-line character to the controls's content, but just /// activates the control with focus. /// /// Default: true. /// TextBox and/or RichTextBox need to set this value appropriately /// public static readonly DependencyProperty AcceptsReturnProperty = KeyboardNavigation.AcceptsReturnProperty.AddOwner(typeof(TextBoxBase)); ////// Whether or not the Textbox accepts newlines /// public bool AcceptsReturn { get { return (bool) GetValue(AcceptsReturnProperty); } set { SetValue(AcceptsReturnProperty, value); } } ////// Indicates if VK_TAB character is accepted as a normal tab char, if it is true, it will insert a tab character to the control's content, /// otherwise, it will not insert new tab to the content of control, instead, it will navigate the focus to the next IsTabStop control. /// /// Default: false. /// /// TextBox and RichTextBox need to set the value appropriately. /// public static readonly DependencyProperty AcceptsTabProperty = DependencyProperty.Register( "AcceptsTab", // Property name typeof(bool), // Property type typeof(TextBoxBase), // Property owner new FrameworkPropertyMetadata(false /*default value*/)); ////// Whether or not the Textbox accepts tabs /// public bool AcceptsTab { get { return (bool) GetValue(AcceptsTabProperty); } set { SetValue(AcceptsTabProperty, value); } } ////// Access to all spelling options. /// public SpellCheck SpellCheck { get { return new SpellCheck(this); } } ////// Exposes ScrollViewer's HorizontalScrollBarVisibility property /// Default: Hidden /// public static readonly DependencyProperty HorizontalScrollBarVisibilityProperty = ScrollViewer.HorizontalScrollBarVisibilityProperty.AddOwner( typeof(TextBoxBase), new FrameworkPropertyMetadata( ScrollBarVisibility.Hidden, new PropertyChangedCallback(OnScrollViewerPropertyChanged))); // PropertyChangedCallback ////// Whether or not a horizontal scrollbar is shown /// public ScrollBarVisibility HorizontalScrollBarVisibility { get { return (ScrollBarVisibility) GetValue(HorizontalScrollBarVisibilityProperty); } set { SetValue(HorizontalScrollBarVisibilityProperty, value); } } ////// Exposes ScrollViewer's VerticalScrollBarVisibility property /// Default: Hidden /// public static readonly DependencyProperty VerticalScrollBarVisibilityProperty = ScrollViewer.VerticalScrollBarVisibilityProperty.AddOwner( typeof(TextBoxBase), new FrameworkPropertyMetadata(ScrollBarVisibility.Hidden, new PropertyChangedCallback(OnScrollViewerPropertyChanged))); ////// Whether or not a vertical scrollbar is shown /// public ScrollBarVisibility VerticalScrollBarVisibility { get { return (ScrollBarVisibility) GetValue(VerticalScrollBarVisibilityProperty); } set { SetValue(VerticalScrollBarVisibilityProperty, value); } } ////// Horizontal size of scrollable content; 0.0 if TextBox is non-scrolling /// public double ExtentWidth { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ExtentWidth : 0.0; } } ////// Vertical size of scrollable content; 0.0 if TextBox is non-scrolling /// public double ExtentHeight { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ExtentHeight : 0.0; } } ////// Horizontal size of scroll area; 0.0 if TextBox is non-scrolling /// public double ViewportWidth { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ViewportWidth : 0.0; } } ////// Vertical size of scroll area; 0.0 if TextBox is non-scrolling /// public double ViewportHeight { get { return (this.ScrollViewer != null) ? this.ScrollViewer.ViewportHeight : 0.0; } } ////// Actual HorizontalOffset contains the ScrollViewer's current horizontal offset. /// This is a computed value, depending on the state of ScrollViewer, its Viewport, Extent /// and previous scrolling commands. /// public double HorizontalOffset { get { return (this.ScrollViewer != null) ? this.ScrollViewer.HorizontalOffset : 0.0; } } ////// Actual VerticalOffset contains the ScrollViewer's current vertical offset. /// This is a computed value, depending on the state of ScrollViewer, its Viewport, Extent /// and previous scrolling commands. /// public double VerticalOffset { get { return (this.ScrollViewer != null) ? this.ScrollViewer.VerticalOffset : 0.0; } } ////// Can the most recent action on the text box be undone? Since we will frequently be called /// during a TextChanged event when the undo stack hasn't yet been modified to reflect the /// pending change, just looking at the UndoCount isn't sufficient. TextEditor caches /// the pending undo action with us so we can refer to it now. /// public bool CanUndo { get { UndoManager undoManager; undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && (_pendingUndoAction != UndoAction.Clear && (undoManager.UndoCount > undoManager.MinUndoStackCount || (undoManager.State != UndoState.Undo && _pendingUndoAction == UndoAction.Create)))) { return true; } else { return false; } } } ////// Can the most recent undone action on the text box be redone? /// public bool CanRedo { get { UndoManager undoManager; undoManager = UndoManager.GetUndoManager(this); if (undoManager != null && (_pendingUndoAction != UndoAction.Clear && (undoManager.RedoCount > 0 || (undoManager.State == UndoState.Undo && _pendingUndoAction == UndoAction.Create)))) { return true; } else { return false; } } } ////// Enables or disabled undo support on this Control. /// ////// Defaults to true. /// /// The control's undo record is cleared when this property transitions /// to false. /// public static readonly DependencyProperty IsUndoEnabledProperty = DependencyProperty.Register("IsUndoEnabled", typeof(bool), typeof(TextBoxBase), new FrameworkPropertyMetadata(true, new PropertyChangedCallback(OnIsUndoEnabledChanged))); ////// Enables or disabled undo support on this Control. /// ////// Defaults to true. /// /// The control's undo record is cleared when this property transitions /// to false. /// public bool IsUndoEnabled { get { return (bool)GetValue(IsUndoEnabledProperty); } set { SetValue(IsUndoEnabledProperty, value); } } ////// Sets the number of actions stored in the undo queue. /// ////// The value must be >= -1. /// /// -1 sets the storage to "infinite", limited only by available memory. /// 0 disables undo. /// /// Setting any value will clear the existing queue. /// /// An InvalidOperationException is thrown if the value is set inside to /// context of a BeginChange/EndChange pair while IsUndoEnabled is true /// (ie, you may not set this property while an undo unit is open). /// /// The default value is -1. /// public static readonly DependencyProperty UndoLimitProperty = DependencyProperty.Register("UndoLimit", typeof(int), typeof(TextBoxBase), new FrameworkPropertyMetadata(UndoManager.UndoLimitDefaultValue, new PropertyChangedCallback(OnUndoLimitChanged)), new ValidateValueCallback(UndoLimitValidateValue)); ////// public int UndoLimit { get { return (int)GetValue(UndoLimitProperty); } set { SetValue(UndoLimitProperty, value); } } ////// /// The DependencyID for the AutoWordSelection property. /// Flags: Can be used in style rules /// Default Value: false /// public static readonly DependencyProperty AutoWordSelectionProperty = DependencyProperty.Register( "AutoWordSelection", // Property name typeof(bool), // Property type typeof(TextBoxBase), // Property owner new FrameworkPropertyMetadata(false)); ////// Whether or not dragging with the mouse automatically selects words /// public bool AutoWordSelection { get { return (bool)GetValue(AutoWordSelectionProperty); } set { SetValue(AutoWordSelectionProperty, value); } } ////// Brush used for selection fill. /// ////// If set to null, the selection will not be rendered. /// public static readonly DependencyProperty SelectionBrushProperty = DependencyProperty.Register("SelectionBrush", typeof(Brush), typeof(TextBoxBase), new FrameworkPropertyMetadata(GetDefaultSelectionBrush(), new PropertyChangedCallback(UpdateCaretElement))); ////// public Brush SelectionBrush { get { return (Brush)GetValue(SelectionBrushProperty); } set { SetValue(SelectionBrushProperty, value); } } ////// /// Opacity used for drawing the selection. /// ////// The opacity of SelectionBrush will also be respected (multiplied with this one during render). /// public static readonly DependencyProperty SelectionOpacityProperty = DependencyProperty.Register("SelectionOpacity", typeof(double), typeof(TextBoxBase), new FrameworkPropertyMetadata(0.4, new PropertyChangedCallback(UpdateCaretElement))); ////// public double SelectionOpacity { get { return (double)GetValue(SelectionOpacityProperty); } set { SetValue(SelectionOpacityProperty, value); } } ////// /// Brush used for the caret. /// ////// If set to null, the default behavior of setting the caret color to the inverse of the background color will be used. /// public static readonly DependencyProperty CaretBrushProperty = DependencyProperty.Register("CaretBrush", typeof(Brush), typeof(TextBoxBase), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(UpdateCaretElement))); ////// 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" /// public static readonly RoutedEvent TextChangedEvent = EventManager.RegisterRoutedEvent( "TextChanged", // Event name RoutingStrategy.Bubble, // typeof(TextChangedEventHandler), // typeof(TextBoxBase)); // ////// Event fired from this text box when its inner content /// has been changed. /// ////// The event itself is defined on TextEditor. /// public event TextChangedEventHandler TextChanged { add { AddHandler(TextChangedEvent, value); } remove { RemoveHandler(TextChangedEvent, value); } } ////// Event for "Selection has changed" /// public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent( "SelectionChanged", // Event name RoutingStrategy.Bubble, // typeof(RoutedEventHandler), // typeof(TextBoxBase)); // ////// Event fired from this text box when its selection has been changed. /// public event RoutedEventHandler SelectionChanged { add { AddHandler(SelectionChangedEvent, value); } remove { RemoveHandler(SelectionChangedEvent, value); } } #endregion Public Events //----------------------------------------------------- // // Protected Methods // //------------------------------------------------------ #region Protected Methods internal override void ChangeVisualState(bool useTransitions) { // See ButtonBase.ChangeVisualState. // This method should be exactly like it, except we have a ReadOnly state instead of Pressed if (!IsEnabled) { VisualStateManager.GoToState(this, VisualStates.StateDisabled, useTransitions); } else if (IsReadOnly) { VisualStateManager.GoToState(this, VisualStates.StateReadOnly, useTransitions); } else if (IsMouseOver) { VisualStateManager.GoToState(this, VisualStates.StateMouseOver, useTransitions); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } if (IsKeyboardFocused) { VisualStateManager.GoToState(this, VisualStates.StateFocused, useTransitions); } else { VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions); } base.ChangeVisualState(useTransitions); } ////// Called when content in this Control changes. /// Raises the TextChanged event. /// /// protected virtual void OnTextChanged(TextChangedEventArgs e) { RaiseEvent(e); } ////// Called when the caret or selection changes position. /// Raises the SelectionChanged event. /// /// protected virtual void OnSelectionChanged(RoutedEventArgs e) { RaiseEvent(e); } ////// 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(); } } ////// ScrollViewer marks all mouse wheel events as handled, even if no scrolling occurs. This means that /// when mousewheeling through a document, if the cursor happens to land on a textbox, scrolling will /// stop when the textbox reaches the end of its content. We want the scroll event to continue to the /// outer control in such a case so that outer control continues scrolling. /// /// MouseWheelEventArgs protected override void OnMouseWheel(MouseWheelEventArgs e) { if (e == null) { throw new ArgumentNullException("e"); } if (this.ScrollViewer != null) { // Only raise the event on ScrollViewer if we're actually going to scroll if ((e.Delta > 0 && VerticalOffset != 0) /* scrolling up */ || (e.Delta < 0 && VerticalOffset < this.ScrollViewer.ScrollableHeight) /* scrolling down */ ) { Invariant.Assert(this.RenderScope is IScrollInfo); if (e.Delta > 0) { ((IScrollInfo)this.RenderScope).MouseWheelUp(); } else { ((IScrollInfo)this.RenderScope).MouseWheelDown(); } e.Handled = true; } } base.OnMouseWheel(e); } ////// Virtual method reporting a key was pressed /// protected override void OnPreviewKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnPreviewKeyDown(e); } } ////// Virtual method reporting a key was pressed /// protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnKeyDown(e); } } ////// Virtual method reporting a key was released /// protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnKeyUp(e); } } ////// Virtual method reporting text composition /// protected override void OnTextInput(TextCompositionEventArgs e) { base.OnTextInput(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnTextInput(e); } } ////// Virtual method reporting the mouse button was pressed /// protected override void OnMouseDown(MouseButtonEventArgs e) { base.OnMouseDown(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnMouseDown(e); } } ////// Virtual method reporting a mouse move /// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Handled) { return; } if (_textEditor != null) { _textEditor.OnMouseMove(e); } } ////// Virtual method reporting the mouse button was released /// protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (e.Handled) { return; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _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; } if (_textEditor != null) { _textEditor.OnLostFocus(e); } } // Allocates the initial render scope for this control. internal abstract FrameworkElement CreateRenderScope(); ////// Handler for TextContainer.Changed event. Raises the TextChanged event on UiScope. /// for editing controls. /// /// /// sender /// /// /// event args /// internal virtual 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 && !e.HasLocalPropertyValueChange) { return; } UndoManager undoManager = UndoManager.GetUndoManager(this); UndoAction undoAction; if (undoManager != null) // Will be null for controls like PasswordBox that don't use undo. { if (_textEditor.UndoState == UndoState.Redo) { undoAction = UndoAction.Redo; } else if (_textEditor.UndoState == UndoState.Undo) { undoAction = UndoAction.Undo; } else if (undoManager.OpenedUnit == null) { undoAction = UndoAction.Clear; } else if (undoManager.LastReopenedUnit == undoManager.OpenedUnit) { undoAction = UndoAction.Merge; } else { undoAction = UndoAction.Create; } } else { undoAction = UndoAction.Create; } // The undo stack hasn't yet been modified by this change, so CanUndo will not // necessarily yield the correct result if queried during the TextChange event. // Store the undo action in the uiScope, so CanUndo can // reference it to provide the correct result. _pendingUndoAction = undoAction; try { OnTextChanged(new TextChangedEventArgs(TextChangedEvent, undoAction, new ReadOnlyCollection(e.Changes.Values))); } finally { _pendingUndoAction = UndoAction.None; } } #endregion Protected Methods //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods // Attaches this control to a new TextContainer. internal void InitializeTextContainer(TextContainer textContainer) { Invariant.Assert(textContainer != null); Invariant.Assert(textContainer.TextSelection == null); // Uninitialize previous TextEditor if (_textContainer != null) { Invariant.Assert(_textEditor != null); Invariant.Assert(_textEditor.TextContainer == _textContainer); Invariant.Assert(_textEditor.TextContainer.TextSelection == _textEditor.Selection); // Detach existing editor from VisualTree DetachFromVisualTree(); // Discard TextEditor - must release text container _textEditor.OnDetach(); } // Save text container _textContainer = textContainer; _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); _textEditor.Selection.Changed += new EventHandler(OnSelectionChangedInternal); // Init a default undo limit. UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { undoManager.UndoLimit = this.UndoLimit; } // Delay raising automation events until the automation subsystem is activated by a client. // ISSUE-2005/01/23-vsmirnov - Adding an event listener to AutomationProvider apparently // causes memory leaks because TextBoxBase is never released. I comment it out for now just // to fix the build break (perf DRT failure). Need to find a right fix later. // AutomationProvider.Activated += new AutomationActivatedEventHandler(OnAutomationActivated); } /// /// Returns a TextPosition matching the specified pixel coordinates. /// /// /// Pixel coordinate to hittest with. /// point is expected to be in the coordinate space of this TextBox. /// /// /// If true, heuristics are applied to find the closest character /// position to point, even if point does not intersect any character /// bounding box. /// ////// A TextPosition and its orientation matching the specified pixel. /// May return null if snapToText is false and point does not fall /// within any character bounding box. /// internal TextPointer GetTextPositionFromPointInternal(Point point, bool snapToText) { TextPointer position; // Transform to content coordinates. GeneralTransform transform = this.TransformToDescendant(this.RenderScope); if (transform != null) { transform.TryTransform(point, out point); } if (TextEditor.GetTextView(this.RenderScope).Validate(point)) { position = (TextPointer)TextEditor.GetTextView(this.RenderScope).GetTextPositionFromPoint(point, snapToText); } else { position = snapToText ? this.TextContainer.Start : null; } return position; } ////// Retrieves the height and offset, in pixels, of the edge of /// the object/character represented by position. /// /// /// Position of an object/character. /// /// /// Receives the bounding box. /// ////// Returns false if no layout is available. In this case rect will be set empty. /// ////// Coordinates of the return value are relative to this TextBox. /// /// Rect.Width is always 0. /// /// If the content is empty, then this method returns the expected /// height of a character, if placed at the specified position. /// internal bool GetRectangleFromTextPosition(TextPointer position, out Rect rect) { Point offset; if (position == null) { throw new ArgumentNullException("position"); } // Validate layout information on TextView if (TextEditor.GetTextView(this.RenderScope).Validate(position)) { // Get the rect in local content coordinates. rect = TextEditor.GetTextView(this.RenderScope).GetRectangleFromTextPosition(position); // Transform to RichTextBox control coordinates. offset = new Point(0, 0); GeneralTransform transform = this.TransformToDescendant(this.RenderScope); if (transform != null) { transform.TryTransform(offset, out offset); } rect.X -= offset.X; rect.Y -= offset.Y; } else { rect = Rect.Empty; } return rect != Rect.Empty; } ////// Detaches the editor from old visual tree and attaches it to a new one /// internal virtual void AttachToVisualTree() { DetachFromVisualTree(); // Walk the visual tree to find our Text element SetRenderScopeToContentHost(); // Set properties on ScrollViewer // 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.ScrollChanged += new ScrollChangedEventHandler(OnScrollChanged); // SetValue(TextEditor.PageHeightProperty, this.ScrollViewer.ViewportHeight); // Need to make scroll viewer non-focusable, otherwise it will eat keyboard navigation from editor this.ScrollViewer.Focusable = false; // Prevent mouse wheel scrolling from breaking when there's no more content in the direction of the scroll this.ScrollViewer.HandlesMouseWheelScrolling = false; if (this.ScrollViewer.Background == null) { // prevent hit-testing through padding this.ScrollViewer.Background = Brushes.Transparent; } OnScrollViewerPropertyChanged(this, new DependencyPropertyChangedEventArgs(ScrollViewer.HorizontalScrollBarVisibilityProperty, null /* old value */, this.GetValue(HorizontalScrollBarVisibilityProperty))); OnScrollViewerPropertyChanged(this, new DependencyPropertyChangedEventArgs(ScrollViewer.VerticalScrollBarVisibilityProperty, null /* old value */, this.GetValue(VerticalScrollBarVisibilityProperty))); OnScrollViewerPropertyChanged(this, new DependencyPropertyChangedEventArgs(ScrollViewer.PaddingProperty, null /* old value */, this.GetValue(PaddingProperty))); } else { ClearValue(TextEditor.PageHeightProperty); } } // Do the work of line up. Can be overridden by subclass to implement true line up. internal virtual void DoLineUp() { if (this.ScrollViewer != null) { this.ScrollViewer.LineUp(); } } // Do the work of line down. Can be overridden by subclass to implement true line down. internal virtual void DoLineDown() { if (this.ScrollViewer != null) { this.ScrollViewer.LineDown(); } } ////// When RenderScope is FlowDocumentView, events can bypass our nested ScrollViewer. /// We want to make sure that ScrollViewer-- and any other elements in our style-- /// always gets a `crack at mouse events. /// internal override void AddToEventRouteCore(EventRoute route, RoutedEventArgs args) { base.AddToEventRouteCore(route, args); // Walk up the tree from the RenderScope to this, adding each element to the route Visual visual = this.RenderScope; while (visual != this && visual != null) { if (visual is UIElement) { ((UIElement)visual).AddToEventRoute(route, args); } visual = VisualTreeHelper.GetParent(visual) as Visual; } } ////// Helper method to update the IsUndoEnabled flag within UndoManager /// attached to the TextBox. /// /// /// New Value of IsUndoEnabled flag. /// internal void ChangeUndoEnabled(bool value) { // if (this.TextSelectionInternal.ChangeBlockLevel > 0) { throw new InvalidOperationException(SR.Get(SRID.TextBoxBase_CantSetIsUndoEnabledInsideChangeBlock)); } UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { if (!value && undoManager.IsEnabled) { undoManager.Clear(); } undoManager.IsEnabled = value; } } ////// Helper method to update the UndoLimit in UndoManager /// attached to the TextBox. /// /// /// New Value of UndoLimit. /// internal void ChangeUndoLimit(object value) { UndoManager undoManager = UndoManager.GetUndoManager(this); if (undoManager != null) { if (undoManager.OpenedUnit != null) { // throw new InvalidOperationException(SR.Get(SRID.TextBoxBase_CantSetIsUndoEnabledInsideChangeBlock)); } int limit; if (value == DependencyProperty.UnsetValue) { limit = UndoManager.UndoLimitDefaultValue; } else { limit = (int)value; } undoManager.UndoLimit = limit; } } #endregion Internal Methods //------------------------------------------------------ // // Internal Properties // //----------------------------------------------------- #region Internal Properties ////// Access to the ScrollViewer in textbox style /// internal ScrollViewer ScrollViewer { get { if (_scrollViewer == null) { if (_textEditor != null) { // TextEditor's _Scroller property finds a ScrollViewer found // by a tree walk from the editor's render scope within ui scope. _scrollViewer = _textEditor._Scroller as ScrollViewer; } } return _scrollViewer; } } ////// Text Selection (readonly) /// internal TextSelection TextSelectionInternal { get { return (TextSelection)_textEditor.Selection; } } ////// A TextContainer covering the TextBox's inner content. /// Never returns null, throws SystemException if unavailable. /// internal TextContainer TextContainer { get { return _textContainer; } } ////// readonly access to internal content control /// internal FrameworkElement RenderScope { get { return _renderScope; } } // Expose _pendingUndoAction for DrtEditing.exe, via reflection. internal UndoAction PendingUndoAction { get { return _pendingUndoAction; } set { _pendingUndoAction = value; } } // TextEditor attached to this control. internal TextEditor TextEditor { get { return _textEditor; } } // True if style has been applied to the control and // ContentHostTemplateName was successfully found in it. internal bool IsContentHostAvailable { get { return _textBoxContentHost != null; } } #endregion Internal Properties //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods ////// Clear our layout-specific data, and detach our current renderScope from our text editor. /// private void DetachFromVisualTree() { if (_textEditor != null) { _textEditor.Selection.DetachFromVisualTree(); } // Detach scroll handler from old 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.ScrollChanged -= new ScrollChangedEventHandler(OnScrollChanged); } // Invalidate our cached copy of scroll viewer. _scrollViewer = null; ClearContentHost(); } // Initializes a new render scope. private void InitializeRenderScope() { if (_renderScope == null) { return; } // Map the TextContainer and TextView. ITextView textView = (ITextView)((IServiceProvider)_renderScope).GetService(typeof(ITextView)); this.TextContainer.TextView = textView; _textEditor.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; // Remove our content from the renderScope if (_renderScope is TextBoxView) { // Nothing to do. } else if (_renderScope is FlowDocumentView) { if (((FlowDocumentView)_renderScope).Document != null) { ((FlowDocumentView)_renderScope).Document.Uninitialize(); ((FlowDocumentView)_renderScope).Document = null; } } else { Invariant.Assert(_renderScope == null, "_renderScope must be null here"); } } ////// Creates the default brush used for selection rendering. /// private static Brush GetDefaultSelectionBrush() { Brush selectionBrush = new SolidColorBrush(SystemColors.HighlightColor); selectionBrush.Freeze(); return selectionBrush; } ////// Callback for PageHeight GetValue. /// /// /// dependency object /// ////// private static object OnPageHeightGetValue(DependencyObject d) { return ((TextBoxBase)d).ViewportHeight; } ////// Finds an element in a style temaplte marked as ContentHostTemplateName /// where our render scope must be placed as a child. /// private void SetRenderScopeToContentHost() { FrameworkElement renderScope = CreateRenderScope(); // Clear the content host from previous render scope (if any) ClearContentHost(); // Find ContentHostTemplateName in the style _textBoxContentHost = 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 // TextBox goes into disabled state, but not throw. // Add renderScope as a child of ContentHostTemplateName _renderScope = renderScope; if (_textBoxContentHost is ScrollViewer) { ScrollViewer scrollViewer = (ScrollViewer)_textBoxContentHost; if (scrollViewer.Content != null) { _renderScope = null; _textBoxContentHost = null; // throw new NotSupportedException(SR.Get(SRID.TextBoxScrollViewerMarkedAsTextBoxContentMustHaveNoContent)); } else { scrollViewer.Content = _renderScope; // this may replace old render scope in case of upgrade scenario in TextBox } } else if (_textBoxContentHost is Decorator) { Decorator decorator = (Decorator)_textBoxContentHost; if (decorator.Child != null) { _renderScope = null; _textBoxContentHost = 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 (_textBoxContentHost != null) { _textBoxContentHost = null; // throw new NotSupportedException(SR.Get(SRID.TextBoxInvalidTextContainer)); } } // Attach render scope to TextEditor InitializeRenderScope(); } 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 (_textBoxContentHost is ScrollViewer) { ((ScrollViewer)_textBoxContentHost).Content = null; } else if (_textBoxContentHost is Decorator) { ((Decorator)_textBoxContentHost).Child = null; } else { Invariant.Assert(_textBoxContentHost == null, "_textBoxContentHost must be null here"); } _textBoxContentHost = null; } ////// PropertyChanged handler for IsReadOnlyCaretVisibleProperty. /// private static void OnIsReadOnlyCaretVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; textBox.TextSelectionInternal.UpdateCaretState(CaretScrollMethod.None); ((ITextSelection)textBox.TextSelectionInternal).RefreshCaret(); } ////// Handler for ScrollViewer's OnScrollChanged event. /// internal virtual void OnScrollChanged(object sender, ScrollChangedEventArgs e) { // if (e.ViewportHeightChange != 0) { SetValue(TextEditor.PageHeightProperty, e.ViewportHeight); } } ////// TextSelection.Moved event listener. /// private void OnSelectionChangedInternal(object sender, EventArgs e) { #if OLD_AUTOMATION // It the automation subsystem is active, notify automation clients // about the selection change. if (AutomationProvider.IsActive) { RaiseSelectionChangedEvent(); } #endif OnSelectionChanged(new RoutedEventArgs(SelectionChangedEvent)); } #if OLD_AUTOMATION ////// A helper to raise AutomationEvents. /// The reason this method is standalone with MethodImplOptions.NoInlining is to avoid /// loading UIAutomation unless there's a client already present. /// [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private void RaiseSelectionChangedEvent() { AutomationProvider.RaiseAutomationEvent(TextPatternIdentifiers.TextSelectionChangedEvent, this); } #endif /// // 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; } } ////// Callback for changed ScrollViewer properties, forwarding values from TextBoxBase to ScrollViewer. /// /// /// TextBoxBase on which the property is changed /// /// event args internal static void OnScrollViewerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = d as TextBoxBase; if (textBox != null && textBox.ScrollViewer != null) { object value = e.NewValue; if (value == DependencyProperty.UnsetValue) { textBox.ScrollViewer.ClearValue(e.Property); } else { textBox.ScrollViewer.SetValue(e.Property, value); } } } // Callback for IsUndoEnabledProperty changes. private static void OnIsUndoEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; textBox.ChangeUndoEnabled((bool)e.NewValue); } ////// private static bool UndoLimitValidateValue(object value) { return ((int)value) >= -1; } // Callback for UndoLimitProperty changes. private static void OnUndoLimitChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; textBox.ChangeUndoLimit(e.NewValue); } ////// /// Callback for changed InputMethodEnabled properties /// /// /// TextBoxBase on which the property is changed /// /// event args ////// Critical:This code register command handlers for texteditor related events and commands (OnGotFocus) /// TreatAsSafe: This just hooks up methods that are internal to this class /// [SecurityCritical,SecurityTreatAsSafe] private static void OnInputMethodEnabledPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBox = (TextBoxBase)d; if ((textBox.TextEditor != null) && (textBox.TextEditor.TextStore != null)) { bool value = (bool)e.NewValue; if (value) { if (Keyboard.FocusedElement == textBox) { // Call TextStore.OnGotFocus() to set up the focus dim correctly. textBox.TextEditor.TextStore.OnGotFocus(); } } } } ////// PropertyChanged callback for a property that affects the selection or caret rendering. /// private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBoxBase textBoxBase = (TextBoxBase)d; if (textBoxBase.TextSelectionInternal != null) { CaretElement caretElement = textBoxBase.TextSelectionInternal.CaretElement; if (caretElement != null) { if (e.Property == CaretBrushProperty) { caretElement.UpdateCaretBrush(TextSelection.GetCaretBrush(textBoxBase.TextEditor)); } caretElement.InvalidateVisual(); } } } #endregion Private methods //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Fields private static DependencyObjectType _dType; // Text content owned by this TextBox. // private TextContainer _textContainer; // Text editor private TextEditor _textEditor; // An element marked as TextBoxContentto which we assign our _renderScope as a anonymous child. // In case when TextBoxContent is not an anonymouse child this member is null. private FrameworkElement _textBoxContentHost; // Encapsulated control that holds/implements our TextContainer. private FrameworkElement _renderScope; // ScrollViewer private ScrollViewer _scrollViewer; /// When TextEditor fires a TextChanged event, listeners may want to use the event to /// update their Undo/Redo UI. But the undo stack hasn't yet been modified by the event, /// so querying that stack won't give us the information we need to report correctly. /// TextBoxBase therefore caches the UndoAction here, so that CanUndo can reference it /// and make the right determination. private UndoAction _pendingUndoAction; // Part name used in the style. The class TemplatePartAttribute should use the same name internal const string ContentHostTemplateName = "PART_ContentHost"; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ErrorsHelper.cs
- WebConfigurationFileMap.cs
- ExplicitDiscriminatorMap.cs
- RadioButtonPopupAdapter.cs
- BaseCodeDomTreeGenerator.cs
- WsrmMessageInfo.cs
- DataRow.cs
- safelinkcollection.cs
- MenuEventArgs.cs
- BadImageFormatException.cs
- CompModSwitches.cs
- ParameterBuilder.cs
- DisplayNameAttribute.cs
- RoutedEventConverter.cs
- RenderingEventArgs.cs
- DataGridViewImageColumn.cs
- Itemizer.cs
- FontSizeConverter.cs
- Models.cs
- Decimal.cs
- DataTemplateSelector.cs
- BindingNavigatorDesigner.cs
- DbInsertCommandTree.cs
- AdCreatedEventArgs.cs
- InputReportEventArgs.cs
- InvalidAsynchronousStateException.cs
- SqlRowUpdatingEvent.cs
- ExpandoObject.cs
- CalendarDateRangeChangingEventArgs.cs
- InternalConfigHost.cs
- TemplateFactory.cs
- FormCollection.cs
- BitmapEffectOutputConnector.cs
- ValidatorUtils.cs
- RightsManagementPermission.cs
- RoleService.cs
- RightsManagementEncryptionTransform.cs
- FormConverter.cs
- HttpWebResponse.cs
- PropertyRecord.cs
- UIElement3D.cs
- SdlChannelSink.cs
- ThicknessConverter.cs
- EditorZoneBase.cs
- ViewStateException.cs
- ComponentResourceManager.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- ListViewGroupItemCollection.cs
- PeerApplication.cs
- DbProviderSpecificTypePropertyAttribute.cs
- TextBoxAutoCompleteSourceConverter.cs
- RawTextInputReport.cs
- ISAPIWorkerRequest.cs
- ScrollEvent.cs
- LambdaCompiler.Expressions.cs
- Vector3DAnimationBase.cs
- InternalsVisibleToAttribute.cs
- ValidatingPropertiesEventArgs.cs
- SafeProcessHandle.cs
- BuildManagerHost.cs
- AQNBuilder.cs
- SingleObjectCollection.cs
- CodeAccessSecurityEngine.cs
- HandlerBase.cs
- RelationshipEndMember.cs
- AppSecurityManager.cs
- VirtualizingPanel.cs
- ReadOnlyDataSource.cs
- ThreadStaticAttribute.cs
- BadImageFormatException.cs
- IdentifierCreationService.cs
- SafeReversePInvokeHandle.cs
- ScriptReferenceEventArgs.cs
- MetadataItemEmitter.cs
- XmlSchemaSimpleContentRestriction.cs
- ColumnClickEvent.cs
- PartitionResolver.cs
- FamilyCollection.cs
- DockAndAnchorLayout.cs
- Crc32.cs
- BamlRecordReader.cs
- CssStyleCollection.cs
- ItemsPresenter.cs
- XmlSecureResolver.cs
- TreeSet.cs
- ShortcutKeysEditor.cs
- ControlCollection.cs
- UrlPath.cs
- SHA512Managed.cs
- ArithmeticException.cs
- MetadataArtifactLoaderXmlReaderWrapper.cs
- SamlAuthorityBinding.cs
- NamespaceTable.cs
- BrushMappingModeValidation.cs
- ToolboxDataAttribute.cs
- TypeConverter.cs
- FlowDocument.cs
- DecoderExceptionFallback.cs
- MouseGestureConverter.cs
- AppDomainManager.cs