Ниже приведен пример кода, который, я считаю, делает то, что вы ищете. Максимальный размер шрифта жестко задан как 32, но на самом деле это должно быть другое свойство зависимости.
Редактировать: теперь у элемента управления есть DP для коллекций тегов и слов.
XAML:
<UserControl x:Class="TagCloudDemo.TagCloudControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TagCloudDemo="clr-namespace:TagCloudDemo">
<UserControl.Resources>
<TagCloudDemo:WeightToSizeConverter x:Key="WeightToSizeConverter" />
</UserControl.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<ItemsControl
ItemsSource="{Binding Path=Tags, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TagCloudDemo:TagCloudControl}}}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" FontSize="{Binding Path=Weight, Converter={StaticResource WeightToSizeConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace TagCloudDemo
{
public partial class TagCloudControl : UserControl
{
public TagCloudControl()
{
InitializeComponent();
}
public IEnumerable<string> Words
{
get { return (IEnumerable<string>)GetValue(WordsProperty); }
set { SetValue(WordsProperty, value); }
}
public static readonly DependencyProperty WordsProperty =
DependencyProperty.Register("Words",
typeof(IEnumerable<string>),
typeof(TagCloudControl),
new UIPropertyMetadata(new List<string>(), WordsChanged));
public IEnumerable<Tag> Tags
{
get { return (IEnumerable<Tag>)GetValue(TagsProperty); }
set { SetValue(TagsProperty, value); }
}
public static readonly DependencyProperty TagsProperty =
DependencyProperty.Register("Tags",
typeof(IEnumerable<Tag>),
typeof(TagCloudControl),
new UIPropertyMetadata(new List<Tag>(), TagsChanged));
private static void WordsChanged(object sender, DependencyPropertyChangedEventArgs e)
{
TagCloudControl tagCloudControl = sender as TagCloudControl;
tagCloudControl.Tags = TagCloudDemo.Tag.CreateTags(tagCloudControl.Words);
}
private static void TagsChanged(object sender, DependencyPropertyChangedEventArgs e)
{
TagCloudControl tagCloudControl = sender as TagCloudControl;
WeightToSizeConverter converter = tagCloudControl.FindResource("WeightToSizeConverter") as WeightToSizeConverter;
if (converter != null && tagCloudControl.Tags != null)
{
converter.MaxWeight = tagCloudControl.Tags.Max(t => t.Weight);
}
}
}
public class WeightToSizeConverter : IValueConverter
{
public int MaxWeight { get; set; }
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int weight = (int)value;
return 32 * MaxWeight / weight;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion IValueConverter Members
}
}
XAML:
<Window x:Class="TagCloudDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TagCloudDemo="clr-namespace:TagCloudDemo"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TagCloudDemo:TagCloudControl Tags="{Binding Path=Tags}" Grid.Row="0" Background="Red" />
<TagCloudDemo:TagCloudControl Words="{Binding Path=Words}" Grid.Row="1" Background="Yellow" />
</Grid>
</Window>
Код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace TagCloudDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = new VM();
}
}
public class VM
{
public VM()
{
Words = LoadWords();
Tags = Tag.CreateTags(Words);
}
public IEnumerable<string> Words { get; private set; }
public IEnumerable<Tag> Tags { get; private set; }
private static IEnumerable<string> LoadWords()
{
Random random = new Random();
string loremIpsum =
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
string[] tokens = loremIpsum.Split(new char[] {' '});
List<string> words = new List<string>();
for (int i = 0; i < 500; i++)
{
words.Add(tokens[random.Next(tokens.Count())]);
}
return words;
}
}
public class Tag
{
public Tag(string name, int weight)
{
Name = name;
Weight = weight;
}
public string Name { get; set; }
public int Weight { get; set; }
public static IEnumerable<Tag> CreateTags(IEnumerable<string> words)
{
Dictionary<string, int> tags = new Dictionary<string, int>();
foreach (string word in words)
{
int count = 1;
if (tags.ContainsKey(word))
{
count = tags[word] + 1;
}
tags[word] = count;
}
return tags.Select(kvp => new Tag(kvp.Key, kvp.Value));
}
}
}