// Token: 0x06002BA8 RID: 11176 RVA: 0x000C7340 File Offset: 0x000C5540 void ITextContainer.EndChange(bool skipEvents) { Invariant.Assert(this._changeBlockLevel > 0, "Unmatched EndChange call!"); this._changeBlockLevel--; if (this._changeBlockLevel == 0 && this._changes != null) { TextContainerChangedEventArgs changes = this._changes; this._changes = null; if (this.Changed != null && !skipEvents) { this.Changed(this, changes); } } }
private void AddChange(ITextPointer startPosition, int symbolCount, PrecursorTextChangeType precursorTextChange) { Invariant.Assert(!_isReadOnly, "Illegal to modify DocumentSequenceTextContainer inside Change event scope!"); ITextContainer textContainer = (ITextContainer)this; textContainer.BeginChange(); try { // Contact any listeners. if (this.Changing != null) { Changing(this, EventArgs.Empty); } // Fire the ChangingEvent now if we haven't already. if (_changes == null) { _changes = new TextContainerChangedEventArgs(); } _changes.AddChange(precursorTextChange, DocumentSequenceTextPointer.GetOffsetToPosition(_start, startPosition), symbolCount, false /* collectTextChanges */); if (this.Change != null) { Invariant.Assert(precursorTextChange == PrecursorTextChangeType.ContentAdded || precursorTextChange == PrecursorTextChangeType.ContentRemoved); TextChangeType textChange = (precursorTextChange == PrecursorTextChangeType.ContentAdded) ? TextChangeType.ContentAdded : TextChangeType.ContentRemoved; _isReadOnly = true; try { // Pass in a -1 for charCount parameter. DocumentSequenceTextContainer // doesn't support this feature because it is only consumed by IMEs // which never run on read-only documents. Change(this, new TextContainerChangeEventArgs(startPosition, symbolCount, -1, textChange)); } finally { _isReadOnly = false; } } } finally { textContainer.EndChange(); } }
/// <summary> /// Handler for TextContainer.Changed event. Raises the TextChanged event on UiScope. /// for editing controls. /// </summary> /// <param name="sender"> /// sender /// </param> /// <param name="e"> /// event args /// </param> 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<TextChange>(e.Changes.Values))); } finally { _pendingUndoAction = UndoAction.None; } }
/// <summary> /// Handler for text array change notifications. /// </summary> /// <param name="sender"> /// sender /// </param> /// <param name="e"> /// event args /// </param> private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { // If only properties on the text changed, don't fire a content change event. // This can happen even in a plain text TextBox if we switch logical trees. if (!e.HasContentAddedOrRemoved) { return; } RaiseEvent(new RoutedEventArgs(PasswordChangedEvent)); }
//----------------------------------------------------- // // Private Methods // //----------------------------------------------------- #region Private Methods private void AddChange(ITextPointer startPosition, int symbolCount, PrecursorTextChangeType precursorTextChange) { Invariant.Assert(_changeBlockLevel > 0, "All public APIs must call BeginChange!"); Invariant.Assert(!_isReadOnly, "Illegal to modify PasswordTextContainer inside Change event scope!"); // Contact any listeners. if (this.Changing != null) { Changing(this, EventArgs.Empty); } // Fire the ChangingEvent now if we haven't already. if (_changes == null) { _changes = new TextContainerChangedEventArgs(); } _changes.AddChange(precursorTextChange, startPosition.Offset, symbolCount, false /* collectTextChanges */); if (this.Change != null) { Invariant.Assert(precursorTextChange == PrecursorTextChangeType.ContentAdded || precursorTextChange == PrecursorTextChangeType.ContentRemoved); TextChangeType textChange = (precursorTextChange == PrecursorTextChangeType.ContentAdded) ? TextChangeType.ContentAdded : TextChangeType.ContentRemoved; _isReadOnly = true; try { Change(this, new TextContainerChangeEventArgs(startPosition, symbolCount, symbolCount, textChange)); } finally { _isReadOnly = false; } } }
/// <summary> /// Handler for TextContainer.Changed event. /// </summary> internal override void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { bool resetText = false; string newTextValue = null; try { // if there are re-entrant changes, only raise public events // after the outermost change completes _changeEventNestingCount++; // Ignore property changes that originate from OnTextPropertyChange. if (!_isInsideTextContentChange) { _isInsideTextContentChange = true; // Use a DeferredTextReference instead of calculating the new // value now for better performance. Most of the time no // one cares what the new value is, and loading our content into a // string can be extremely expensive. DeferredTextReference dtr = new DeferredTextReference(this.TextContainer); _newTextValue = dtr; SetCurrentDeferredValue(TextProperty, dtr); } } finally { _changeEventNestingCount--; if (_changeEventNestingCount == 0) { // when Text is data-bound, _newTextValue is converted from a // deferred reference to a string. The binding writes the string // back to the source, then computes a new value for Text (which // may be different, either because the source normalizes the value // or because of conversion and formatting). Usually this raises // a change notification for Text, which brings the Text property and // the text container into [....]. But this doesn't happen in one // case: when the normalized value is the same as the original // value for Text. The property engine thinks that Text hasn't // changed, and doesn't raise the notification. It's true that // Text hasn't changed, but we still need to update the text container, // which now displays the wrong value. // We detect that case by checking whether _newTextValue (the // text container value) agrees with Text. if (FrameworkCompatibilityPreferences.GetKeepTextBoxDisplaySynchronizedWithTextProperty()) { newTextValue = _newTextValue as String; resetText = (newTextValue != null && newTextValue != Text); } _isInsideTextContentChange = false; _newTextValue = DependencyProperty.UnsetValue; } } if (resetText) { // The text container holds a new value which round-trips to the // old value of Text. We need to bring the text container into [....]. try { _newTextValue = newTextValue; _isInsideTextContentChange = true; ++ _changeEventNestingCount; OnTextPropertyChanged(newTextValue, Text); } finally { -- _changeEventNestingCount; _isInsideTextContentChange = false; _newTextValue = DependencyProperty.UnsetValue; } } if (_changeEventNestingCount == 0) { // Let base raise the public TextBoxBase.TextChanged event. base.OnTextContainerChanged(sender, e); } }
//------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods /// <summary> /// Notify about content changes. /// </summary> private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { _textPeer.RaiseAutomationEvent(AutomationEvents.TextPatternOnTextChanged); }
/// <summary> /// Handler for TextContainer.Changed event. /// </summary> internal override void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { try { // if there are re-entrant changes, only raise public events // after the outermost change completes _changeEventNestingCount++; // Ignore property changes that originate from OnTextPropertyChange. if (!_isInsideTextContentChange) { _isInsideTextContentChange = true; // Use a DeferredTextReference instead of calculating the new // value now for better performance. Most of the time no // one cares what the new value is, and loading our content into a // string can be extremely expensive. DeferredTextReference dtr = new DeferredTextReference(this.TextContainer); _newTextValue = dtr; SetCurrentDeferredValue(TextProperty, dtr); } } finally { _changeEventNestingCount--; if (_changeEventNestingCount == 0) { _isInsideTextContentChange = false; _newTextValue = DependencyProperty.UnsetValue; } } if (_changeEventNestingCount == 0) { // Let base raise the public TextBoxBase.TextChanged event. base.OnTextContainerChanged(sender, e); } }
// ------------------------------------------------------------------ // Handler for TextContainer.Changed notification. // ------------------------------------------------------------------ private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs args) { // Skip changes that only affect properties. if (args.HasContentAddedOrRemoved) { UpdateAccessKey(); } }
// Adds a change to the current change block. // This call must be preceeded by a matching BeforeAddChange. internal void AddChange(TextPointer startPosition, TextPointer endPosition, int symbolCount, int leftEdgeCharCount, int childCharCount, PrecursorTextChangeType textChange, DependencyProperty property, bool affectsRenderOnly) { Invariant.Assert(_changeBlockLevel > 0, "All public APIs must call BeginChange!"); Invariant.Assert(!CheckFlags(Flags.ReadOnly) || textChange == PrecursorTextChangeType.PropertyModified, "Illegal to modify TextContainer structure inside Change event scope!"); if (this.HasListeners) { // Lazy init _changes. This looks redundant with the BeforeAddChange call // we already require -- strictly speaking that's true. But in practice, // we want the Invariant in this method to remind callers to think about // when they must call BeforeAddChange ahead of logical tree events. Then, // in practice, there's a subtle bug where a listener might not initially // exist but is added during the logical tree events. That we handle // here with an additional BeforeAddChange call instead of requiring all // our callers to remember to handle the more subtle case. if (_changes == null) { _changes = new TextContainerChangedEventArgs(); } Invariant.Assert(_changes != null, "Missing call to BeforeAddChange!"); _changes.AddChange(textChange, startPosition.Offset, symbolCount, this.CollectTextChanges); if (this.ChangeHandler != null) { FireChangeEvent(startPosition, endPosition, symbolCount, leftEdgeCharCount, childCharCount, textChange, property, affectsRenderOnly); } } }
// Prepares the tree for an AddChange call, and raises the Changing // event if it has not already fired in this change block. // // This method must be called before a matching AddChange. // // (We cannot simply merge BeforeAddChange/AddChange because // in practice callers will sometimes raise LogicalTree events which // must be fired between Changing/Changed events.) internal void BeforeAddChange() { Invariant.Assert(_changeBlockLevel > 0, "All public APIs must call BeginChange!"); if (this.HasListeners) { // Contact any listeners. if (this.ChangingHandler != null) { ChangingHandler(this, EventArgs.Empty); } if (_changes == null) { _changes = new TextContainerChangedEventArgs(); } } }
// ................................................................ // // Event Handlers: Internal Events // // ................................................................ /// <summary> /// Handler for TextContainer.Changed event. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs e) { // Set short short-term dirty indicator to true. // The indicator is used in TextEditorMouse.MoveFocusToUiScope to check // that there is no side effects happened in content during focus movement this._contentChangeCounter++; }