绑定字典< T>到WPF列表框绑定、字典、列表、LT

2023-09-02 10:55:51 作者:搁浅的残刺

由于℃的字典;字符串,饮料> ,你会怎么绑定 dictionary.Values​​ 到WPF列表框,这样的项目使用 .Name点属性?

 结构饮料
{
    公共字符串名称{;私定; }
    公众诠释流行{获得;私定; }

    公众饮料(字符串名称,诠释普及)
        : 本 ( )
    {
        this.Name =名称;
        this.Popularity =普及;
    }
}
 

解决方案

项控件上设置的ItemsSource 创建一个绑定到枚举源对象。 T1,T2>一个字典1所述的枚举的类型是的IEnumerable< KeyValuePair< T1,T2>> 。因此,在您的项目模板,您可以绑定到属性,并使用路径语法来获取特定的键和值的属性。

下面是一个例子。首先,code,创建和填充字典,并将其添加到资源字典(有很多不同的方法可以暴露字典数据绑定,这样一个人的简单):

 命名空间WpfApplication17
{
    ///<总结>
    ///为Window1.xaml交互逻辑
    ///< /总结>
    公共部分类窗口1:窗口
    {
        公共窗口1()
        {
            字典<字符串,饮料> D =新字典<字符串,饮料>();
            d.Add(A,新的饮料(NEHI,0));
            d.Add(B,新的饮料(莫邪,1));
            d.Add(C,新的饮料(弗农的,2));
            d.Add(D,新的饮料(Canfield的,3));

            资源[饮料] = d的;

            的InitializeComponent();
        }

        公共类饮料
        {
            公众饮料(字符串名称,诠释普及)
            {
                名称=名称;
                人气=普及;
            }
            公共字符串名称{;组; }
            公众诠释流行{获得;组; }
        }
    }
}
 
C WPF XAML事件 资源 样式

现在的XAML代码填充列表框(虽然的ListView 会更容易些,因为你不会有定义一个模板,这个复杂,使它看起来不错):

 <窗​​口x:类=WpfApplication17.Window1
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        标题=窗口1
        高度=300
        WIDTH =300>
    <电网保证金=10>
        <列表框的ItemsSource ={DynamicResource饮料}Grid.IsSharedSizeScope =真>
            < ListBox.ItemTemplate>
                <的DataTemplate>
                    <电网>
                        < Grid.ColumnDefinitions>
                            < ColumnDefinition SharedSizeGroup =键/>
                            < ColumnDefinition SharedSizeGroup =名称/>
                            < ColumnDefinition SharedSizeGroup =大众化/>
                        < /Grid.ColumnDefinitions>
                        &所述; TextBlock的保证金=2文本={结合密钥}Grid.Column =0/>
                        &所述; TextBlock的保证金=2文本={结合Value.Name}Grid.Column =1/>
                        &所述; TextBlock的保证金=2文本={结合Value.Popularity}Grid.Column =2/>
                    < /网格>
                < / DataTemplate中>
            < /ListBox.ItemTemplate>
        < /列表框>
    < /网格>
< /窗>
 

该XAML的的ListView 是简单了很多,并显示更漂亮,以启动:

 < ListView控件的ItemsSource ={DynamicResource饮料}>
    < ListView.View>
        < GridView控件>
            < GridViewColumn标题=关键
                            DisplayMemberBinding ={结合重点}/>
            < GridViewColumn标题=名称
                            DisplayMemberBinding ={结合Value.Name}/>
            < GridViewColumn标题=大众化
                            DisplayMemberBinding ={结合Value.Popularity}/>
        < / GridView的>
    < /ListView.View>
 < / ListView控件>
 

要回答你的后续问题:

我推荐亚当森的的Windows presentation基金会偷跑的。与面板上的布局本章介绍了如何网格工作相当详细。该电网的pretty的反直觉在很多方面。你以为你想要创建一个电网包含很多项目,但在电网不是动态的。所以,你做的,而不是什么是创建一个电网为每个项目,然后使用共享大小的功能,以确保在每个格列的大小相同。该的ListView 有自己的怪癖,但它是一个简单得多的使用情况。

常见的在网格中显示多个项目

DynamicResource 是一个标记扩展的作品很像的StaticResource 。所不同的是,当XAML分析器做出决议的StaticResource ,因为它分析它 - 如果引用的资源不是在资源字典,它抛出一个异常。 DynamicResource 解析参考,如果该项目被添加到字典后。有一点性能的成本,但它是可以忽略不计在大多数情况下。在code我发布的作品,如果你使用的StaticResource ,因为XAML被解析的的InitializeComponent 。但我不喜欢必须记住这一点,所以我用 DynamicResource 默认情况下,如果我绑定的东西,我加入到资源字典中的code和只是不担心无论是被之前或之后的XAML被解析创建的。

至于工具箱:也许我会开始使用,在VS2010,但我发现一个在2008年unusably车。而且无论如何也非常有用。我做的几乎所有的编辑器我布置工作,有的在Kaxaml。我认为在2008年的可视化编辑器实际上是由学习WPF的困难的,因为它强加给我和XAML之间的抽象层(这本身就是我和WPF对象模型之间的抽象层)。而且这不是一个很好的抽象层:即进入决定什么应该被隐藏,哪些应该是可见的设计决策都没有,在我看来,是正确的。此外,它是越野车的地狱。

Given a dictionary of <string, Drink>, how would you bind the dictionary.Values to a WPF ListBox, so that the items use the .Name property?

struct Drink
{
    public string Name { get; private set; }
    public int Popularity { get; private set; }

    public Drink ( string name, int popularity )
        : this ( )
    {
        this.Name = name;
        this.Popularity = popularity;
    }
}

解决方案

Setting the ItemsSource on an items control creates a binding to the enumerator for the source object. The enumerator of a Dictionary<T1, T2> is of type IEnumerable<KeyValuePair<T1, T2>>. So in your item template, you can bind to the Key and Value properties, and use the path syntax to get specific properties of the key and value.

Here's an example. First the code that creates and populates the dictionary and adds it to the resource dictionary (there are lots of different ways you can expose the dictionary to data binding; this one's simple):

namespace WpfApplication17
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            Dictionary<string, Drink> d = new Dictionary<string, Drink>();
            d.Add("A", new Drink("Nehi", 0));
            d.Add("B", new Drink("Moxie", 1));
            d.Add("C", new Drink("Vernor's", 2));
            d.Add("D", new Drink("Canfield's", 3));

            Resources["Drinks"] = d;

            InitializeComponent();
        }

        public class Drink
        {
            public Drink(string name, int popularity)
            {
                Name = name;
                Popularity = popularity;
            }
            public string Name { get; set; }
            public int Popularity { get; set; }
        }
    }
}

Now the XAML for populating a ListBox (though a ListView would be easier, because you wouldn't have to define a template this complicated to make it look nice):

<Window x:Class="WpfApplication17.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1"
        Height="300"
        Width="300">
    <Grid Margin="10">
        <ListBox ItemsSource="{DynamicResource Drinks}" Grid.IsSharedSizeScope="True">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition SharedSizeGroup="Key" />
                            <ColumnDefinition SharedSizeGroup="Name" />
                            <ColumnDefinition SharedSizeGroup="Popularity" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Margin="2" Text="{Binding Key}" Grid.Column="0"/>
                        <TextBlock Margin="2" Text="{Binding Value.Name}" Grid.Column="1"/>
                        <TextBlock Margin="2"  Text="{Binding Value.Popularity}" Grid.Column="2"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

The XAML for a ListView is a lot simpler, and displays more nicely to boot:

<ListView ItemsSource="{DynamicResource Drinks}">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Key"
                            DisplayMemberBinding="{Binding Key}" />
            <GridViewColumn Header="Name"
                            DisplayMemberBinding="{Binding Value.Name}" />
            <GridViewColumn Header="Popularity"
                            DisplayMemberBinding="{Binding Value.Popularity}" />
        </GridView>
    </ListView.View>
 </ListView>

To answer your follow-up questions:

I recommend Adam Nathan's Windows Presentation Foundation Unleashed. The chapter on layout with panels explains how the Grid works in considerable detail. The Grid's pretty counter-intuitive in a lot of ways. You think that you'd want to create a single Grid that contains many items, but the number of rows and columns in a Grid isn't dynamic. So what you do instead is create a Grid for each item, and then use the shared-size functionality to make sure that the columns in each Grid are the same size. The ListView has quirks of its own, but it's a lot more straightforward for the common "display multiple items in a grid" use case.

DynamicResource is a markup extension that works a lot like StaticResource. The difference is that when the XAML parser resolves StaticResource as it parses it - if the referenced resource isn't in the resource dictionary, it throws an exception. DynamicResource resolves the reference if the item gets added to the dictionary later. There's a bit of a performance cost to this, but it's negligible in most cases. The code I posted works if you use StaticResource, because the XAML gets parsed in InitializeComponent. But I don't like having to remember that, so I use DynamicResource by default if I'm binding to something that I'm adding to the resource dictionary in code and just don't worry about whether it's being created before or after the XAML gets parsed.

And as for the toolbox: Maybe I'll start using that in VS2010, but I find the one in 2008 unusably buggy. And not very useful anyway. I do almost all of my layout work in the editor, and some in Kaxaml. I think the visual editor in 2008 actually made learning WPF harder, because it imposed an abstraction layer between me and the XAML (which is itself an abstraction layer between me and the WPF object model). And it's not a very good abstraction layer: the design decisions that went into deciding what should be hidden and what should be visible aren't, it seems to me, the right ones. Also it's buggy as hell.

 
精彩推荐
图片推荐