WPF 用户控制字符串缩放

发布于 2024-10-21 04:08:46 字数 4067 浏览 0 评论 0原文

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

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

I have a user control which takes some strings and displays them in the UI according to how many times the string appears in my collection. Therefore the more times a string is contained in my collection then the larger it would appear in the UI and vice versa. Anyway my problem is that at the moment a scrollViewer is displaying the tags but I would like all the tags to be displayed in one window without the need for scrolling and also scale to fit the whole window. Can anyone assist with this? thanks!

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>

Code behind:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

臻嫒无言 2024-10-28 04:08:46

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

Use a ViewBox instead of a ScrollViewer to wrap your tag cloud.

彼岸花ソ最美的依靠 2024-10-28 04:08:46

如果您的目标是像 wordle.net 那样生成的内容,那么您需要使用画布并使用某种算法定位每个标签,这将最大限度地减少每个标签之间的空间,请参阅 实现 Wordle 之类的算法。这将是一些很难编写的代码。

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

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

If your goal is something like wordle.net produces then you need to use a canvas and position each tag using some algorithm which will minimize space between each tag, see Algorithm to implement something like Wordle. This will be some hard code to write.

A simpler solution would be to use a wrappanel and put inside a viewbox. Add below code to your itemscontrol. This is the solution I have seen others use who created tag cloud controls and published their code, for example: Creating a Tag Cloud in Silverlight

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文