Windows Phone: Working With ListBox Items With Hyperlinks

Introduction

Sometimes we may need to detect hyperlinks in a given message. For example I have a Listbox that is bound with multiple message items, but here the problem is that when the user sends hyperlinks to the ListboxItems message we need to detect the hyperlinks in the message content and provide an action for the hyperlink to navigate to the linked page. So this article explains how to work with ListboxItems with hyperlinks. At present this article may not be useful for you, but I am sure it will definitely help you in the future. :)

Requirements

This sample is targeted to WindowsPhone7.1 OS.

Description

To detect hyperlinks from ListboxItems in an app we need to use the following procedure.

Step 1

  • Open Visual Studio.
  • Create a new project, named for example "ListBoxWithHyperLinks".

Step 2

In the DataTemplate of the Listbox, I used a WrapPanel that is great for laying out things in a vertical or horizontal orientation until you reach the edge of the container and then move on to the next column or row. In XAML code, I added a Loaded event for the wrappanel. In the Loaded event I can detect hyperlinks from the bindable message content as well as I can set an action for the hyperlinks by adding a HyperlinkButton to the wrappanel.

To use WrapPanel we need to add Microsoft.Phone.Controls.Toolkit.dll to the references and make sure that the DLL is added to the references as in the following:

DLL is added to the references

Open MainPage.xaml and add the toolkit namespace in the XAML:

  1. xmlns:Toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"   
Let's write the following XAML code.
  1. <Grid x:Name="LayoutRoot" Background="White">     
  2.     <Grid.RowDefinitions>     
  3.         <RowDefinition Height="Auto"/>     
  4.         <RowDefinition Height="*"/>     
  5.     </Grid.RowDefinitions>     
  6.   
  7.     <!--TitlePanel contains the name of the application and page title-->     
  8.     <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">     
  9.         <TextBlock x:Name="ApplicationTitle" FontSize="25" Text="ListBoxItem with Hyperlinks Demo:" Foreground="#FF0FAEEA"  />     
  10.     </StackPanel>     
  11.   
  12.     <Grid  Grid.Row="1">     
  13.         <!--ListBox Content.-->     
  14.         <ListBox Foreground="Black" SelectionMode="Multiple" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="5" Name="ListBoxMessage" BorderBrush="#FFE622E6" BorderThickness="3" >     
  15.            <ListBox.ItemTemplate>     
  16.                 <DataTemplate>     
  17.                     <Grid Height="auto"   Background="White" Width="470" >     
  18.                         <Grid.RowDefinitions>     
  19.                             <RowDefinition Height="auto" />     
  20.                             <RowDefinition Height="auto" />     
  21.                         </Grid.RowDefinitions>     
  22.                         <!--WrapPanel for aligning dynamic TextBlock and HyperLinkButton -->     
  23.                         <Grid Grid.Row="0"  MinHeight="45" VerticalAlignment="Center">     
  24.                             <Toolkit:WrapPanel VerticalAlignment="Center" HorizontalAlignment="Left"  Tag="{Binding Message}" Width="450" Loaded="WrapPanel_Loaded"/>     
  25.                         </Grid>      
  26.                         <!--ListBox Item Seperator -->     
  27.                         <Rectangle  Grid.Row="1" Margin="0,3,0,0" Width="500" Height="3"  Fill="#FF77EEA2" HorizontalAlignment="Left"/>     
  28.                     </Grid>     
  29.                 </DataTemplate>     
  30.             </ListBox.ItemTemplate>     
  31.         </ListBox>     
  32.     </Grid>    
Please in the preceding code, I used a WrapPanel in a DataTemplate and highlighted the two properties Tag (for binding the message content) and Loaded event.

Step 3

Create a class named "Data".
  1. public class Data     
  2. {     
  3.     public string Message { getset; }//for storing message content's     
  4. }  
Create an object in the page constructor to list the "Data" items. Add some static message contents to the list object with a combination of plain text and hyperlinks and finally bind the list to our ListBox (in other words ListBoxMessage).
  1. // Constructor             
  2. public MainPage()     
  3. {     
  4.     InitializeComponent();     
  5.   
  6.     List<Data> ObjDataList = new List<Data>();//for list of Data items     
  7.          
  8.     //List item with plain text     
  9.     ObjDataList.Add(new Data { Message = "SubramanyamRaju WindowsPhone Tutorials is my personal blog ,which is targeted to both beginners and experience" });     
  10.          
  11.     //List item with plain text and hyperlinks     
  12.     ObjDataList.Add(new Data { Message = "SubramanyamRaju WindowsPhone Tutorials blog website link : http://bsubramanyamraju.blogspot.com which is dedicated for only windowsphone development." });     
  13.     ObjDataList.Add(new Data { Message = "Windows developer blog website link :http://blogs.windows.com/buildingapps/" });     
  14.     ObjDataList.Add(new Data { Message = "https://bing.com  is a search engine that brings together the best of search and people in your social networks to help you spend less time searching and more time doing." });     
  15.     ObjDataList.Add(new Data { Message = "The most popular search engines are https://bing.com and http://google.com" });     
  16.   
  17.     //Bind listitem to our ListBox     
  18.     ListBoxMessage.ItemsSource = ObjDataList;     
  19. }   
Note: Here I highlighted the hyperlinks in the Message.

Step 4

In Step 2, I bound the wrappanel Tag property with "Message" and added a Loaded event for wrappanel. We also need to make some changes in the code to make the hyperlink action in the ListBox items. the Loaded event will be fired when the ListBox userinterface begins to load. In this event we can get every wrapapnel Tag message. So the next important step is to detect the hyperlinks from every message. After detecting the hyperlink we need to set that hyperlink to HyperlinkButton and add it to the wrappanel and also add a TextBlock for plaintext. So the entire code is like the following.
  1. private void WrapPanel_Loaded(object sender, RoutedEventArgs e)     
  2. {     
  3.     var objWrapPanel = sender as WrapPanel;     
  4.     //Clear wrapanel child items before set content     
  5.     objWrapPanel.Children.Clear();     
  6.     //Get current listboxitem message with Tag property     
  7.     string Value = Convert.ToString(objWrapPanel.Tag);                 
  8.     //Check if message having http:// or https://     
  9.     if (Value.Contains("http://") || Value.Contains("https://"))     
  10.     {     
  11.         string[] SplitDataSync = Regex.Split(Value, @"(?=http)");//Split message based on http     
  12.         for (int i = 0; i < SplitDataSync.Length; i++)     
  13.         {     
  14.             var normalText = SplitDataSync[i].ToString();     
  15.             if (normalText.Contains("http"))     
  16.             {     
  17.                 string navigateLink = "";     
  18.                 string regUrl = @"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";     
  19.                 Regex r = new Regex(regUrl);     
  20.                 MatchCollection results = r.Matches(normalText);//get collection of hyperlinks from given message list item     
  21.                 foreach (Match m in results)//Loop all http links from push message     
  22.                 {     
  23.                     navigateLink = m.Value.ToString();     
  24.                     break;     
  25.                 }     
  26.   
  27.                 var plainText = normalText.Replace(navigateLink, "");//remove http or https links from message and get plain text only     
  28.   
  29.                 HyperlinkButton hyper = new HyperlinkButton();//for making hyperlinkbutton when link found on message     
  30.                 hyper.HorizontalAlignment = HorizontalAlignment.Left;     
  31.                 hyper.FontSize = 18;     
  32.                 hyper.Foreground = new SolidColorBrush(Colors.Blue);     
  33.                 hyper.NavigateUri = new Uri(navigateLink);     
  34.                 hyper.TargetName = "_blank";     
  35.                 hyper.Margin = new Thickness(-8, 0, 0, 0);     
  36.                 hyper.Content = navigateLink;//set hyperlink to hyperlinkbutton     
  37.                 objWrapPanel.Children.Add(hyper); //add http link  as HyperlinkButton to wrappanel     
  38.   
  39.                 AddTextBlocktoWrapPanel(objWrapPanel, plainText);//add plain text as TextBlock     
  40.   
  41.             }     
  42.             else     
  43.             {     
  44.                 AddTextBlocktoWrapPanel(objWrapPanel, normalText);//add plain text as TextBlock     
  45.             }     
  46.         }     
  47.     }     
  48.     else     
  49.     {     
  50.         AddTextBlocktoWrapPanel(objWrapPanel, Value);//add plain text as TextBlock     
  51.     }     
  52.   
  53.   
  54. }     
  55.   
  56. //Add plain text as TextBlock to WrapPanel     
  57. private void AddTextBlocktoWrapPanel(WrapPanel objWrapPanel, string Text)     
  58. {     
  59.     TextBlock objBlock = new TextBlock();     
  60.     objBlock.Text = Text.Trim();     
  61.     objBlock.MaxWidth = 420;     
  62.     objBlock.Foreground = new SolidColorBrush(Colors.Gray);     
  63.     objBlock.TextWrapping = TextWrapping.Wrap;     
  64.     objWrapPanel.Children.Add(objBlock);     
  65. }   
Screenshots

After running the sample, we will get a screen like this.

running the sample

See in the preceding screen when we tap on the Blue hyperlink from the ListboxItem, it will be redirected to the linked page.

This article is also available at my original blog.

Up Next
    Ebook Download
    View all
    Learn
    View all