我对C#比较新。我将在超市中举例说明。
我目前有一个表,每个唯一的StoreID / Product组合都有一行,使用此布局:
StoreID Store Country Product In-Stock? Count SalePrice
1 Tesco UK Soap Yes 10 £2.99
2 Asda UK Soap No 0 £0.00
3 Aldi UK Soap Yes 15 £2.98
1 Tesco UK Cheese Yes 10 £4.72
2 Asda UK Cheese No 0 £0.00
3 Aldi UK Cheese Yes 15 £3.57
我想重新安排此表,以便结果显示如下:
Cheese Soap
StoreID Store Country In-Stock? Count SalePrice In-Stock? Count SalePrice
1 Tesco UK Yes 10 £4.72 Yes 10 £2.99
2 Asda UK No 0 £0.00 No 0 £2.49
3 Aldi UK Yes 15 £3.57 Yes 15 £2.98
您会看到我每个唯一商店只有一行(由storeID定义),但现在每个产品都会重复与产品相关的三个列(和肥皂)。
答案 0 :(得分:1)
好的,所以这是一个非常简单的例子,说明如何开始做这样的事情。 (如果你愿意的话,你可能会变得非常强大,但这超出了范围)如果你喜欢这个一般的想法,我建议使用LINQ to SQL并完全跳过数据表转换的东西。 免责声明:( in try / catch评论或评论告诉我为什么有些不好主意,使用ORM等等)这是演示代码,仅用于展示如何思考没有任何第三方组件解决此问题。生产代码必须处理缺少的ID,错误处理,正确的布局和CSS样式,以及更多我不会涉及的内容。
<强> Test.aspx文件强>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Test.aspx.cs" Inherits="WebApplication2.Test" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server">
</asp:GridView>
<div runat="server" id="container">
</div>
</div>
</form>
</body>
</html>
<强>代码隐藏强>
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public class MyStoreObject
{
public int StoreID { get; set; }
public string StoreName { get; set; }
public string Country { get; set; }
public string Product { get; set; }
public bool InStock { get; set; }
public Int16 Count { get; set; }
public double Price { get; set; }
}
public partial class Test : System.Web.UI.Page
{
protected DataTable dtStoreInfo = new DataTable();
protected List<MyStoreObject> MyStoreObjects = new List<MyStoreObject>();
//protected
protected void Page_Init(object sender, EventArgs e)
{
dtStoreInfo.Columns.AddRange(new DataColumn[] {
new DataColumn("StoreID", typeof(int)),
new DataColumn("StoreName", typeof(string)),
new DataColumn("Country", typeof(string)),
new DataColumn("Product", typeof(string)),
new DataColumn("InStock", typeof(bool)),
new DataColumn("Count", typeof(Int16)),
new DataColumn("Price", typeof(double))
});
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
FillDatasource();
TransformDataSourceToObjects();
// here's all the things
GridView1.DataSource = MyStoreObjects;
GridView1.DataBind();
// we need to break this down into a multi-column layout; the store name, id, and country in one section
// then additional sections per product that have the prod as the header, the in-stock, count, and price in body
// you can create whatever controls you need to display this information
var MyStoreObjects_Stores = MyStoreObjects.Select(x => new { x.StoreID, x.StoreName, x.Country }).Distinct();
var MyStoreObjects_Products = MyStoreObjects.Select(x => x.Product).Distinct();
Table displayTable = new Table();
TableRow tRow = new TableRow();
TableCell tCell = new TableCell();
tRow.Cells.Add(tCell);
displayTable.Rows.Add(tRow);
GridView oGridViewMain = new GridView();
oGridViewMain.DataSource = MyStoreObjects_Stores;
oGridViewMain.DataBind();
tCell.Controls.Add(oGridViewMain);
foreach (var product in MyStoreObjects_Products)
{
var resultByProd = MyStoreObjects.Where(x => x.Product == product);
GridView gvProduct = new GridView();
gvProduct.DataSource = resultByProd;
gvProduct.DataBind();
TableCell tCellProd = new TableCell();
tCellProd.Controls.Add(gvProduct);
tRow.Cells.Add(tCellProd);
}
container.Controls.Add(displayTable);
}
}
private void FillDatasource()
{
// assume this comes from a database query eventually, maybe from a dataadapter fill or whatever
dtStoreInfo.Rows.Add(new object[] { 1, "Tesco", "UK", "Soap", true, 10, 2.99 });
dtStoreInfo.Rows.Add(new object[] { 2, "Asda", "UK", "Soap", false, 0, 0.00 });
dtStoreInfo.Rows.Add(new object[] { 3, "Aldi", "UK", "Soap", true, 15, 2.98 });
dtStoreInfo.Rows.Add(new object[] { 1, "Tesco", "UK", "Cheese", true, 10, 4.72 });
dtStoreInfo.Rows.Add(new object[] { 2, "Asda", "UK", "Cheese", false, 0, 0.00 });
dtStoreInfo.Rows.Add(new object[] { 3, "Aldi", "UK", "Cheese", true, 15, 3.57 });
}
private void TransformDataSourceToObjects()
{
// this would ideally come from LINQ to SQL or another ORM, presented simplified here for demo only
foreach (DataRow row in dtStoreInfo.Rows)
{
MyStoreObjects.Add(new MyStoreObject()
{
StoreID = (Int32)row["StoreID"],
StoreName = (string)row["StoreName"],
Country = (string)row["Country"],
Product = (string)row["Product"],
InStock = (bool)row["InStock"],
Count = (Int16)row["Count"],
Price = (double)row["Price"]
});
}
}
}
}
答案 1 :(得分:0)
我在尝试检索所需输出时发现的主要问题是数据表不能有多个具有相同名称的列。所以这里是一个非常简单的概述,我如何检索正确格式的数据:
为每个重复列指定唯一名称(发送到此方法的“前缀”是唯一项目名称):
DataTable GetUniqueColumnNames(DataTable table, string prefix)
{
table.Columns["InStore"].ColumnName = prefix + " - In-Stock?";
table.Columns["Vanda"].ColumnName = prefix + " - Count";
table.Columns["Cattleya"].ColumnName = prefix + " - Price";
return table;
}
使用StoreID作为表主键合并每个项目表(具有唯一的项目相关列)。
这提供了以下内容:
StoreID Store Country Cheese-In-Stock? Cheese-Count Cheese-Price Soap-In-Stock? Soap-Count Soap-Price
1 Tesco UK Yes 10 £4.72 Yes 10 £2.99
2 Asda UK No 0 £0.00 No 0 £2.49
3 Aldi UK Yes 15 £3.57 Yes 15 £2.98
不可否认,它并不像我希望的那样漂亮 - 但是它完成了这项工作!