3

出于本示例的目的,过度简化了我们的模型,假设我们有两个数据列表 ListA 和 ListB,它们的类型都是List<string>。从数据的角度来看,它们是不相关的。ListA 和 ListB 可以独立添加、删除或更新。

我们要做的是在同一个列表中同时显示它们,按序号位置对齐。

我们的第一种方法是创建一个新的 ListMapping 对象,如下所示:

public class ListMapping
{
    public int Index{ get; set; }
    public string StringA{ get; set; }
    public string StringB{ get; set; }
}

然后在 ListA 和 ListB 的序数位置“x”处创建一个List<ListMapping>关联的字符串,我们将像这样初始化它:

var MappedList = new List<ListMapping>();
var maxItems = Math.Max(ListA.Count, ListB.Count);
for(int index = 0; index < maxItems; index++)
{
    var lm = new ListMapping(){
        Index   = index,
        StringA = (index < ListA.Count) ? ListA[index] : null;
        StringB = (index < ListB.Count) ? ListB[index] : null;
    }
    MappedList.Add(lm);
}

这种方法的问题是我们必须手动管理这个新的 ListMap 对象列表。如果从 ListB 中删除了一个项目,那么我们需要手动将所有 ListMapping.StringB 属性上移一个位置以与新的 ListMapping.StringA“重新对齐”。与插入等相同。

我们的下一个方法是实际上不将字符串值存储在 ListMapping 中,只存储索引,并让 getter 直接从底层列表返回值,就像这样......

public class ListMapping
{
    public int Index{ get; set; }
    public string StringA{ get{ (Index < ListA.Count) ? ListA[Index] : null; } }
    public string StringB{ get{ (Index < ListB.Count) ? ListB[Index] : null; } }
}

然后我们会List<ListMapping>像这样初始化对象......

var MappedList = new List<ListMapping>();
var maxItems = Math.Max(ListA.Count, ListB.Count);
for(int index = 0; index < maxItems; index++)
{
    var lm = new ListMapping(){
        Index   = index
    }
    MappedList.Add(lm);
}

使用这种设计,我们只需要触发任何 ListMapping 的 StringA 和 StringB 属性的属性更改通知,其索引可能会受到 ListA 或 ListB 上的操作的影响。绝对更干净,没有对源对象的引用,但现在他们必须引用 List 对象本身。另外,我们仍然需要手动管理 ListMapping 项目的整体列表,以确保始终至少有 'maxItems' 个项目。更好,但并不理想。

我不禁想知道是否有一种方法可以构造一个 ItemsControl 以具有两个 ItemsSource 属性,然后用它的布局面板和 ItemContainerGenerator 做一些聪明的事情,但这似乎就像我会在 UI 中做我已经在做的事情在数据中。

那么,关于解决这个问题的方法有什么想法吗?

4

0 回答 0