WPF中如何绑定ObservableCollection<Binding>内嵌套的List<KeyValuePair<BoardElement,int>>集合以展示所有元素
解决WPF嵌套集合数据绑定问题
你的问题核心在于父级列表的ItemTemplate是针对单个Binding对象的,但Outputs是一个集合,不能直接通过Outputs.Key.Name访问——因为集合本身没有Key属性,你需要在父模板中再嵌套一个列表控件来遍历Outputs里的每个元素。
我帮你梳理下解决方案,分两步:先修正后台代码的小问题,再调整XAML的绑定结构。
第一步:修正后台属性访问权限
首先注意:WPF数据绑定只能访问公共属性,你的BoardElement类里Name是私有的,这会导致绑定失败。先把它改成public:
public class BoardElement { public string Name { get; set; } // 保留你的构造函数 public BoardElement(string name) { Name = name; } }
同时确保Binding类的Input属性也是public的(从你的代码看你已经用到了,这里确认一下):
public class Binding { public BoardElement Input { get; set; } // 必须public才能绑定 public List<KeyValuePair<BoardElement, int>> Outputs { get; set; } }
第二步:嵌套ItemsControl遍历Outputs集合
在父级ListBox的ItemTemplate中,添加一个ItemsControl(或ListBox/WrapPanel等),将其ItemsSource绑定到当前Binding对象的Outputs集合。这样就能自动为每个KeyValuePair生成对应的TextBlock。
示例XAML(横向排列Outputs元素)
<ListBox x:Name="ListOfBindngs"> <ListBox.ItemTemplate> <DataTemplate> <!-- 每个Binding对象的容器,可以先显示Input的名称作为标题 --> <StackPanel Margin="0,5"> <TextBlock Text="{Binding Input.Name}" FontWeight="Bold" FontSize="14" Margin="0,0,0,3"/> <!-- 嵌套ItemsControl遍历Outputs集合 --> <ItemsControl ItemsSource="{Binding Outputs}"> <!-- 设置Outputs元素的排列方式:横向换行 --> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <WrapPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <!-- 每个Output元素的模板:显示BoardElement的Name --> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Key.Name}" Margin="5,2" Padding="3,1" Background="#F0F0F0" CornerRadius="2"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
示例XAML(纵向排列Outputs元素)
如果希望每个Output元素纵向排列,只需要把内层ItemsControl的ItemsPanel改成StackPanel即可:
<ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Vertical" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel>
代码逻辑解释
- 外层ListBox:
ItemsSource绑定到你的ObservableCollection<Binding>,所以每个ItemTemplate对应一个Binding对象。 - 内层ItemsControl:
ItemsSource="{Binding Outputs}"表示当前数据上下文是Binding对象,我们要遍历它的Outputs集合。 - 内层ItemTemplate:此时数据上下文是
KeyValuePair<BoardElement, int>,所以{Binding Key.Name}就能访问到BoardElement的Name属性。
测试用后台代码(可选)
你可以给Outputs多添加几个元素,测试绑定效果:
public ObservableCollection<Binding> B { get; set; } public MainWindow() { InitializeComponent(); // 别忘了调用这个初始化XAML控件 // 第一个Binding对象 var a = new Binding(); a.Input = new BoardElement("D1"); a.Outputs = new List<KeyValuePair<BoardElement, int>> { new KeyValuePair<BoardElement, int>(new BoardElement("D2"), 7), new KeyValuePair<BoardElement, int>(new BoardElement("D3"), 9), new KeyValuePair<BoardElement, int>(new BoardElement("D4"), 11) }; // 第二个Binding对象 var b = new Binding(); b.Input = new BoardElement("D5"); b.Outputs = new List<KeyValuePair<BoardElement, int>> { new KeyValuePair<BoardElement, int>(new BoardElement("D6"), 3), new KeyValuePair<BoardElement, int>(new BoardElement("D7"), 5) }; B = new ObservableCollection<Binding> { a, b }; ListOfBindngs.ItemsSource = B; }
这样运行后,每个Binding对象会显示自己的Input名称,下面列出所有Output对应的BoardElement的Name。
内容的提问来源于stack exchange,提问作者sts
相关产品推荐
相关产品推荐

