|
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 }
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.
|
August 2nd, 2008 at 02:34
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
August 2nd, 2008 at 06:00
hey, looks really great!
August 10th, 2008 at 18:07
[...] 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 [...]
August 20th, 2008 at 21:42
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
August 23rd, 2008 at 12:00
@fred:
Did you add the code for listening to the event?
tagCloud.CloudItemClicked += tagCloud_CloudItemClicked;
August 24th, 2008 at 14:16
[...] 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: [...]
September 21st, 2008 at 16:19
[...] 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 [...]
January 16th, 2009 at 08:05
[...] 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 [...]
February 3rd, 2009 at 10:40
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?
February 3rd, 2009 at 12:13
Basically I want to limit the cloud items I should display in this tagcloud.
February 3rd, 2009 at 12:25
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.
February 4th, 2009 at 07:28
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!
February 5th, 2009 at 07:04
Hi, any suggestion?
February 5th, 2009 at 09:13
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.
February 7th, 2009 at 06:36
Hi, thank you for your good suggestion. But seems, I’m having difficulty implementing it inside your wrap panel class.
Thanks again!
February 7th, 2009 at 21:52
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.
July 17th, 2009 at 21:22
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?
September 22nd, 2009 at 07:22
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.
September 22nd, 2009 at 07:34
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
September 23rd, 2009 at 08:22
hi. its me again.
i cant deploy it to my sharepoint site. any idea?
October 1st, 2009 at 08:23
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?
October 5th, 2009 at 04:49
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.
October 5th, 2009 at 07:41
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
October 8th, 2009 at 09:22
hi mark.
so i just have to add in the codes from
http://blogs.tamtam.nl/peterg/2009/02/13/CreatingA3DTagcloudInSilverlightPart1.aspx?
January 6th, 2010 at 09:22
great job,keep it up,thanks
January 17th, 2010 at 22:20
[...] 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 [...]