IValueConverter 数据绑定

发布于 2024-10-12 05:27:23 字数 4340 浏览 13 评论 0原文

我正在自学一些 .NET 编程,目前正在尝试在 WPF 中构建标签云控件。目标是在窗口上有 2 个列表框,第一个列表框显示“ContactLists”列表,第二个列表框显示与 ContactLists 关联的“标签”(或标签)。对于标签,目的是使用 IValueConverter 将字体大小绑定到 itemCount,因此如果我有一个特定的标签在我的集合中出现多次,那么它会在标签列表框中以更大的字体显示。我还从 DB2 数据库填充我的控件。

因此,我已经在正确的列表框中显示联系人列表和标签,但我只是在绑定方面遇到了一些问题。我正在使用从教程中获取的转换器类,想知道是否有人可以帮助我完成这项工作。非常感谢 - Ben

属性

public class Label
{
    public int LabelID { get; set; }
    public string LabelName { get; set; }

}

ContactListClass

public class ContactList    
    {           
        public string ContactListName { get; set; }
        public List<Label> Labels { get; set; }

    }  

转换器

   public class CountToFontSizeConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            const int minFontSize = 6;
            const int maxFontSize = 38;
            const int increment = 3;
            int count = (int)value;
            return ((minFontSize + count + increment) < maxFontSize) ? 
                    (minFontSize + count + increment)                : 
                    maxFontSize;
        }

        public object ConvertBack(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
        #endregion
    }

窗口加载事件

private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        //TODO: Add event handler implementation here.
        ListCollectionView lcv = new ListCollectionView(myLabels);

        lcv.GroupDescriptions.Add(new PropertyGroupDescription("LabelName"));

        tagsList.ItemsSource = lcv.Groups;                    
    }

XAML

<Window.Resources>
    <local:CountToFontSizeConverter x:Key="CountToFontSizeConverter"/>

    <Style x:Key="tagsStyle" TargetType="{x:Type ListBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBox}">
                    <Grid>
                        <Border x:Name="Border" 
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"/>
                            <WrapPanel Orientation="Horizontal" 
                                       Margin="2" 
                                       IsItemsHost="true" 
                                       Background="#FFFCF6F6"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <DataTemplate x:Key="ContactsTemplate">
    <WrapPanel>
        <TextBlock TextWrapping="Wrap" 
                       Text="{Binding ContactListName, Mode=Default}"/>
    </WrapPanel>
    </DataTemplate>

    <DataTemplate x:Key="TagsTemplate">
    <WrapPanel>
        <TextBlock Text="{Binding LabelName, Mode=Default}" 
                       TextWrapping="Wrap" 
                       FontSize="{Binding ItemCount, 
                                  Converter={StaticResource CountToFontSizeConverter}, 
                                  Mode=Default}" 
                       Foreground="#FF0D0AF7"/>
    </WrapPanel>
    </DataTemplate>
</Window.Resources>

<Grid x:Name="LayoutRoot" Background="#FFCBD5E6">
    <ListBox x:Name="contactsList" 
             SelectionMode="Multiple" 
             Margin="7,8,0,7" 
             ItemsSource="{Binding ContactLists, Mode=Default}" 
             ItemTemplate="{DynamicResource ContactsTemplate}" 
             HorizontalAlignment="Left" 
             Width="254"/>

    <ListBox x:Name="tagsList" 
             Margin="293,8,8,8" 
             ItemsSource="{Binding Labels, Mode=Default}" 
             ItemTemplate="{StaticResource TagsTemplate}" 
             Style="{StaticResource tagsStyle}" />
</Grid>

I am teaching myself some .NET programming and I’m currently trying to build a tag cloud control in WPF. The aim is to have 2 listboxes on a window with the first listbox displaying a list of “ContactLists” and the second listbox displaying the “labels” (or tags) associated with the ContactLists. For the labels the aim is to bind the font size to the itemCount using IValueConverter so if I have a particular label which appears several times in my collection this would be displayed in a bigger font in the labels listbox. Also I’m populating my controls from DB2 database.

So I have got as far as displaying the ContactLists and Labels in the correct listboxes I am just having some trouble with the binding. I am using a converter class which I took from a tutorial and was wondering if anyone can assist me to get this working. Many thanks - Ben

Properties

public class Label
{
    public int LabelID { get; set; }
    public string LabelName { get; set; }

}

ContactListClass

public class ContactList    
    {           
        public string ContactListName { get; set; }
        public List<Label> Labels { get; set; }

    }  

Converter

   public class CountToFontSizeConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            const int minFontSize = 6;
            const int maxFontSize = 38;
            const int increment = 3;
            int count = (int)value;
            return ((minFontSize + count + increment) < maxFontSize) ? 
                    (minFontSize + count + increment)                : 
                    maxFontSize;
        }

        public object ConvertBack(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
        #endregion
    }

Window Loaded event

private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        //TODO: Add event handler implementation here.
        ListCollectionView lcv = new ListCollectionView(myLabels);

        lcv.GroupDescriptions.Add(new PropertyGroupDescription("LabelName"));

        tagsList.ItemsSource = lcv.Groups;                    
    }

XAML

<Window.Resources>
    <local:CountToFontSizeConverter x:Key="CountToFontSizeConverter"/>

    <Style x:Key="tagsStyle" TargetType="{x:Type ListBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListBox}">
                    <Grid>
                        <Border x:Name="Border" 
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"/>
                            <WrapPanel Orientation="Horizontal" 
                                       Margin="2" 
                                       IsItemsHost="true" 
                                       Background="#FFFCF6F6"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <DataTemplate x:Key="ContactsTemplate">
    <WrapPanel>
        <TextBlock TextWrapping="Wrap" 
                       Text="{Binding ContactListName, Mode=Default}"/>
    </WrapPanel>
    </DataTemplate>

    <DataTemplate x:Key="TagsTemplate">
    <WrapPanel>
        <TextBlock Text="{Binding LabelName, Mode=Default}" 
                       TextWrapping="Wrap" 
                       FontSize="{Binding ItemCount, 
                                  Converter={StaticResource CountToFontSizeConverter}, 
                                  Mode=Default}" 
                       Foreground="#FF0D0AF7"/>
    </WrapPanel>
    </DataTemplate>
</Window.Resources>

<Grid x:Name="LayoutRoot" Background="#FFCBD5E6">
    <ListBox x:Name="contactsList" 
             SelectionMode="Multiple" 
             Margin="7,8,0,7" 
             ItemsSource="{Binding ContactLists, Mode=Default}" 
             ItemTemplate="{DynamicResource ContactsTemplate}" 
             HorizontalAlignment="Left" 
             Width="254"/>

    <ListBox x:Name="tagsList" 
             Margin="293,8,8,8" 
             ItemsSource="{Binding Labels, Mode=Default}" 
             ItemTemplate="{StaticResource TagsTemplate}" 
             Style="{StaticResource tagsStyle}" />
</Grid>

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

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

发布评论

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

评论(2

时光瘦了 2024-10-19 05:27:24

你的问题描述得不太清楚,所以我只是发表一些评论。

问题是您的模型(Label 和 ContactList)没有实现 INotifyPropertyChanged,因此 WPF 很难知道此类属性发生了什么变化。但是,如果您不在运行时更改这些值,那么这应该不是问题。

另外,最好返回 Binding.DoNothing 而不是抛出 NotImplementedException。

您还可以从任何地方删除 Mode=Default,但这不是必需的。

我看到您正在绑定到包含标签的列表框。但为什么不绑定联系人列表呢?您应该通过代码全部设置,或者使用绑定(我更喜欢绑定)。

如果您能提供有关实际问题的更多详细信息,也许我可以更好地帮助您。

You are not very exact with your problem, so I am just going to spit some comments.

The problem is that your models (Label and ContactList) don't implement INotifyPropertyChanged, so it's hard for WPF to known what such a property has changed. However, if you do not change the values at runtime, it shouldn't be a problem though.

Also, it's better to return Binding.DoNothing instead of throwing a NotImplementedException.

You can also remove the Mode=Default from everywhere, it's not required.

I see that you are binding to the listbox containing the tags. But why aren't you binding the contactlist as well? You should either set all via code, or use bindings (and I prefer bindings).

If you can provide more details about the actual problem, maybe I can help you out better.

我纯我任性 2024-10-19 05:27:24

本,我仍然不确定你面临的问题;

当你运行你的代码时到底发生了什么?
您的标签名称的字体大小是否已更改?

我在您的代码中看到的问题 -

1 您正在 XAML 和代码中为 tagList 设置 ItemsSource -

ItemsSource="{绑定标签,
模式=默认}”

tagsList.ItemsSource = lcv.Groups;

2 我没有在任何地方看到 ItemCount 属性定义?

3 FontSize 是一个双精度值,因此您的转换器应该返回双精度值而不是 int。

4 您的“标签”列表应该是可观察的集合(以防在运行时添加或删除项目)。

Ben, still I am not sure about the problem you are facing;

what exactly is happening when you run your code?
Is font size of your Label name changed or not?

Problems I can see in your code -

1 You are setting ItemsSource for your tagsList in both XAML and code -

ItemsSource="{Binding Labels,
Mode=Default}"

tagsList.ItemsSource = lcv.Groups;

2 I don't see an ItemCount property defined anywhere?

3 FontSize is a double value so your converter should return double values and not int.

4 Your 'Labels' list should be an observable collection (in case items can get added or removed at run time).

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