绑定到包含Dictionary的对象列表
本文关键字:对象 列表 Dictionary 包含 绑定 | 更新日期: 2023-09-27 17:50:31
我有一个名为BaseNode的模型类,它有一个Name属性和一个Dictionary属性。我在这个类中有方法来管理字典在我的BaseNodeViewModel中有一个BaseNodes列表。在下面的示例代码中,我向List添加了2个BaseNode,第一个BaseNode在Dictionary中有3个条目,第二个BaseNode只有1个条目。我想把这个List绑定到ListView。然而,我不想只看到列表中的2个BaseNode,我想看到4个BaseNode。名称-"来自baseNode的字典的键值"。
实现这一目标的最佳方法是什么?我目前有一个方法:"UpdateBindBaseNodeList()",它用字典的名称和键值填充另一个列表(BindBaseNodeList),然后绑定到这个列表。我不太喜欢这个解决方案,因为每次我的原始列表发生变化时,我都需要记住更新这个列表。
模型:
...
public Dictionary<ushort, BitArray> MatIDBitArrayDictionary { get; set; }
...
public void CreateNewMaterialBitArray(ushort matID, int index, int size)
{
var tempBitArray = new BitArray(size);
tempBitArray.Set(index, true);
MatIDBitArrayDictionary.Add(matID, tempBitArray);
}
Viewmodel:
{
...
var testNode1 = new BaseNode();
testNode1.Name = "TestNode";
testNode1.CreateNewMaterialBitArray(0, 0, 100);
testNode1.CreateNewMaterialBitArray(1, 10, 100);
testNode1.CreateNewMaterialBitArray(2, 30, 100);
var testNode2 = new BaseNode();
testNode2.Name = "TestNode2";
testNode2.CreateNewMaterialBitArray(10, 0, 100);
BaseNodes.Add(testNode1);
BaseNodes.Add(testNode2);
UpdateBindBaseNodList();
}
private void UpdateBindBaseNodList()
{
foreach (var baseNode in BaseNodes)
{
ushort[] usedMatIDs = baseNode.GetUsedMaterialIDsArray();
foreach (ushort matID in usedMatIDs)
{
BindBaseNodeList.Add(baseNode.Name + " - " + matID);
}
}
}
听起来像树这样的层次结构更适合显示这些数据。然而,要回答您的问题,您需要"平面化"数据的嵌套列表性质(因此您拥有嵌套foreach循环),而无需每次手动创建新列表。
在不知道任何基础设施的情况下,这里有一些可能有效的方法,尽管有更优雅的方法可以做到这一点。
首先,添加另一个属性,它将表示你想要在ListView中显示的扁平数据(有点像你在UpdateBindBaseNodList中所做的)。
public IEnumerable<String> BaseNodeListFlattened
{
get
{
foreach (var baseNode in BaseNodes)
{
foreach (ushort matId in baseNode.MatIDBitArrayDictionary.Keys)
{
yield return String.Format("{0} - {1}", baseNode.Name, matId);
}
}
}
}
这可以让你随时得到列表。现在你只需要一种方法来告诉视图它已经被更新了。
ObservableCollection
很好地满足了我们的需求。
给定ObservableCollection<BaseNode> BaseNodes;
…
我们可以这样做(也许在ViewModel的构造函数中),以便在更改列表时告诉View。
this.BaseNodes.CollectionChanged += (s, e) => this.OnPropertyChanged("BaseNodeListFlattened");
现在每次你添加一个节点到你的BaseNodes
,它将触发CollectionChanged
事件,然后调用OnPropertyChanged
处理程序并通知视图更新列表,在那里它将读取BaseNodeListFlattened
并刷新其项目列表。
当然还有相应的ListView的xaml…
<ListView ItemsSource="{Binding BaseNodeListFlattened}"/>