Hyperlink Control
One of the things I needed to build for my Search application is hyperlinks. So that people can navigate to actual search results if they wanted to. Remember couple of places in my application, I display where the image came from but it is just text and user can not do anything with it. I would like it to be hyperlink and click on it and navigate to the destination. So what is the basic functionality I needed from my hyperlink.
- It can take the Uri where link is supposed to point to
- It can take text that it displays on the page
- It can support hyperlink targeting i.e It can navigate either iframe on a current page, or current browser window or open new browser window.
- It should support click tracking i.e. changing colors when user has visited this site once. I did not get time to write this one but it should be possible to do using isolated storage.
- It should support right click menu but can not do it till Silverlight has input support for right mouse click.
Code for Hyperlink.xaml
<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns="http://schemas.microsoft.com/winfx/2006/xaml" Width="40" Height="20" Cursor="Hand" > <TextBlock x:Name="txtlink" Width="40" Height="20" Canvas.Left="0" Canvas.Top="0" FontFamily="Arial Unicode MS" FontSize="14" FontWeight="Normal" Foreground="#FF3281D4" Text="Test" TextWrapping="Wrap" /> </Canvas>
Code for Hyperlink.xaml.cs
using System; using System.IO; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Browser; namespace HyperlinkApp { public class Hyperlink : Control { private Canvas rootCanvas; private TextBlock txtlink; private Uri _navigateUri; private string _targetname; private bool click; public Hyperlink() { Stream s = this.GetType().Assembly.GetManifestResourceStream("HyperlinkApp.Hyperlink.xaml"); rootCanvas = (Canvas)this.InitializeFromXaml(new StreamReader(s).ReadToEnd()); txtlink = (TextBlock) rootCanvas.FindName("txtlink"); this.Loaded += new EventHandler(Hyperlink_Loaded); this.MouseLeftButtonDown += new MouseEventHandler(Hyperlink_MouseLeftButtonDown); this.MouseLeave += new EventHandler(Hyperlink_MouseLeave); this.MouseLeftButtonUp += new MouseEventHandler(Hyperlink_MouseLeftButtonUp); this.MouseEnter += new MouseEventHandler(Hyperlink_MouseEnter); this.Cursor = Cursors.Hand; } void Hyperlink_MouseEnter(object sender, MouseEventArgs e) { txtlink.TextDecorations = TextDecorations.Underline; } void Hyperlink_MouseLeftButtonUp(object sender, MouseEventArgs e) { if (click == true) { if (_navigateUri != null) { if (_targetname == null) HtmlPage.Navigate(_navigateUri.ToString()); else if(_targetname.ToLower().Equals("new") == true) HtmlPage.Navigate(_navigateUri.ToString(),"__newWindow"); else HtmlPage.Navigate(_navigateUri.ToString(), _targetname); } } } void Hyperlink_MouseLeave(object sender, EventArgs e) { click = false; txtlink.TextDecorations = TextDecorations.None; } void Hyperlink_MouseLeftButtonDown(object sender, MouseEventArgs e) { click = true; } public String NavigateUri { get { return (_navigateUri!= null? _navigateUri.ToString():null); } set { try { _navigateUri = new Uri(value, UriKind.RelativeOrAbsolute); } catch (UriFormatException) { _navigateUri = null; } } } public string TargetName { get { return _targetname; } set { _targetname = value; } } public string Text { get { return txtlink.Text; } set { txtlink.Text = value; } } //Usual Layout GOO void Hyperlink_Loaded(object sender, EventArgs e) { UpdateLayout(); } private void UpdateLayout() { rootCanvas.Height = Height; rootCanvas.Width = Width; txtlink.Height = Height; txtlink.Width = Width; } public new double Height { get { return ((FrameworkElement)this).Height; } set { ((FrameworkElement)this).Height = value; UpdateLayout(); } } public new double Width { get { return ((FrameworkElement)this).Width; } set { ((FrameworkElement)this).Width = value; UpdateLayout(); } } } }
Ideally, I would have liked the TargetUri property to be of type Uri rather than a string but since there is no built-in type converter for Uri yet, Xaml parser would know how to set that property. That is the reason why I have that property as a string and then I internally convert it as a Uri.
Code for Page.xaml
<Canvas x:Name="parentCanvas" xmlns="http://schemas.microsoft.com/client/2007" xmlns="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mycontrol="clr-namespace:HyperlinkApp;assembly=ClientBin/HyperlinkApp.dll" Loaded="Page_Loaded" x:Class="HyperlinkApp.Page;assembly=ClientBin/HyperlinkApp.dll" Width="640" Height="480" Background="White"> <mycontrol:Hyperlink Height="20" Width="450" NavigateUri="http://www.silverlight.net" TargetName="Test" Text="Navigate iFrame" /> <mycontrol:Hyperlink Height="20" Width="450" NavigateUri="http://www.silverlight.net" Canvas.Top="30" Text="Navigate Browser"/> <mycontrol:Hyperlink Height="20" Width="450" NavigateUri="http://www.silverlight.net" TargetName="New" Canvas.Top="60" Text="Navigate New Browser Window"/> </Canvas>
Link to full project is here.
[...] Hyperlink Control [...]