绑定到包含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);
        }
    }
}

绑定到包含Dictionary的对象列表

听起来像树这样的层次结构更适合显示这些数据。然而,要回答您的问题,您需要"平面化"数据的嵌套列表性质(因此您拥有嵌套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}"/>