C# 如何展平嵌套对象(LINQ)

C# 如何展平嵌套对象(LINQ),c#,linq,datagridview,models,C#,Linq,Datagridview,Models,我正在一个旧的Winforms网格上做一些工作,我有两个模型,我正试图将它们展平并分配给DataGridView 这是我的样品模型 public class StockItem { public string StockName { get; set; } public int Id { get; set; } public List<Warehouse> Warehouses { get; set; } } public class Warehous

我正在一个旧的Winforms网格上做一些工作,我有两个模型,我正试图将它们展平并分配给DataGridView

这是我的样品模型

public class StockItem
{
     public string StockName { get; set; }
     public int Id { get; set; }
     public List<Warehouse> Warehouses { get; set; }
}

public class Warehouse
{
     public string WarehouseName { get; set; }
     public int Id { get; set; }
}
我试图通过Linq查询来实现这一点,但只能获得每个StockItem\Warehouse的记录。

我不建议这样做,但您可以使用对象创建具有所需形状的对象这样做不是常见的C#模式。这在Python或Javascript等语言中更常见


C#是一种强类型语言,只有在绝对必要时才应该考虑冒险进入动态对象的世界(想想解析json blob)。我强烈认为你重新评估你需要做的事情,并从不同的角度去看待它。

< P>这应该给你所需要的:

var flattened = stockItems
    .Select(x => new { 
                 StockName = x.StockName, 
                 WarehouseNames = x.Warehouses
                                  .Select(y => y.WarehouseName)
                                  .ToList() })
    .ToList();
它将生成包含
StockName
的项目集合和
WarehouseName
字符串列表<添加代码>列表以枚举查询

对于这些样本数据:

List<StockItem> stockItems = new List<StockItem>
{
    new StockItem
    {
        StockName ="A",
        Id = 1,
        Warehouses = new List<Warehouse>
        {
            new Warehouse { Id = 1, WarehouseName = "x" },
            new Warehouse { Id = 2, WarehouseName = "y" }
        }
    },
    new StockItem
    {
        StockName = "B",
        Id = 2,
        Warehouses = new List<Warehouse>
        {
            new Warehouse { Id = 3, WarehouseName = "z" },
            new Warehouse { Id = 4, WarehouseName = "w" }
        }
    }
};
List stockItems=新列表
{
新库存项目
{
StockName=“A”,
Id=1,
仓库=新列表
{
新仓库{Id=1,WarehouseName=“x”},
新仓库{Id=2,WarehouseName=“y”}
}
},
新库存项目
{
StockName=“B”,
Id=2,
仓库=新列表
{
新仓库{Id=3,WarehouseName=“z”},
新仓库{Id=4,WarehouseName=“w”}
}
}
};
我得到了以下结果:

类似这样的内容:

var availableWarehouses = new [] { 
    new Warehouse { 
        WarehouseName = "Warehouse1",
        Id = 1
    },
    new Warehouse {
        WarehouseName = "Warehouse2",
        Id = 2
    },
    new Warehouse {
        WarehouseName = "Warehouse3",
        Id = 3
    }
};

var stocks = new [] {
    new StockItem {
        StockName = "StockCode1",
        Id = 1,
        Warehouses = new List<Warehouse> { availableWarehouses[0], availableWarehouses[1], availableWarehouses[2] }
    },
    new StockItem {
        StockName = "StockCode2",
        Id = 2,
        Warehouses = new List<Warehouse> { availableWarehouses[0], availableWarehouses[1] }
    },
    new StockItem {
        StockName = "StockCode3",
        Id = 3,
        Warehouses = new List<Warehouse> { availableWarehouses[0], availableWarehouses[2] }
    }
};

var flatten = stocks.Select(item => new {
        StockName = item.StockName,
        WarehousesNames = availableWarehouses.Select(warehouse => item.Warehouses.Contains(warehouse) ? warehouse.WarehouseName : "          ")
            .Aggregate((current, next) => current + "\t" + next)
    });

foreach(var item in flatten) {
    Console.WriteLine("{0}\t{1}", item.StockName, item.WarehousesNames);
}
var availablewalehouses=new[]{
新仓库{
WarehouseName=“Warehouse1”,
Id=1
},
新仓库{
WarehouseName=“Warehouse2”,
Id=2
},
新仓库{
WarehouseName=“Warehouse3”,
Id=3
}
};
var股票=新[]{
新库存项目{
StockName=“StockCode1”,
Id=1,
仓库=新列表{availableWarehouses[0],availableWarehouses[1],availableWarehouses[2]}
},
新库存项目{
StockName=“StockCode2”,
Id=2,
仓库=新列表{availableWarehouses[0],availableWarehouses[1]}
},
新库存项目{
StockName=“StockCode3”,
Id=3,
仓库=新列表{availableWarehouses[0],availableWarehouses[2]}
}
};
var Flant=股票。选择(项目=>新建{
StockName=item.StockName,
WarehousesNames=availableWarehouses.Select(仓库=>item.Warehouses.Contains(仓库)?warehouse.WarehouseName:)
.Aggregate((当前,下一个)=>当前+“\t”+下一个)
});
foreach(展平中的var项目){
Console.WriteLine(“{0}\t{1}”,item.StockName,item.WarehousesNames);
}

您可以通过创建一个
数据表来实现它,您可以轻松地将其用作gridview的源。首先添加所有列,然后为每个库存添加仓库:

var warehouseNames = 
    stocks
    .SelectMany(x => x.Warehouses.Select(y => y.WarehouseName)).Distinct();

var dt = new DataTable();
dt.Columns.Add("StockCode");

foreach (var name in warehouseNames)
{
    dt.Columns.Add(name);
}

foreach (var stock in stocks)
{
    var row = dt.NewRow();
    row["StockCode"] = stock.Id;
    foreach (var warehouse in stock.Warehouses)
    {
        row[warehouse.WarehouseName] = warehouse.Id;
    }
    dt.Rows.Add(row);
}

也许这会有帮助?这不是真正的扁平化,而是交叉表/数据透视结果数据类型是什么?是否存在可与
库存项目关联的最大可能仓库数
?我不熟悉WinForms
DataGridView
,因此我可能缺少一些东西,但您不需要将其绑定到强类型对象集合吗?对于数量可变的仓库,您似乎无法做到这一点。您能否创建一段代码并共享您构建数据的方式?但一般来说,您应该能够使用LINQ查询获得数据。
var warehouseNames = 
    stocks
    .SelectMany(x => x.Warehouses.Select(y => y.WarehouseName)).Distinct();

var dt = new DataTable();
dt.Columns.Add("StockCode");

foreach (var name in warehouseNames)
{
    dt.Columns.Add(name);
}

foreach (var stock in stocks)
{
    var row = dt.NewRow();
    row["StockCode"] = stock.Id;
    foreach (var warehouse in stock.Warehouses)
    {
        row[warehouse.WarehouseName] = warehouse.Id;
    }
    dt.Rows.Add(row);
}