do { Engine.BlogAbout(".NET","Silverlight"); } while ( alive );  

Mark Monster

Mark Monster  

Creating a Silverlight TagCloud UserControl

I was just looking around the web to find a Silverlight Control that’s has the features of a TagCloud. There are a lot of TagClouds in the world of Web 2.0, so probably almost everyone knows the way they work.

The looks of a Cloud Item

Just very simple a class that has a name, used for displaying and a weight, used for determining the font-size. You’ll probably want it to have more properties but that can be added when needed I guess.

1 public class CloudItem 2 { 3 public string Name { get; set; } 4 public int Weight { get; set; } 5 }

Determining the style for a CloudItem based on the Weight

I’ve been Googling around to find a nice approach for determining the font-size for a Cloud-Item. I finally found a blog-post about Tag Clouds in ColdFusion that explains an approach that I also followed in this UserControl. It basically supports 5 different font-sizes: Smallest, Small, Medium, Large and Largest. The definition for which font-size is determined by using the minimum and maximum Weights. I did this in a very simple Linq query.

int minWeight = cloudItems.Min((cloudItem => cloudItem.Weight)); int maxWeight = cloudItems.Max((cloudItem => cloudItem.Weight));

And the following method determines which of the five styles should be used.

1 public string DetermineResourceForWeight(CloudItem cloudItem, int minWeight, int maxWeight) 2 { 3 int distribution = (maxWeight - minWeight)/3; 4 if (cloudItem.Weight == minWeight) 5 return "CloudTagStyleSmallest"; 6 if (cloudItem.Weight == maxWeight) 7 return "CloudTagStyleLargest"; 8 if (cloudItem.Weight > (minWeight + (distribution*2))) 9 return "CloudTagStyleLarge"; 10 if (cloudItem.Weight > (minWeight + (distribution))) 11 return "CloudTagStyleMedium"; 12 return "CloudTagStyleSmall"; 13 }

I added the styles to the App.xaml

1 <Application.Resources> 2 <Style x:Key="CloudTagStyleLargest" TargetType="TextBlock"> 3 <Setter Property="Margin" Value="3,3,3,3"/> 4 <Setter Property="FontSize" Value="30"/> 5 </Style> 6 <Style x:Key="CloudTagStyleLarge" TargetType="TextBlock"> 7 <Setter Property="Margin" Value="3,3,3,3"/> 8 <Setter Property="FontSize" Value="25"/> 9 </Style> 10 <Style x:Key="CloudTagStyleMedium" TargetType="TextBlock"> 11 <Setter Property="Margin" Value="3,3,3,3"/> 12 <Setter Property="FontSize" Value="20"/> 13 </Style> 14 <Style x:Key="CloudTagStyleSmall" TargetType="TextBlock"> 15 <Setter Property="Margin" Value="3,3,3,3"/> 16 <Setter Property="FontSize" Value="15"/> 17 </Style> 18 <Style x:Key="CloudTagStyleSmallest" TargetType="TextBlock"> 19 <Setter Property="Margin" Value="3,3,3,3"/> 20 <Setter Property="FontSize" Value="10"/> 21 </Style> 22 <Style x:Key="CloudTagStylePanel" TargetType="TagCloud:WrapPanel"> 23 <Setter Property="Background" Value="White"/> 24 </Style> 25 </Application.Resources>

Converting a CloudItem to a TextBlock

Now we have ourselves some code that covers the logic we have to convert every CloudItem into a TextBlock. The following function converts one CloudItem.

1 public TextBlock ConvertToTextBlock(CloudItem cloudItem, int minWeight, int maxWeight) 2 { 3 return new TextBlock 4 { 5 Text = cloudItem.Name, 6 Style = 7 Application.Current.Resources 8 [DetermineResourceForWeight(cloudItem, minWeight, maxWeight)] as Style, 9 Tag = cloudItem 10 }; 11 }

And this does the conversion for a collection of CloudItems.

IEnumerable<TextBlock> textBlocks = (from cloudItem in cloudItems select cloudItemService.ConvertToTextBlock(cloudItem, minWeight, maxWeight));

Dynamically adding TextBlocks to a Panel

We can add those items very easy to a Panel. We just have to remove all the items that are in it (you’ll never know if there are any) and then just add the TextBlocks.

1 LayoutRoot.Children.Clear(); 2 3 foreach (TextBlock textBlock in textBlocks) 4 { 5 LayoutRoot.Children.Add(textBlock); 6 }

Wrapping the TextBlocks the right way

But yes, there needs to be some layout done. I was not sure if I needed to put time in doing a thing like layout on Panel like Wrapping or some kind. I did again some Googling and found a very nice solution that’s works in this situation, so far. So I just used it!

Interaction with the TagCloud UserControl

It’s important to know how you can interact with the TagCloud UserControl. You can change the collection of CloudItems in the following way.

1 var tagCloud = new TagCloud.TagCloud(); 2 tagCloud.CloudItems = new List<CloudItem> 3 { 4 new CloudItem {Name = ".NET", Weight = 6}, 5 new CloudItem {Name = "API", Weight = 2}, 6 new CloudItem {Name = "C#", Weight = 3}, 7 new CloudItem {Name = "Calendar", Weight = 1}, 8 new CloudItem {Name = "Mail", Weight = 2}, 9 new CloudItem {Name = "PIM", Weight = 4}, 10 new CloudItem {Name = "Reader", Weight = 1}, 11 new CloudItem {Name = "Silverlight", Weight = 5}, 12 new CloudItem {Name = "Task", Weight = 1} 13 };

And you can also listen to clicks on CloudItems by using this code. The CloudItemEventArgs contains the original CloudItem property. Even when you inherit from CloudItem to add properties these will be passed back through the CloudItemEventArgs.

1 tagCloud.CloudItemClicked += tagCloud_CloudItemClicked; 2 3 void tagCloud_CloudItemClicked(object sender, CloudItemEventArgs e) 4 { 5 throw new NotImplementedException(); 6 }

tagCloud Final preview and The sources

I think this control is quite done now. It can become more feature-rich but does the things I want it to do. You can find the sources here.

Please leave a message if you’re using this control. It’s free, but I’d like to know if the control get’s used a lot.

26 Responses to “Creating a Silverlight TagCloud UserControl”

  1. Community Blogs Says:

    Silverlight Cream for August 1, 2008 — #340

    Denislav Savkov with a selection helper class, Mark Monster with SL Tag Cloud, Mike Taulty on asmx web

  2. unruledboy Says:

    hey, looks really great!

  3. Mark Monster » Blog Archive » The TagCloud in practice Says:

    [...] it took me some time to get the TagCloud I created in Silverlight to work with WordPress. It’s very easy It isn’t that it’s difficult to set up the [...]

  4. fred Says:

    Hi
    very nice and so sample !! thanks !!
    sorry but I have a problem with tagCloud_CloudItemClicked.
    The event is never called when I click in the left mouse ???
    any idea ????
    I am using vs2008+XP SL2 beta2

  5. Mark Monster Says:

    @fred:

    Did you add the code for listening to the event?

    tagCloud.CloudItemClicked += tagCloud_CloudItemClicked;

  6. Mark Monster » Blog Archive » The advantage of the TagCloud Says:

    [...] While looking at the TagCloud below I thought, there are some things that can be done better. The article on the original TagCloud can be found here.Like: [...]

  7. Recent Links Tagged With "tagclouds" - JabberTags Says:

    [...] public links >> tagclouds Creating a Silverlight TagCloud UserControl Saved by ybadn on Fri 19-9-2008 Online Marketing and Media ‘08: What I did on my day at the [...]

  8. Recent Faves Tagged With "tagclouds" : MyNetFaves Says:

    [...] First saved by DaveJazzHound | 5 days ago Clouds First saved by JarynRad | 6 days ago Creating a Silverlight TagCloud UserControl First saved by mariobiron | 13 days ago Playing with words First saved by niche82 | 18 days [...]

  9. Jan Michael Says:

    This is great. But I have a question, i want to apply paging (prev | next) to this tag cloud. how can I do this?

    The tag cloud item I should display must be not greater than the height of the grid contrainer of this TagCloud.
    Where should I apply this?

  10. Jan Michael Says:

    Basically I want to limit the cloud items I should display in this tagcloud.

  11. Mark Monster Says:

    Hi Jan,

    What you can do is limit the list of cloudItems. This can be done within the following part

    IEnumerable textBlocks =
    (from cloudItem in cloudItems
    select cloudItemService.ConvertToTextBlock(cloudItem, minWeight, maxWeight)).Take(10)

    If you want to do things like paging, you can easily combine the Take and Skip methods.

  12. Jan Michael Says:

    Thanks for your quick response!
    To explain further about my scenario in paging, the items I should display is based on the grid container of my tagcloud.

    ex: I have 10 tag items, because I have a predefine height of tag cloud, the visible tag item is 5. So then the others should be in the next page.
    Sorry for my lengthy question. I just barely need this. Thanks!

  13. Jan Michael Says:

    Hi, any suggestion?

  14. Mark Monster Says:

    Hi Jan,

    It is possible to measure the highest item per row. If the the max visible height is reached you can stop adding items. Maybe it’s good to give each item an ascending number so you are able to easily select the next items that that should be visible on the next page.

    But in the end it all means measuring. I know this can be very difficult. I’ve had some trouble myself in creating a flow-panel that does the layout I want it to do. I hope this helps you in the right direction.

  15. Jan Michael Says:

    Hi, thank you for your good suggestion. But seems, I’m having difficulty implementing it inside your wrap panel class.

    Thanks again!

  16. Mark Monster Says:

    Hi Jan,

    I can understand the difficulty of implementing it in the Wrap Panel. I do not think about the Wrap Panel as an easy control. It’s already half a year since I implemented it. I hope you will be able to find a solution that fits for your situation.

  17. nk Says:

    Great post! SL newb here, I was trying to follow your tutorial / code to make on my own but am running into some issues. I’m not quite sure where all this code goes… I made a new SL project in VS2008 and added a new class CloudItem in which I only added the Name and Weight. Then in page.xaml.cs I put all that other code in. However this isn’t working…I keep getting this error:

    1. cloudItems does not exist in current context

    Also, do I not need anything in page.xaml?

  18. donna Says:

    hi. nice tagcloud.:) i am currently working on a school project that requires me to do tag cloud and silverlight application. i happened to come across your page and found the tag cloud to be kind of interesting. therefore i decided to use it for my project. perhaps i can score better.:)

    i downloaded the sources from you. but when i opened up the solution, there seemed to be a warning.

    Unable to update auto-refresh reference ’system.web.silverlight.dll’. Cannot find assembly ‘C:\Documents and Settings\Administrator\Desktop\Program Files\Microsoft SDKs\Silverlight\v2.0\Libraries\Server\System.Web.Silverlight.dll’.

    can i know where i can get this .dll file from??

    it would be great if you can help me. because i am not good with IT-related stuffs.

  19. Mark Monster Says:

    Hi Donna,

    This dll is no longer needed. It didn’t much anyway, but basically it included some html that can show the silverlight application.

    Please read this article to understand how to include your Silverlight application using html: http://msdn.microsoft.com/en-us/library/cc189089%28VS.95%29.aspx

  20. donna Says:

    hi. its me again.

    i cant deploy it to my sharepoint site. any idea?

  21. donna Says:

    hi

    i realised the reason why i cant deploy to the sharepoint site is because the source you gave is not a webpart project. it is a web application. am i right?

    however, when i transferred all your codes to the new webpart project that i created, i encountered many errors.

    why is this so?

  22. donna Says:

    hey mark.

    i’m in need of help. i managed to build the application successfully. however, upon debugging, the tags are static. as shown above. it did not move like the one you have. can help me with that? do i have to add in any additional codes for it to work and move?? pls pls i need help.

  23. Mark Monster Says:

    Hi Donna,

    The rotating 3-D Tagcloud is based on the articles of Peter Gerritsen.

    http://blogs.tamtam.nl/peterg/2009/02/13/CreatingA3DTagcloudInSilverlightPart1.aspx
    http://blogs.tamtam.nl/peterg/2009/02/19/CreatingA3DTagcloudInSilverlightPart2.aspx

  24. donna Says:

    hi mark.

    so i just have to add in the codes from

    http://blogs.tamtam.nl/peterg/2009/02/13/CreatingA3DTagcloudInSilverlightPart1.aspx?

  25. waqas Says:

    great job,keep it up,thanks

  26. MeXperience – Step 2 – Architecture and more « Mark Monster Says:

    [...] Google, I first find a component on Codeplex which has tight integration with WCF, second result is an article from my own hand (July 2008), third is the very nice 3D-Tagcloud by Peter Gerritsen. But in the end all that looks like the best [...]

Leave a Reply