Hyperlink.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Documents / Hyperlink.cs / 3 / Hyperlink.cs

                            //---------------------------------------------------------------------------- 
// File: Hyperlink.cs
//
// Description:
// Implementation of Underline element. 
//
// Copyright (C) 2004 by Microsoft Corporation.  All rights reserved. 
// 
//---------------------------------------------------------------------------
using System; 
using System.ComponentModel;
using System.Windows;                // DependencyID etc.
using System.Windows.Automation.Peers;
using System.Windows.Controls;       // 
using System.Windows.Input;
using System.Windows.Navigation; 
using System.Threading; 
using System.Windows.Markup; // IUriContext
using System.Security; 
using System.Security.Permissions;
using MS.Internal;
using MS.Internal.AppModel;
using MS.Internal.Utility; 
using MS.Internal.PresentationFramework;                   // SecurityHelper
 
namespace System.Windows.Documents 
{
    ///  
    /// Implements a Hyperlink element
    /// 
    [UIPermissionAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
    [TextElementEditingBehaviorAttribute(IsMergeable = false, IsTypographicOnly = false)] 
    public class Hyperlink : Span, ICommandSource, IUriContext
    { 
        //------------------------------------------------------------------- 
        //
        // Constructors 
        //
        //---------------------------------------------------------------------

        #region Constructors 

        // 
        // Static Ctor to create default style sheet 
        //
        static Hyperlink() 
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Hyperlink), new FrameworkPropertyMetadata(typeof(Hyperlink)));
            _dType = DependencyObjectType.FromSystemTypeInternal(typeof(Hyperlink));
            FocusableProperty.OverrideMetadata(typeof(Hyperlink), new FrameworkPropertyMetadata(true)); 
            EventManager.RegisterClassHandler(typeof(Hyperlink), Mouse.QueryCursorEvent, new QueryCursorEventHandler(OnQueryCursor));
        } 
 

        ///  
        /// Initializes a new instance of Hyperlink element.
        /// 
        /// 
        /// To become fully functional this element requires at least one other Inline element 
        /// as its child, typically Run with some text.
        ///  
        public Hyperlink() : base() 
        {
        } 

        /// 
        /// Initializes a new instance of Hyperlink element and adds a given Inline element as its first child.
        ///  
        /// 
        /// Inline element added as an initial child to this Hyperlink element 
        ///  
        public Hyperlink(Inline childInline) : base(childInline)
        { 
        }

        /// 
        /// Creates a new Span instance. 
        /// 
        ///  
        /// Optional child Inline for the new Span.  May be null. 
        /// 
        ///  
        /// Optional position at which to insert the new Span.  May be null.
        /// 
        public Hyperlink(Inline childInline, TextPointer insertionPosition) : base(childInline, insertionPosition)
        { 
        }
 
        ///  
        /// Creates a new Hyperlink instance covering existing content.
        ///  
        /// 
        /// Start position of the new Hyperlink.
        /// 
        ///  
        /// End position of the new Hyperlink.
        ///  
        ///  
        /// start and end must both be parented by the same Paragraph, otherwise
        /// the method will raise an ArgumentException. 
        /// 
        public Hyperlink(TextPointer start, TextPointer end) : base(start, end)
        {
            // After inserting this Hyperlink, we need to extract any child Hyperlinks. 

            TextPointer navigator = this.ContentStart.CreatePointer(); 
            TextPointer stop = this.ContentEnd; 

            while (navigator.CompareTo(stop) < 0) 
            {
                Hyperlink hyperlink = navigator.GetAdjacentElement(LogicalDirection.Forward) as Hyperlink;

                if (hyperlink != null) 
                {
                    hyperlink.Reposition(null, null); 
                } 
                else
                { 
                    navigator.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }
        } 

        #endregion Constructors 
 
        //--------------------------------------------------------------------
        // 
        // Public Methods
        //
        //---------------------------------------------------------------------
 
        #region Public Methods
 
        ///  
        /// This method does exactly the same operation as clicking the Hyperlink with the mouse.
        ///  
        public void DoClick()
        {
            OnClick();
        } 

 
        #region ICommandSource 

        ///  
        ///     The DependencyProperty for RoutedCommand
        /// 
        public static readonly DependencyProperty CommandProperty =
                DependencyProperty.Register( 
                        "Command",
                        typeof(ICommand), 
                        typeof(Hyperlink), 
                        new FrameworkPropertyMetadata((ICommand)null,
                            new PropertyChangedCallback(OnCommandChanged))); 

        /// 
        /// Get or set the Command property
        ///  
        [Bindable(true), Category("Action")]
        [Localizability(LocalizationCategory.NeverLocalize)] 
        public ICommand Command 
        {
            get 
            {
                return (ICommand)GetValue(CommandProperty);
            }
            set 
            {
                SetValue(CommandProperty, value); 
            } 
        }
 
        private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Hyperlink h = (Hyperlink)d;
            h.OnCommandChanged((ICommand)e.OldValue, (ICommand)e.NewValue); 
        }
 
        private void OnCommandChanged(ICommand oldCommand, ICommand newCommand) 
        {
            if (oldCommand != null) 
            {
                UnhookCommand(oldCommand);
            }
            if (newCommand != null) 
            {
                HookCommand(newCommand); 
            } 
        }
 
        private void UnhookCommand(ICommand command)
        {
            EventHandler handler = CanExecuteChangedHandler.GetValue(this);
            if (handler != null) 
            {
                command.CanExecuteChanged -= handler; 
                CanExecuteChangedHandler.ClearValue(this); 
            }
            UpdateCanExecute(); 
        }

        private void HookCommand(ICommand command)
        { 
            EventHandler handler = new EventHandler(OnCanExecuteChanged);
            CanExecuteChangedHandler.SetValue(this, handler); 
            command.CanExecuteChanged += handler; 
            UpdateCanExecute();
        } 

        private void OnCanExecuteChanged(object sender, EventArgs e)
        {
            UpdateCanExecute(); 
        }
 
        private void UpdateCanExecute() 
        {
            if (Command != null) 
            {
                CanExecute = MS.Internal.Commands.CommandHelpers.CanExecuteCommandSource(this);
            }
            else 
            {
                CanExecute = true; 
            } 
        }
 
        private bool CanExecute
        {
            get { return _canExecute; }
            set 
            {
                if (_canExecute != value) 
                { 
                    _canExecute = value;
                    CoerceValue(IsEnabledProperty); 
                }
            }
        }
 
        // Returns true when this Hyperlink is hosted by an enabled
        // TextEditor (eg, within a RichTextBox). 
        private bool IsEditable 
        {
            get 
            {
                return (this.TextContainer.TextSelection != null &&
                        !this.TextContainer.TextSelection.TextEditor.IsReadOnly);
            } 
        }
 
        ///  
        ///     Fetches the value of the IsEnabled property
        ///  
        /// 
        ///     The reason this property is overridden is so that Hyperlink
        ///     can infuse the value for CanExecute into it.
        ///  
        protected override bool IsEnabledCore
        { 
            get 
            {
                return base.IsEnabledCore && CanExecute; 
            }
        }

        ///  
        /// The DependencyProperty for the CommandParameter
        ///  
        public static readonly DependencyProperty CommandParameterProperty = 
                DependencyProperty.Register(
                        "CommandParameter", 
                        typeof(object),
                        typeof(Hyperlink),
                        new FrameworkPropertyMetadata((object)null));
 
        /// 
        /// Reflects the parameter to pass to the CommandProperty upon execution. 
        ///  
        [Bindable(true), Category("Action")]
        [Localizability(LocalizationCategory.NeverLocalize)] 
        public object CommandParameter
        {
            get
            { 
                return GetValue(CommandParameterProperty);
            } 
            set 
            {
                SetValue(CommandParameterProperty, value); 
            }
        }

        ///  
        ///     The DependencyProperty for Target property
        ///     Flags:              None 
        ///     Default Value:      null 
        /// 
        public static readonly DependencyProperty CommandTargetProperty = 
                DependencyProperty.Register(
                        "CommandTarget",
                        typeof(IInputElement),
                        typeof(Hyperlink), 
                        new FrameworkPropertyMetadata((IInputElement)null));
 
        ///  
        ///     The target element on which to fire the command.
        ///  
        [Bindable(true), Category("Action")]
        public IInputElement CommandTarget
        {
            get 
            {
                return (IInputElement)GetValue(CommandTargetProperty); 
            } 
            set
            { 
                SetValue(CommandTargetProperty, value);
            }
        }
 
        #endregion
 
        #endregion Public Methods 

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

        #region Public Properties 
 
        /// 
        /// Contains the target URI to navigate when hyperlink is clicked 
        /// 
        [CommonDependencyProperty]
        public static readonly DependencyProperty NavigateUriProperty
            = DependencyProperty.Register("NavigateUri", typeof(Uri), typeof(Hyperlink), 
                                          new FrameworkPropertyMetadata((Uri)null));
 
        ///  
        /// Provide public access to NavigateUriProperty property. Content the URI to navigate.
        ///  
        [Bindable(true), CustomCategory("Navigation")]
        [Localizability(LocalizationCategory.Hyperlink)]
        public Uri NavigateUri
        { 
            get
            { 
                return GetValue(NavigateUriProperty) as Uri; 

            } 
            set
            {
                SetValue(NavigateUriProperty, value);
            } 
        }
 
        ///  
        /// Contains the target window to navigate when hyperlink is clicked
        ///  
        public static readonly DependencyProperty TargetNameProperty
            = DependencyProperty.Register("TargetName", typeof(String), typeof(Hyperlink),
                                          new FrameworkPropertyMetadata(string.Empty));
 
        /// 
        /// Provide public access to TargetNameProperty property.  The target window to navigate. 
        ///  
        [Bindable(true), CustomCategory("Navigation")]
        [Localizability( 
            LocalizationCategory.None,
            Modifiability = Modifiability.Unmodifiable)
        ]
        public string TargetName 
        {
            get 
            { 
                return GetValue(TargetNameProperty) as string;
            } 
            set
            {
                SetValue(TargetNameProperty, value);
            } 
        }
 
        #endregion Public Properties 

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

        #region Public Events 
 
        // **
 



        ///  
        /// Navigate Event
        ///  
        public static readonly RoutedEvent RequestNavigateEvent = EventManager.RegisterRoutedEvent( 
                                                    "RequestNavigate",
                                                    RoutingStrategy.Bubble, 
                                                    typeof(RequestNavigateEventHandler),
                                                    typeof(Hyperlink));

        ///  
        /// Add / Remove RequestNavigateEvent handler
        ///  
        public event RequestNavigateEventHandler RequestNavigate 
        {
            add 
            {
                AddHandler(RequestNavigateEvent, value);
            }
            remove 
            {
                RemoveHandler(RequestNavigateEvent, value); 
            } 
        }
 
        /// 
        /// Event correspond to left mouse button click
        /// 
        public static readonly RoutedEvent ClickEvent = System.Windows.Controls.Primitives.ButtonBase.ClickEvent.AddOwner(typeof(Hyperlink)); 

        ///  
        /// Add / Remove ClickEvent handler 
        /// 
        [Category("Behavior")] 
        public event RoutedEventHandler Click { add { AddHandler(ClickEvent, value); } remove { RemoveHandler(ClickEvent, value); } }

        /// 
        /// StatusBar event 
        /// 
        internal static readonly RoutedEvent RequestSetStatusBarEvent = EventManager.RegisterRoutedEvent( 
                                                    "RequestSetStatusBar", 
                                                    RoutingStrategy.Bubble,
                                                    typeof(RoutedEventHandler), 
                                                    typeof(Hyperlink));

        #endregion Public Events
 
        //-------------------------------------------------------------------
        // 
        // Protected Methods 
        //
        //--------------------------------------------------------------------- 

        #region Protected Methods

        ///  
        /// This is the method that responds to the KeyDown event.
        ///  
        ///  
        ///
        ///     Critical - asserts UserInitatedNavigationPermisison. 
        ///
        ///     TreatAsSafe - assert is used to enable "safe" navigation only.
        ///                   we consider this safe as we only assert if this is a userInitiated action.
        ///                   The UserInitiated bit is set inside of the InputManager - and tracked via critical. 
        ///
        ///     Note that we LinkDemand and InheritanceDemand for calling OnKeyDown. 
        ///     To defend against someone caching the trusted event args - and playing it back to us. 
        ///
        [SecurityCritical, SecurityTreatAsSafe] 
        [UIPermissionAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
        //we get a compiler warning that a similar LinkDemand should exist on the base class (ContentElement)
        //but we don't want or need that.  The base class doesn't cause navigation to happen so it's safe to
        //call programatically. 
#pragma warning disable 0688
        [UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)] 
        protected override void OnKeyDown(KeyEventArgs e) 
        {
            if (e.RoutedEvent == Keyboard.KeyDownEvent && e.Key == Key.Enter) 
            {
                if (e.UserInitiated)
                {
                    CodeAccessPermission perm = SecurityHelper.CreateUserInitiatedNavigationPermission(); 
                    perm.Assert();
                } 
 
                try
                { 
                    e.Handled = true;
                    OnClick();
                }
                finally 
                {
                    if (e.UserInitiated) 
                    { 
                        CodeAccessPermission.RevertAssert();
                    } 
                }
            }
            else
            { 
                base.OnKeyDown(e);
            } 
        } 
#pragma warning restore 0688
 
        /// 
        /// This is the method that responds to the MouseButtonEvent event.
        /// 
        /// Event arguments 
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        { 
            base.OnMouseLeftButtonDown(e); 

            if (IsEnabled && (!IsEditable || ((Keyboard.Modifiers & ModifierKeys.Control) != 0))) 
            {
                // Hyperlink should take focus when left mouse button is clicked on it
                // This is consistent with all ButtonBase controls and current Win32 behavior
                Focus(); 

                // It is possible that the mouse state could have changed during all of 
                // the call-outs that have happened so far. 
                if (e.ButtonState == MouseButtonState.Pressed)
                { 
                    // Capture the mouse, and make sure we got it.
                    // WARNING: callout
                    CaptureMouse();
                    if (IsMouseCaptured) 
                    {
                        // Though we have already checked this state, our call to CaptureMouse 
                        // could also end up changing the state, so we check it again. 

                        // 
                        //

                        if (e.ButtonState == MouseButtonState.Pressed)
                        { 
                            _isPressed = true;
                        } 
                        else 
                        {
 
                            // Release capture since we decided not to press the button.
                            ReleaseMouseCapture();
                        }
                    } 
                }
 
                e.Handled = true; 
            }
        } 


        /// 
        /// This is the method that responds to the MouseButtonEvent event. 
        /// 
        /// Event arguments 
        /// 
        ///     Critical - asserts UserInitatedNavigationPermisison.
        /// 
        ///     TreatAsSafe - assert is used to enable "safe" navigation only.
        ///                   we consider this safe as we only assert if this is a userInitiated action.
        ///                   The UserInitiated bit is set inside of the InputManager - and tracked via critical.
        /// 
        ///     Note that we LinkDemand and InheritanceDemand for calling OnMouseLeftButtonUp.
        ///     To defend against someone caching the trusted event args - and playing it back to us. 
        /// 
        [SecurityCritical, SecurityTreatAsSafe ]
        [UIPermissionAttribute(SecurityAction.InheritanceDemand , Unrestricted=true)] 
        //we get a compiler warning that a similar LinkDemand should exist on the base class (ContentElement)
        //but we don't want or need that.  The base class doesn't cause navigation to happen so it's safe to
        //call programatically.
#pragma warning disable 0688 
        [UIPermissionAttribute(SecurityAction.LinkDemand, Unrestricted = true)]
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
        { 
            base.OnMouseLeftButtonUp(e);
 
            if (IsMouseCaptured)
            {
                ReleaseMouseCapture();
            } 

            // 
            // 

 
            if (_isPressed)
            {
                _isPressed = false;
 
                // Make sure we're mousing up over the hyperlink
                if (IsMouseOver) 
                { 
                    bool assertCodeAccessPermission = e.UserInitiated &&
                                                    (e.RoutedEvent == UIElement.MouseLeftButtonUpEvent) && 
                                                    (e.ChangedButton == MouseButton.Left);

                    if (assertCodeAccessPermission)
                    { 
                        CodeAccessPermission perm = SecurityHelper.CreateUserInitiatedNavigationPermission();
                        perm.Assert(); 
                    } 

                    try 
                    {
                        OnClick();
                    }
                    finally 
                    {
                        if (assertCodeAccessPermission) 
                        { 
                            CodeAccessPermission.RevertAssert();
                        } 
                    }
                }
            }
 
            e.Handled = true;
        } 
#pragma warning restore 0688 

        ///  
        /// Fire the event to change the status bar.
        /// 
        protected override void OnMouseEnter(MouseEventArgs e)
        { 
            Uri uri = NavigateUri;
            if (uri != null) 
            { 
                RequestSetStatusBarEventArgs args = new RequestSetStatusBarEventArgs(BindUriHelper.UriToString(uri));
                RaiseEvent(args); 
            }
        }

        ///  
        /// Set the status bar text back to empty
        ///  
        protected override void OnMouseLeave(MouseEventArgs e) 
        {
            RequestSetStatusBarEventArgs args = new RequestSetStatusBarEventArgs(String.Empty); 
            RaiseEvent(args);
        }

        ///  
        /// Navigate to URI specified in NavigateUri property and mark the hyperlink as visited
        ///  
        ///Some forms of navigation are not allowed in the internet zone. 
        ///         As such there are cases where this API will demand for fulltrust
        /// 
        ///
        ///     Demands unrestricted UI permssion.
        ///     Asserted in the InputManager when the command is userinitiated.
        /// 
        protected virtual void OnClick()
        { 
            if (AutomationPeer.ListenerExists(AutomationEvents.InvokePatternOnInvoked)) 
            {
                AutomationPeer peer = ContentElementAutomationPeer.CreatePeerForElement(this); 
                if (peer != null)
                    peer.RaiseAutomationEvent(AutomationEvents.InvokePatternOnInvoked);
            }
 
            Uri uri = NavigateUri;
 
            if ((uri != null)) 
            {
                // 
                RequestNavigateEventArgs navigateArgs = new RequestNavigateEventArgs(uri, TargetName);
                navigateArgs.Source=this;
                RaiseEvent(navigateArgs);
                if (navigateArgs.Handled) 
                {
                    // The browser's status bar should be cleared. Otherwise it will still show the 
                    // hyperlink address after navigation has completed. 
                    RequestSetStatusBarEventArgs args = new RequestSetStatusBarEventArgs(String.Empty);
                    RaiseEvent(args); 
                }
            }
            RaiseEvent(new RoutedEventArgs(Hyperlink.ClickEvent, this));
 
            MS.Internal.Commands.CommandHelpers.ExecuteCommandSource(this);
        } 
 
        //
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization
        //
        internal override int EffectiveValuesInitialSize 
        {
            get { return 19; } 
        } 

        ///  
        /// Creates AutomationPeer ()
        /// 
        protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
        { 
            return new System.Windows.Automation.Peers.HyperlinkAutomationPeer(this);
        } 
 
        #endregion Protected Methods
 
        #region IUriContext implementation

        /// 
        /// IUriContext interface is implemented by Hyperlink element so that it 
        /// can hold on to the base URI used by parser.
        /// The base URI is needed to resolve NavigateUri property 
        ///  
        /// Base Uri
        Uri IUriContext.BaseUri 
        {
            get
            {
                return  BaseUri; 
            }
            set 
            { 
                BaseUri = value;
            } 
        }

        /// 
        ///    Implementation for BaseUri 
        /// 
        protected virtual Uri BaseUri 
        { 
            get
            { 
                return (Uri)GetValue(BaseUriHelper.BaseUriProperty);
            }
            set
            { 
                SetValue(BaseUriHelper.BaseUriProperty, value);
            } 
        } 

        #endregion IUriContext implementation 


        //-------------------------------------------------------------------
        // 
        // Internal Properties
        // 
        //---------------------------------------------------------------------- 

        #region Internal Properties 

        /// 
        /// The content spanned by this Hyperlink represented as plain text.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        internal string Text 
        { 
            get
            { 
                return TextRangeBase.GetTextInternal(this.ContentStart, this.ContentEnd);
            }
        }
 
        #endregion Internal Properties
 
        //------------------------------------------------------------------- 
        //
        // Private Methods 
        //
        //----------------------------------------------------------------------

        #region Private Methods 

        // QueryCursorEvent callback. 
        // If this Hyperlink is editable, use the editor cursor unless 
        // the control key is down.
        private static void OnQueryCursor(object sender, QueryCursorEventArgs e) 
        {
            Hyperlink link = (Hyperlink)sender;

            if (link.IsEnabled && link.IsEditable) 
            {
                if ((Keyboard.Modifiers & ModifierKeys.Control) == 0) 
                { 
                    e.Cursor = link.TextContainer.TextSelection.TextEditor._cursor;
                    e.Handled = true; 
                }
            }
        }
 
        #endregion Private Methods
 
        //-------------------------------------------------------------------- 
        //
        // Private Fields 
        //
        //---------------------------------------------------------------------

        #region Private Fields 

        bool _isPressed; 
        private bool _canExecute = true; 

        private static readonly UncommonField CanExecuteChangedHandler = new UncommonField(); 

        #endregion Private Fields

        #region DTypeThemeStyleKey 

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

        private static DependencyObjectType _dType; 

        #endregion DTypeThemeStyleKey 
    } 
}

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

Link Menu

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