绑定到包含Dictionary的对象列表

时间:2015-05-24 17:24:24

标签: c# wpf data-binding

我有一个名为BaseNode的Model类,它有一个Name属性和一个Dictionary属性。我在这个类中有方法来管理Dictionary,我的BaseNodeViewModel中有一个BaseNode列表。在下面的示例代码中,我向List添加了2个BaseNode,第一个BaseNode在Dictionary中有3个条目,第二个只有1.我想将此List绑定到ListView。但是,我不只是想在列表中看到2个BaseNodes,我想看到4:BaseNode.Name - “来自baseNode的字典的键值”。

实现这一目标的最佳方法是什么?我目前有一个方法:“UpdateBindBaseNodeList()”填充另一个List(BindBaseNodeList),其中包含Dictionary的名称和键值,然后我将绑定到此List。我真的不喜欢这个解决方案,因为每次原始列表更改时我都需要记住更新此列表。

型号:

...
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);
}

视图模型:

{
    ...
    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);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

听起来像树这样的层次结构更适合显示这些数据。但是,要回答你的问题,你想要“平坦化”#34;出你的数据的嵌套列表性质(因此你有嵌套的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);
      }
    }
  }
}

这可以随时为您提供清单。现在您只需要一种方法来告诉View它已经更新。

ObservableCollection很好地满足了我们的需求 鉴于ObservableCollection<BaseNode> BaseNodes; ...
我们可以这样做(可能在ViewModel的构造函数中),以便在您更改列表时随时告诉View。

this.BaseNodes.CollectionChanged += (s, e) => this.OnPropertyChanged("BaseNodeListFlattened");

现在,每次向BaseNodes添加节点时,它都会触发CollectionChanged事件,然后调用OnPropertyChanged处理程序并通知View更新列表,阅读BaseNodeListFlattened并刷新其项目列表。

当然还有ListView的相应xaml ......

<ListView ItemsSource="{Binding BaseNodeListFlattened}"/>