WPF用户控制字符串缩放

时间:2011-03-11 12:13:45

标签: c# wpf wpf-controls

我有一个用户控件,它接受一些字符串并根据字符串在我的集合中出现的次数在UI中显示它们。因此,我的集合中包含字符串的次数越多,它在UI中显示的越大,反之亦然。无论如何我的问题是,目前scrollViewer正在显示标签,但我希望所有标签都显示在一个窗口中,无需滚动,也可以缩放以适应整个窗口。任何人都可以协助吗?谢谢!

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>
</UserControl>

代码背后:

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
    }
}

2 个答案:

答案 0 :(得分:1)

使用ViewBox代替ScrollViewer来包装您的代码云。

答案 1 :(得分:0)

如果您的目标是像wordle.net产生的那样,那么您需要使用画布并使用一些算法定位每个标记,这将最小化每个标记之间的空间,请参阅Algorithm to implement something like Wordle。这将是一些难以编写的代码。

更简单的解决方案是使用wrappanel并放入视图框。将以下代码添加到您的itemscontrol。这是我见过其他人使用的创建标签云控件并发布其代码的解决方案,例如:Creating a Tag Cloud in Silverlight

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>