WPF 用户控制字符串缩放
我有一个用户控件,它接受一些字符串并根据字符串在我的集合中出现的次数在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
ViewBox
而不是ScrollViewer
来包装您的标签云。Use a
ViewBox
instead of aScrollViewer
to wrap your tag cloud.如果您的目标是像 wordle.net 那样生成的内容,那么您需要使用画布并使用某种算法定位每个标签,这将最大限度地减少每个标签之间的空间,请参阅 实现 Wordle 之类的算法。这将是一些很难编写的代码。
一个更简单的解决方案是使用包装面板并放入视图框内。将以下代码添加到您的项目控件中。这是我看到其他人使用创建标签云控件并发布其代码的解决方案,例如: 在 Silverlight 中创建标签云
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