【问题标题】:WPF User Control String ScalingWPF 用户控制字符串缩放
【发布时间】:2011-07-13 11:09:47
【问题描述】:

我有一个用户控件,它接受一些字符串并根据字符串在我的集合中出现的次数在 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
    }
}

【问题讨论】:

    标签: c# wpf wpf-controls


    【解决方案1】:

    如果您的目标是类似 wordle.net 产生的东西,那么您需要使用画布并使用某种算法定位每个标签,这将最大限度地减少每个标签之间的空间,请参阅Algorithm to implement something like Wordle。这将是一些难以编写的代码。

    更简单的解决方案是使用包装面板并将其放在视图框内。将以下代码添加到您的项目控件。这是我看到其他人使用的解决方案,他们创建了标签云控件并发布了他们的代码,例如:Creating a Tag Cloud in Silverlight

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

    【讨论】:

    • 嗨,我决定尝试编写一个算法来解决这个问题。请参阅我的最新问题:WPF 自定义面板缩放以适合窗口。谢谢 - 本
    【解决方案2】:

    使用ViewBox 而不是ScrollViewer 来包装您的标签云。

    【讨论】:

    • 问题是当它们不再适合窗口时它会切断一些标签。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多