Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Controls / AccessText.cs / 1 / AccessText.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System.Collections; using System.ComponentModel; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Markup; using System.Diagnostics; using System.Xml; using MS.Internal; namespace System.Windows.Controls { ////// AccessText Element - Register an accesskey specified after the underscore character in the text. /// [ContentProperty("Text")] public class AccessText : FrameworkElement, IAddChild { //------------------------------------------------------------------- // // IContentHost Members // //------------------------------------------------------------------- #region IAddChild members ////// Called to Add the object as a Child. /// /// /// Object to add as a child /// void IAddChild.AddChild(Object value) { ((IAddChild)TextBlock).AddChild(value); } ////// Called when text appears under the tag in markup. /// /// /// Text to Add to the Object /// void IAddChild.AddText(string text) { ((IAddChild)TextBlock).AddText(text); } #endregion IAddChild members //-------------------------------------------------------------------- // // LogicalTree // //------------------------------------------------------------------- #region LogicalTree ////// Returns enumerator to logical children. /// protected internal override IEnumerator LogicalChildren { get { return new RangeContentEnumerator(TextContainer.Start, TextContainer.End); } } #endregion LogicalTree //-------------------------------------------------------------------- // // Constructors // //-------------------------------------------------------------------- #region Constructors ////// AccessText constructor. /// public AccessText() : base() { } #endregion Constructors //------------------------------------------------------------------- // // Public Properties // //-------------------------------------------------------------------- #region Public Properties ////// Read only access to the key after the first underline character /// public char AccessKey { get { // return (_accessKey != null && _accessKey.Text.Length > 0) ? _accessKey.Text[0] : (char)0; } } #endregion Public Properties //------------------------------------------------------------------- // // Public Dynamic Properties // //------------------------------------------------------------------- #region Public Dynamic Properties ////// DependencyProperty for public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof(string), typeof(AccessText), new FrameworkPropertyMetadata( string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnTextChanged))); ///property. /// /// The Text property defines the text to be displayed. /// [DefaultValue("")] public string Text { get { return (string) GetValue(TextProperty); } set { SetValue(TextProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontFamily property specifies the name of font family. /// [Localizability( LocalizationCategory.Font, Modifiability = Modifiability.Unmodifiable )] public FontFamily FontFamily { get { return (FontFamily) GetValue(FontFamilyProperty); } set { SetValue(FontFamilyProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontStyle property requests normal, italic, and oblique faces within a font family. /// public FontStyle FontStyle { get { return (FontStyle) GetValue(FontStyleProperty); } set { SetValue(FontStyleProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontWeight property specifies the weight of the font. /// public FontWeight FontWeight { get { return (FontWeight) GetValue(FontWeightProperty); } set { SetValue(FontWeightProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontStretch property selects a normal, condensed, or extended face from a font family. /// public FontStretch FontStretch { get { return (FontStretch) GetValue(FontStretchProperty); } set { SetValue(FontStretchProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontSize property specifies the size of the font. /// [TypeConverter(typeof(FontSizeConverter))] [Localizability(LocalizationCategory.None)] public double FontSize { get { return (double) GetValue(FontSizeProperty); } set { SetValue(FontSizeProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty ForegroundProperty = TextElement.ForegroundProperty.AddOwner(typeof(AccessText)); ///property. /// /// The Foreground property specifies the foreground brush of an element's text content. /// public Brush Foreground { get { return (Brush) GetValue(ForegroundProperty); } set { SetValue(ForegroundProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty BackgroundProperty = TextElement.BackgroundProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The Background property defines the brush used to fill the content area. /// public Brush Background { get { return (Brush) GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextDecorationsProperty = Inline.TextDecorationsProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( new FreezableDefaultValueFactory(TextDecorationCollection.Empty), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextDecorations property specifies decorations that are added to the text of an element. /// public TextDecorationCollection TextDecorations { get { return (TextDecorationCollection) GetValue(TextDecorationsProperty); } set { SetValue(TextDecorationsProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextEffectsProperty = TextElement.TextEffectsProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( new FreezableDefaultValueFactory(TextEffectCollection.Empty), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextEffects property specifies effects that are added to the text of an element. /// public TextEffectCollection TextEffects { get { return (TextEffectCollection) GetValue(TextEffectsProperty); } set { SetValue(TextEffectsProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty LineHeightProperty = Block.LineHeightProperty.AddOwner(typeof(AccessText)); ///property. /// /// The LineHeight property specifies the height of each generated line box. /// [TypeConverter(typeof(LengthConverter))] public double LineHeight { get { return (double) GetValue(LineHeightProperty); } set { SetValue(LineHeightProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty LineStackingStrategyProperty = Block.LineStackingStrategyProperty.AddOwner(typeof(AccessText)); ///property. /// /// The LineStackingStrategy property specifies how lines are placed /// public LineStackingStrategy LineStackingStrategy { get { return (LineStackingStrategy)GetValue(LineStackingStrategyProperty); } set { SetValue(LineStackingStrategyProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextAlignmentProperty = Block.TextAlignmentProperty.AddOwner(typeof(AccessText)); ///property. /// /// The TextAlignment property specifies horizontal alignment of the content. /// public TextAlignment TextAlignment { get { return (TextAlignment) GetValue(TextAlignmentProperty); } set { SetValue(TextAlignmentProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextTrimmingProperty = TextBlock.TextTrimmingProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( TextTrimming.None, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextTrimming property specifies the trimming behavior situation /// in case of clipping some textual content caused by overflowing the line's box. /// public TextTrimming TextTrimming { get { return (TextTrimming) GetValue(TextTrimmingProperty); } set { SetValue(TextTrimmingProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextWrappingProperty = TextBlock.TextWrappingProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( TextWrapping.NoWrap, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextWrapping property controls whether or not text wraps /// when it reaches the flow edge of its containing block box. /// public TextWrapping TextWrapping { get { return (TextWrapping) GetValue(TextWrappingProperty); } set { SetValue(TextWrappingProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty BaselineOffsetProperty = TextBlock.BaselineOffsetProperty.AddOwner(typeof(AccessText), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The BaselineOffset property provides an adjustment to baseline offset /// public double BaselineOffset { get { return (double) GetValue(BaselineOffsetProperty); } set { SetValue(BaselineOffsetProperty, value); } } #endregion Public Dynamic Properties //------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods ////// Content measurement. /// /// Constraint size. ///Computed desired size. protected sealed override Size MeasureOverride(Size constraint) { TextBlock.Measure(constraint); return TextBlock.DesiredSize; } ////// Content arrangement. /// /// Size that element should use to arrange itself and its children. protected sealed override Size ArrangeOverride(Size arrangeSize) { TextBlock.Arrange(new Rect(arrangeSize)); return arrangeSize; } #endregion Protected Methods //------------------------------------------------------------------- // // Internal Methods // //-------------------------------------------------------------------- #region Internal Methods internal static bool HasCustomSerialization(object o) { Run accessKey = o as Run; return accessKey != null && HasCustomSerializationStorage.GetValue(accessKey); } #endregion Internal methods //-------------------------------------------------------------------- // // Internal Properties // //------------------------------------------------------------------- #region Internal Properties internal TextBlock TextBlock { get { if (_textBlock == null) CreateTextBlock(); return _textBlock; } } internal static char AccessKeyMarker { get { return _accessKeyMarker; } } #endregion Internal Properties //-------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods private TextContainer TextContainer { get { if (_textContainer == null) CreateTextBlock(); return _textContainer; } } private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((AccessText)d).TextBlock.SetValue(e.Property, e.NewValue); } ////// CreateTextBlock - Creates a text block, adds as visual child, databinds properties and sets up appropriate event listener. /// private void CreateTextBlock() { _textContainer = new TextContainer(this, false /* plainTextOnly */); _textBlock = new TextBlock(); AddVisualChild(_textBlock); _textBlock.IsContentPresenterContainer = true; _textBlock.SetTextContainer(_textContainer); InitializeTextContainerListener(); } ////// Gets the Visual children count of the AccessText control. /// protected override int VisualChildrenCount { get { return 1; } } ////// Gets the Visual child at the specified index. /// protected override Visual GetVisualChild(int index) { if (index != 0) { throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); } return TextBlock; } // Provides custom serialization for this element internal static void SerializeCustom(XmlWriter xmlWriter, object o) { Run inlineScope = o as Run; if (inlineScope != null) { xmlWriter.WriteString(AccessKeyMarker + inlineScope.Text); } } private static Style AccessKeyStyle { get { if (_accessKeyStyle == null) { Style accessKeyStyle = new Style(typeof(Run)); Trigger trigger = new Trigger(); trigger.Property = KeyboardNavigation.ShowKeyboardCuesProperty; trigger.Value = true; trigger.Setters.Add(new Setter(TextDecorationsProperty, System.Windows.TextDecorations.Underline)); accessKeyStyle.Triggers.Add(trigger); accessKeyStyle.Seal(); _accessKeyStyle = accessKeyStyle; } return _accessKeyStyle; } } ////// UpdateAccessKey - Scans forward in the tree looking for the access key marker, replacing it with access key element. We only support one find. /// private void UpdateAccessKey() { TextPointer navigator = new TextPointer(TextContainer.Start); while (!_accessKeyLocated && navigator.CompareTo(TextContainer.End) < 0 ) { TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward); switch (symbolType) { case TextPointerContext.Text: string text = navigator.GetTextInRun(LogicalDirection.Forward); int index = FindAccessKeyMarker(text); if(index != -1 && index < text.Length - 1) { TextPointer keyStart = navigator.GetPositionAtOffset(index + 1); TextPointer keyEnd = keyStart.GetNextInsertionPosition(LogicalDirection.Forward); int accessKeyLength = keyStart.GetOffsetToPosition(keyEnd); _accessKey = new Run(text.Substring(index + 1, accessKeyLength)); _accessKey.Style = AccessKeyStyle; RegisterAccessKey(); HasCustomSerializationStorage.SetValue(_accessKey, true); _accessKeyLocated = true; UninitializeTextContainerListener(); TextContainer.BeginChange(); try { TextPointer underlineStart = new TextPointer(navigator, index); TextRangeEdit.DeleteInlineContent(underlineStart, keyEnd); _accessKey.RepositionWithContent(underlineStart); } finally { TextContainer.EndChange(); InitializeTextContainerListener(); } } break; } navigator.MoveToNextContextPosition(LogicalDirection.Forward); } // Convert double _ to single _ navigator = new TextPointer(TextContainer.Start); string accessKeyMarker = AccessKeyMarker.ToString(); string doubleAccessKeyMarker = accessKeyMarker + accessKeyMarker; while (navigator.CompareTo(TextContainer.End) < 0) { TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward); switch (symbolType) { case TextPointerContext.Text: string text = navigator.GetTextInRun(LogicalDirection.Forward); string nexText = text.Replace(doubleAccessKeyMarker, accessKeyMarker); if (text != nexText) { TextPointer keyStart = new TextPointer(navigator, 0); TextPointer keyEnd = new TextPointer(navigator, text.Length); UninitializeTextContainerListener(); TextContainer.BeginChange(); try { keyEnd.InsertTextInRun(nexText); TextRangeEdit.DeleteInlineContent(keyStart, keyEnd); } finally { TextContainer.EndChange(); InitializeTextContainerListener(); } } break; } navigator.MoveToNextContextPosition(LogicalDirection.Forward); } } // Returns the index of _ marker. // _ can be escaped by double _ private static int FindAccessKeyMarker(string text) { int lenght = text.Length; int startIndex = 0; while (startIndex < lenght) { int index = text.IndexOf(AccessKeyMarker, startIndex); if (index == -1) return -1; // If next char exist and different from _ if (index + 1 < lenght && text[index + 1] != AccessKeyMarker) return index; startIndex = index + 2; } return -1; } internal static string RemoveAccessKeyMarker(string text) { if (!string.IsNullOrEmpty(text)) { int index = FindAccessKeyMarker(text); if (index >=0 && index < text.Length - 1) return text.Remove(index, 1); } return text; } private void RegisterAccessKey() { if (_currentlyRegistered != null) { AccessKeyManager.Unregister(_currentlyRegistered, this); _currentlyRegistered = null; } string key = _accessKey.Text; if (!string.IsNullOrEmpty(key)) { AccessKeyManager.Register(key, this); _currentlyRegistered = key; } } //------------------------------------------------------------------- // Text helpers //------------------------------------------------------------------- private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((AccessText) d).UpdateText((string) e.NewValue); } private void UpdateText(string text) { if (text == null) text = string.Empty; _accessKeyLocated = false; _accessKey = null; TextContainer.BeginChange(); try { TextContainer.DeleteContentInternal((TextPointer)TextContainer.Start, TextContainer.End); Run run = Inline.CreateImplicitRun(this); ((TextPointer)TextContainer.End).InsertTextElement(run); run.Text = text; } finally { TextContainer.EndChange(); } } // ------------------------------------------------------------------ // Setup event handler. // ----------------------------------------------------------------- private void InitializeTextContainerListener() { TextContainer.Changed += new TextContainerChangedEventHandler(OnTextContainerChanged); } // ------------------------------------------------------------------ // Clear event handler. // ------------------------------------------------------------------ private void UninitializeTextContainerListener() { TextContainer.Changed -= new TextContainerChangedEventHandler(OnTextContainerChanged); } // ----------------------------------------------------------------- // Handler for TextContainer.Changed notification. // ------------------------------------------------------------------ private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs args) { // Skip changes that only affect properties. if (args.HasContentAddedOrRemoved) { UpdateAccessKey(); } } #endregion Private methods //------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------- #region Private Fields //--------------------------------------------------------------- // Text container for actual content //---------------------------------------------------------------- private TextContainer _textContainer; //--------------------------------------------------------------- // Visual tree text block //---------------------------------------------------------------- private TextBlock _textBlock; //---------------------------------------------------------------- // Visual tree Run - created internally if _ is found //--------------------------------------------------------------- private Run _accessKey; //---------------------------------------------------------------- // Flag indicating whether the access key element has been located //--------------------------------------------------------------- private bool _accessKeyLocated; //--------------------------------------------------------------- // Defines the charecter to be used in fron of the access key //--------------------------------------------------------------- private const char _accessKeyMarker = '_'; //---------------------------------------------------------------- // Stores the default Style applied on the internal Run //--------------------------------------------------------------- private static Style _accessKeyStyle; //---------------------------------------------------------------- // Flag that indicates if access key is registered with this AccessText //---------------------------------------------------------------- private string _currentlyRegistered; //--------------------------------------------------------------- // Flag that indicates that internal Run should have a custom serialization //---------------------------------------------------------------- private static readonly UncommonFieldHasCustomSerializationStorage = new UncommonField (); #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System.Collections; using System.ComponentModel; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Markup; using System.Diagnostics; using System.Xml; using MS.Internal; namespace System.Windows.Controls { /// /// AccessText Element - Register an accesskey specified after the underscore character in the text. /// [ContentProperty("Text")] public class AccessText : FrameworkElement, IAddChild { //------------------------------------------------------------------- // // IContentHost Members // //------------------------------------------------------------------- #region IAddChild members ////// Called to Add the object as a Child. /// /// /// Object to add as a child /// void IAddChild.AddChild(Object value) { ((IAddChild)TextBlock).AddChild(value); } ////// Called when text appears under the tag in markup. /// /// /// Text to Add to the Object /// void IAddChild.AddText(string text) { ((IAddChild)TextBlock).AddText(text); } #endregion IAddChild members //-------------------------------------------------------------------- // // LogicalTree // //------------------------------------------------------------------- #region LogicalTree ////// Returns enumerator to logical children. /// protected internal override IEnumerator LogicalChildren { get { return new RangeContentEnumerator(TextContainer.Start, TextContainer.End); } } #endregion LogicalTree //-------------------------------------------------------------------- // // Constructors // //-------------------------------------------------------------------- #region Constructors ////// AccessText constructor. /// public AccessText() : base() { } #endregion Constructors //------------------------------------------------------------------- // // Public Properties // //-------------------------------------------------------------------- #region Public Properties ////// Read only access to the key after the first underline character /// public char AccessKey { get { // return (_accessKey != null && _accessKey.Text.Length > 0) ? _accessKey.Text[0] : (char)0; } } #endregion Public Properties //------------------------------------------------------------------- // // Public Dynamic Properties // //------------------------------------------------------------------- #region Public Dynamic Properties ////// DependencyProperty for public static readonly DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof(string), typeof(AccessText), new FrameworkPropertyMetadata( string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnTextChanged))); ///property. /// /// The Text property defines the text to be displayed. /// [DefaultValue("")] public string Text { get { return (string) GetValue(TextProperty); } set { SetValue(TextProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontFamily property specifies the name of font family. /// [Localizability( LocalizationCategory.Font, Modifiability = Modifiability.Unmodifiable )] public FontFamily FontFamily { get { return (FontFamily) GetValue(FontFamilyProperty); } set { SetValue(FontFamilyProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontStyle property requests normal, italic, and oblique faces within a font family. /// public FontStyle FontStyle { get { return (FontStyle) GetValue(FontStyleProperty); } set { SetValue(FontStyleProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontWeight property specifies the weight of the font. /// public FontWeight FontWeight { get { return (FontWeight) GetValue(FontWeightProperty); } set { SetValue(FontWeightProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontStretch property selects a normal, condensed, or extended face from a font family. /// public FontStretch FontStretch { get { return (FontStretch) GetValue(FontStretchProperty); } set { SetValue(FontStretchProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(typeof(AccessText)); ///property. /// /// The FontSize property specifies the size of the font. /// [TypeConverter(typeof(FontSizeConverter))] [Localizability(LocalizationCategory.None)] public double FontSize { get { return (double) GetValue(FontSizeProperty); } set { SetValue(FontSizeProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty ForegroundProperty = TextElement.ForegroundProperty.AddOwner(typeof(AccessText)); ///property. /// /// The Foreground property specifies the foreground brush of an element's text content. /// public Brush Foreground { get { return (Brush) GetValue(ForegroundProperty); } set { SetValue(ForegroundProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty BackgroundProperty = TextElement.BackgroundProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The Background property defines the brush used to fill the content area. /// public Brush Background { get { return (Brush) GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextDecorationsProperty = Inline.TextDecorationsProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( new FreezableDefaultValueFactory(TextDecorationCollection.Empty), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextDecorations property specifies decorations that are added to the text of an element. /// public TextDecorationCollection TextDecorations { get { return (TextDecorationCollection) GetValue(TextDecorationsProperty); } set { SetValue(TextDecorationsProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextEffectsProperty = TextElement.TextEffectsProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( new FreezableDefaultValueFactory(TextEffectCollection.Empty), FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextEffects property specifies effects that are added to the text of an element. /// public TextEffectCollection TextEffects { get { return (TextEffectCollection) GetValue(TextEffectsProperty); } set { SetValue(TextEffectsProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty LineHeightProperty = Block.LineHeightProperty.AddOwner(typeof(AccessText)); ///property. /// /// The LineHeight property specifies the height of each generated line box. /// [TypeConverter(typeof(LengthConverter))] public double LineHeight { get { return (double) GetValue(LineHeightProperty); } set { SetValue(LineHeightProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty LineStackingStrategyProperty = Block.LineStackingStrategyProperty.AddOwner(typeof(AccessText)); ///property. /// /// The LineStackingStrategy property specifies how lines are placed /// public LineStackingStrategy LineStackingStrategy { get { return (LineStackingStrategy)GetValue(LineStackingStrategyProperty); } set { SetValue(LineStackingStrategyProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextAlignmentProperty = Block.TextAlignmentProperty.AddOwner(typeof(AccessText)); ///property. /// /// The TextAlignment property specifies horizontal alignment of the content. /// public TextAlignment TextAlignment { get { return (TextAlignment) GetValue(TextAlignmentProperty); } set { SetValue(TextAlignmentProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextTrimmingProperty = TextBlock.TextTrimmingProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( TextTrimming.None, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextTrimming property specifies the trimming behavior situation /// in case of clipping some textual content caused by overflowing the line's box. /// public TextTrimming TextTrimming { get { return (TextTrimming) GetValue(TextTrimmingProperty); } set { SetValue(TextTrimmingProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TextWrappingProperty = TextBlock.TextWrappingProperty.AddOwner( typeof(AccessText), new FrameworkPropertyMetadata( TextWrapping.NoWrap, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The TextWrapping property controls whether or not text wraps /// when it reaches the flow edge of its containing block box. /// public TextWrapping TextWrapping { get { return (TextWrapping) GetValue(TextWrappingProperty); } set { SetValue(TextWrappingProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty BaselineOffsetProperty = TextBlock.BaselineOffsetProperty.AddOwner(typeof(AccessText), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPropertyChanged))); ///property. /// /// The BaselineOffset property provides an adjustment to baseline offset /// public double BaselineOffset { get { return (double) GetValue(BaselineOffsetProperty); } set { SetValue(BaselineOffsetProperty, value); } } #endregion Public Dynamic Properties //------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods ////// Content measurement. /// /// Constraint size. ///Computed desired size. protected sealed override Size MeasureOverride(Size constraint) { TextBlock.Measure(constraint); return TextBlock.DesiredSize; } ////// Content arrangement. /// /// Size that element should use to arrange itself and its children. protected sealed override Size ArrangeOverride(Size arrangeSize) { TextBlock.Arrange(new Rect(arrangeSize)); return arrangeSize; } #endregion Protected Methods //------------------------------------------------------------------- // // Internal Methods // //-------------------------------------------------------------------- #region Internal Methods internal static bool HasCustomSerialization(object o) { Run accessKey = o as Run; return accessKey != null && HasCustomSerializationStorage.GetValue(accessKey); } #endregion Internal methods //-------------------------------------------------------------------- // // Internal Properties // //------------------------------------------------------------------- #region Internal Properties internal TextBlock TextBlock { get { if (_textBlock == null) CreateTextBlock(); return _textBlock; } } internal static char AccessKeyMarker { get { return _accessKeyMarker; } } #endregion Internal Properties //-------------------------------------------------------------------- // // Private Methods // //------------------------------------------------------------------- #region Private Methods private TextContainer TextContainer { get { if (_textContainer == null) CreateTextBlock(); return _textContainer; } } private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((AccessText)d).TextBlock.SetValue(e.Property, e.NewValue); } ////// CreateTextBlock - Creates a text block, adds as visual child, databinds properties and sets up appropriate event listener. /// private void CreateTextBlock() { _textContainer = new TextContainer(this, false /* plainTextOnly */); _textBlock = new TextBlock(); AddVisualChild(_textBlock); _textBlock.IsContentPresenterContainer = true; _textBlock.SetTextContainer(_textContainer); InitializeTextContainerListener(); } ////// Gets the Visual children count of the AccessText control. /// protected override int VisualChildrenCount { get { return 1; } } ////// Gets the Visual child at the specified index. /// protected override Visual GetVisualChild(int index) { if (index != 0) { throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); } return TextBlock; } // Provides custom serialization for this element internal static void SerializeCustom(XmlWriter xmlWriter, object o) { Run inlineScope = o as Run; if (inlineScope != null) { xmlWriter.WriteString(AccessKeyMarker + inlineScope.Text); } } private static Style AccessKeyStyle { get { if (_accessKeyStyle == null) { Style accessKeyStyle = new Style(typeof(Run)); Trigger trigger = new Trigger(); trigger.Property = KeyboardNavigation.ShowKeyboardCuesProperty; trigger.Value = true; trigger.Setters.Add(new Setter(TextDecorationsProperty, System.Windows.TextDecorations.Underline)); accessKeyStyle.Triggers.Add(trigger); accessKeyStyle.Seal(); _accessKeyStyle = accessKeyStyle; } return _accessKeyStyle; } } ////// UpdateAccessKey - Scans forward in the tree looking for the access key marker, replacing it with access key element. We only support one find. /// private void UpdateAccessKey() { TextPointer navigator = new TextPointer(TextContainer.Start); while (!_accessKeyLocated && navigator.CompareTo(TextContainer.End) < 0 ) { TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward); switch (symbolType) { case TextPointerContext.Text: string text = navigator.GetTextInRun(LogicalDirection.Forward); int index = FindAccessKeyMarker(text); if(index != -1 && index < text.Length - 1) { TextPointer keyStart = navigator.GetPositionAtOffset(index + 1); TextPointer keyEnd = keyStart.GetNextInsertionPosition(LogicalDirection.Forward); int accessKeyLength = keyStart.GetOffsetToPosition(keyEnd); _accessKey = new Run(text.Substring(index + 1, accessKeyLength)); _accessKey.Style = AccessKeyStyle; RegisterAccessKey(); HasCustomSerializationStorage.SetValue(_accessKey, true); _accessKeyLocated = true; UninitializeTextContainerListener(); TextContainer.BeginChange(); try { TextPointer underlineStart = new TextPointer(navigator, index); TextRangeEdit.DeleteInlineContent(underlineStart, keyEnd); _accessKey.RepositionWithContent(underlineStart); } finally { TextContainer.EndChange(); InitializeTextContainerListener(); } } break; } navigator.MoveToNextContextPosition(LogicalDirection.Forward); } // Convert double _ to single _ navigator = new TextPointer(TextContainer.Start); string accessKeyMarker = AccessKeyMarker.ToString(); string doubleAccessKeyMarker = accessKeyMarker + accessKeyMarker; while (navigator.CompareTo(TextContainer.End) < 0) { TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward); switch (symbolType) { case TextPointerContext.Text: string text = navigator.GetTextInRun(LogicalDirection.Forward); string nexText = text.Replace(doubleAccessKeyMarker, accessKeyMarker); if (text != nexText) { TextPointer keyStart = new TextPointer(navigator, 0); TextPointer keyEnd = new TextPointer(navigator, text.Length); UninitializeTextContainerListener(); TextContainer.BeginChange(); try { keyEnd.InsertTextInRun(nexText); TextRangeEdit.DeleteInlineContent(keyStart, keyEnd); } finally { TextContainer.EndChange(); InitializeTextContainerListener(); } } break; } navigator.MoveToNextContextPosition(LogicalDirection.Forward); } } // Returns the index of _ marker. // _ can be escaped by double _ private static int FindAccessKeyMarker(string text) { int lenght = text.Length; int startIndex = 0; while (startIndex < lenght) { int index = text.IndexOf(AccessKeyMarker, startIndex); if (index == -1) return -1; // If next char exist and different from _ if (index + 1 < lenght && text[index + 1] != AccessKeyMarker) return index; startIndex = index + 2; } return -1; } internal static string RemoveAccessKeyMarker(string text) { if (!string.IsNullOrEmpty(text)) { int index = FindAccessKeyMarker(text); if (index >=0 && index < text.Length - 1) return text.Remove(index, 1); } return text; } private void RegisterAccessKey() { if (_currentlyRegistered != null) { AccessKeyManager.Unregister(_currentlyRegistered, this); _currentlyRegistered = null; } string key = _accessKey.Text; if (!string.IsNullOrEmpty(key)) { AccessKeyManager.Register(key, this); _currentlyRegistered = key; } } //------------------------------------------------------------------- // Text helpers //------------------------------------------------------------------- private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((AccessText) d).UpdateText((string) e.NewValue); } private void UpdateText(string text) { if (text == null) text = string.Empty; _accessKeyLocated = false; _accessKey = null; TextContainer.BeginChange(); try { TextContainer.DeleteContentInternal((TextPointer)TextContainer.Start, TextContainer.End); Run run = Inline.CreateImplicitRun(this); ((TextPointer)TextContainer.End).InsertTextElement(run); run.Text = text; } finally { TextContainer.EndChange(); } } // ------------------------------------------------------------------ // Setup event handler. // ----------------------------------------------------------------- private void InitializeTextContainerListener() { TextContainer.Changed += new TextContainerChangedEventHandler(OnTextContainerChanged); } // ------------------------------------------------------------------ // Clear event handler. // ------------------------------------------------------------------ private void UninitializeTextContainerListener() { TextContainer.Changed -= new TextContainerChangedEventHandler(OnTextContainerChanged); } // ----------------------------------------------------------------- // Handler for TextContainer.Changed notification. // ------------------------------------------------------------------ private void OnTextContainerChanged(object sender, TextContainerChangedEventArgs args) { // Skip changes that only affect properties. if (args.HasContentAddedOrRemoved) { UpdateAccessKey(); } } #endregion Private methods //------------------------------------------------------------------- // // Private Fields // //------------------------------------------------------------------- #region Private Fields //--------------------------------------------------------------- // Text container for actual content //---------------------------------------------------------------- private TextContainer _textContainer; //--------------------------------------------------------------- // Visual tree text block //---------------------------------------------------------------- private TextBlock _textBlock; //---------------------------------------------------------------- // Visual tree Run - created internally if _ is found //--------------------------------------------------------------- private Run _accessKey; //---------------------------------------------------------------- // Flag indicating whether the access key element has been located //--------------------------------------------------------------- private bool _accessKeyLocated; //--------------------------------------------------------------- // Defines the charecter to be used in fron of the access key //--------------------------------------------------------------- private const char _accessKeyMarker = '_'; //---------------------------------------------------------------- // Stores the default Style applied on the internal Run //--------------------------------------------------------------- private static Style _accessKeyStyle; //---------------------------------------------------------------- // Flag that indicates if access key is registered with this AccessText //---------------------------------------------------------------- private string _currentlyRegistered; //--------------------------------------------------------------- // Flag that indicates that internal Run should have a custom serialization //---------------------------------------------------------------- private static readonly UncommonFieldHasCustomSerializationStorage = new UncommonField (); #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
- OrderedDictionaryStateHelper.cs
- LoginName.cs
- ApplicationFileParser.cs
- EdmProperty.cs
- BaseTreeIterator.cs
- StructuralCache.cs
- ManagementOperationWatcher.cs
- EditorPartCollection.cs
- HttpHandlersInstallComponent.cs
- WebBrowserHelper.cs
- TemplateGroupCollection.cs
- XmlBoundElement.cs
- Cursors.cs
- DataRowChangeEvent.cs
- GroupItemAutomationPeer.cs
- RegistryExceptionHelper.cs
- ISAPIRuntime.cs
- Component.cs
- AppManager.cs
- ToggleButtonAutomationPeer.cs
- ImportException.cs
- SqlReorderer.cs
- TraceSource.cs
- DataBoundControl.cs
- MemoryPressure.cs
- CursorConverter.cs
- MSHTMLHostUtil.cs
- SmiRecordBuffer.cs
- Keywords.cs
- XmlWriterTraceListener.cs
- FormattedText.cs
- PieceNameHelper.cs
- ToggleButton.cs
- RectConverter.cs
- Win32.cs
- CorrelationTokenInvalidatedHandler.cs
- DataKeyCollection.cs
- MediaScriptCommandRoutedEventArgs.cs
- CursorConverter.cs
- dtdvalidator.cs
- LateBoundBitmapDecoder.cs
- Model3D.cs
- JsonWriter.cs
- ScopelessEnumAttribute.cs
- CommandDevice.cs
- ApplicationGesture.cs
- WebServiceReceive.cs
- FactoryGenerator.cs
- FileNotFoundException.cs
- RestClientProxyHandler.cs
- UInt16.cs
- MultiBindingExpression.cs
- ProxySimple.cs
- WorkflowInstance.cs
- Themes.cs
- Keyboard.cs
- DoubleSumAggregationOperator.cs
- ValueCollectionParameterReader.cs
- BitmapScalingModeValidation.cs
- WriteTimeStream.cs
- SetIndexBinder.cs
- MessageEventSubscriptionService.cs
- Brushes.cs
- PasswordRecovery.cs
- HttpVersion.cs
- ObjectDataSourceEventArgs.cs
- NativeMethods.cs
- BamlRecords.cs
- SqlInternalConnectionTds.cs
- XmlSchemaDatatype.cs
- EffectiveValueEntry.cs
- BooleanExpr.cs
- ImageButton.cs
- ArgumentNullException.cs
- ToolStripContentPanelRenderEventArgs.cs
- ResourceManagerWrapper.cs
- RelatedImageListAttribute.cs
- UnrecognizedAssertionsBindingElement.cs
- ExtensionWindowResizeGrip.cs
- SafeNativeMethods.cs
- ConsumerConnectionPointCollection.cs
- WebPartEditorCancelVerb.cs
- DefaultPropertyAttribute.cs
- SafeFileHandle.cs
- HandlerWithFactory.cs
- Int32EqualityComparer.cs
- OracleBinary.cs
- NameScope.cs
- WebException.cs
- OracleLob.cs
- PerformanceCounterPermissionEntryCollection.cs
- CatalogZoneBase.cs
- UserControlParser.cs
- AuthenticationModuleElementCollection.cs
- EventManager.cs
- ManagementDateTime.cs
- OracleFactory.cs
- URLAttribute.cs
- TransactionManager.cs
- DrawingContextWalker.cs