C#根据Windows窗体中接收的数据动态创建组框
我目前正在开发windows窗体应用程序,我想动态创建窗体,根据类别和产品创建GroupBox。 我有两张桌子,像:C#根据Windows窗体中接收的数据动态创建组框,c#,winforms,C#,Winforms,我目前正在开发windows窗体应用程序,我想动态创建窗体,根据类别和产品创建GroupBox。 我有两张桌子,像: +-------------------------------+ | Category | +-------------------------------+ | CategoryId (UNIQUEIDENTIFIER) | | Name (VARCHAR(255)) | | CreatedBy(VARCHAR(2
+-------------------------------+
| Category |
+-------------------------------+
| CategoryId (UNIQUEIDENTIFIER) |
| Name (VARCHAR(255)) |
| CreatedBy(VARCHAR(255)) |
| CreationDate(DATETIME) |
+-------------------------------+
+-----------------------------+
| Product |
+-----------------------------+
| ProductId(UNIQUEIDENTIFIER) |
| CategoryId (FK) |
| Name(VARCHAR(255)) |
| CreatedBy(VARCHAR(255)) |
| CreationDate(DATETIME) |
| IsDeleted(BOOL) |
+-----------------------------+
例如,如果我有一个类别水果
,它的产品是香蕉
和苹果
,但我有另一个类别叫蔬菜
,它的产品是鳄梨
和番茄
,比如:
+--------------------------------------+---------------------+-------------------------+------------------------+
| CategoryId (UNIQUEIDENTIFIER) | Name (VARCHAR(255)) | CreatedBy(VARCHAR(255)) | CreationDate(DATETIME) |
+--------------------------------------+---------------------+-------------------------+------------------------+
| CEF50872-B8E7-4EA0-A3D7-00048FFC82DA | Fruit | Test | 10/11/2018 |
| 646B5A64-EA28-4471-8964-0017EB511797 | Vegetables | Test | 10/12/2018 |
+--------------------------------------+---------------------+-------------------------+------------------------+
+--------------------------------------+--------------------------------------+---------+-------------------------+------------------------+
| ProductId(UNIQUEIDENTIFIER) | CategoryId (FK) | Name | CreatedBy(VARCHAR(255)) | CreationDate(DATETIME) |
+--------------------------------------+--------------------------------------+---------+-------------------------+------------------------+
| D81EFF8C-9B8D-48C9-9CC7-0015B2787D4A | CEF50872-B8E7-4EA0-A3D7-00048FFC82DA | Banana | Test | 10/11/2018 |
| 7683554C-5E46-40FE-9285-001E8CD67740 | CEF50872-B8E7-4EA0-A3D7-00048FFC82DA | Apple | Test | 10/11/2018 |
| 614FBE96-6355-4C3B-985B-002E2B9853CB | 646B5A64-EA28-4471-8964-0017EB511797 | Avocado | Test | 10/11/2018 |
| 74352B1B-36E8-4913-898E-002ED4CB21AD | 646B5A64-EA28-4471-8964-0017EB511797 | Tomato | Test | 10/11/2018 |
+--------------------------------------+--------------------------------------+---------+-------------------------+------------------------+
当我在c#
中从存储过程(如
SELECT * FROM Category AS c
INNER JOIN Product AS P ON C.CategoryId = P.CategoryId
因此,我想动态创建groupbox
。如何根据类别及其产品创建此groupbox
?问候
在决赛中,我想要这样的东西:
更新
我尝试以下评论:
从datatable接收数据:
var data = db.GetTableBySQL("usp_RedMarks_Get");
foreach (DataRow itm in data.Rows)
{
if (itm["CategoryName"].ToString() != CurrentGroupBoxName)
{
flpRedMarks.Controls.Add(GetGroupBox(itm, 200, 100));
}
}
创建GroupBox和项目:
private GroupBox GetGroupBox(DataRow c, int width, int height)
{
GroupBox currentGroupBox = new GroupBox();
currentGroupBox.Size = new Size(width, height);
currentGroupBox.Text = c["CategoryName"].ToString();
currentGroupBox.Name = c["CategoryName"].ToString();
CurrentGroupBoxName = currentGroupBox.Name;
var y = 20;
foreach (var itm in c.Table.Rows)
{
CheckBox cb = new CheckBox();
cb.Text = itm.ToString();
cb.Location = new Point(5, y);
// you can add an event here...
//cb.CheckedChanged += cb_SomeEvent;
currentGroupBox.Controls.Add(cb);
y += 20;
}
return currentGroupBox;
}
我从SQL接收数据,如:
但我得到的不是基于类别的项目(产品),而是合并的数据:
我做错了什么?如果您可以像下面这样向存储过程中添加and ORDER BY子句,请注意:
SELECT C.Name AS 'CategoryName', P.Name AS 'SubcategoryName'
FROM Category AS C
INNER JOIN Product AS P ON C.CategoryId = P.CategoryId
ORDER BY C.Name
然后,您可以像下面这样迭代返回的数据行。请注意,我在组框中添加了一个流面板,以避免需要保留偏移量变量
GroupBox currentGroupBox = new GroupBox();
FlowLayoutPanel currentGroupBoxPanel = null;
foreach (DataRow itm in _data.Rows)
{
var currentCategoryName = itm["CategoryName"].ToString();
if (currentCategoryName != currentGroupBox.Name)
{
currentGroupBox = new GroupBox();
currentGroupBox.Name = currentCategoryName;
currentGroupBoxPanel = new FlowLayoutPanel();
currentGroupBoxPanel.FlowDirection = FlowDirection.TopDown;
currentGroupBoxPanel.Dock = DockStyle.Fill;
currentGroupBox.Controls.Add(currentGroupBoxPanel);
flpRedMarks.Controls.Add(currentGroupBox);
}
var cb = new CheckBox();
cb.Text = itm["SubcategoryName"].ToString();
currentGroupBoxPanel.Controls.Add(cb);
}
如果可以向存储过程中添加and ORDER BY子句,如下所示:
SELECT C.Name AS 'CategoryName', P.Name AS 'SubcategoryName'
FROM Category AS C
INNER JOIN Product AS P ON C.CategoryId = P.CategoryId
ORDER BY C.Name
然后,您可以像下面这样迭代返回的数据行。请注意,我在组框中添加了一个流面板,以避免需要保留偏移量变量
GroupBox currentGroupBox = new GroupBox();
FlowLayoutPanel currentGroupBoxPanel = null;
foreach (DataRow itm in _data.Rows)
{
var currentCategoryName = itm["CategoryName"].ToString();
if (currentCategoryName != currentGroupBox.Name)
{
currentGroupBox = new GroupBox();
currentGroupBox.Name = currentCategoryName;
currentGroupBoxPanel = new FlowLayoutPanel();
currentGroupBoxPanel.FlowDirection = FlowDirection.TopDown;
currentGroupBoxPanel.Dock = DockStyle.Fill;
currentGroupBox.Controls.Add(currentGroupBoxPanel);
flpRedMarks.Controls.Add(currentGroupBox);
}
var cb = new CheckBox();
cb.Text = itm["SubcategoryName"].ToString();
currentGroupBoxPanel.Controls.Add(cb);
}
我将使用
flowLayoutPanel
控件来设置分组框的间距。
然后,您可以编写一个逻辑来动态创建groupbox
元素
以下是实现此任务的一种方法:
namespace WindowsFormsApplication47
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var dataFromDb = GetData();
foreach (var itm in dataFromDb)
{
flowLayoutPanel1.Controls.Add(GetGroupBox(itm, 200, 100));
}
}
private GroupBox GetGroupBox(Category c,int width,int height)
{
GroupBox g = new GroupBox();
g.Size = new Size(width, height);
g.Text = c.Name;
var y = 20;
foreach (var itm in c.Items)
{
CheckBox cb = new CheckBox();
cb.Text = itm;
cb.Location = new Point(5, y);
// you can add an event here...
cb.CheckedChanged += cb_SomeEvent;
g.Controls.Add(cb);
y += 20;
}
return g;
}
private void cb_SomeEvent(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private List<Category> GetData()
{
// Just to simulate a database...
Category c1 = new Category("Fruit", new List<string>() { "Banana", "Apple" });
Category c2 = new Category("Vegetables", new List<string>() { "Avocado", "Tomato" });
Category c3 = new Category("Programming Languages", new List<string>() { "C#", "Visual Basic" });
Category c4 = new Category("Stars", new List<string>() { "Venus", "Mars" });
List<Category> result = new List<Category>();
result.Add(c1);
result.Add(c2);
result.Add(c3);
result.Add(c4);
return result;
}
}
class Category
{
public string Name;
public List<string> Items;
public Category(string name,List<string> items)
{
this.Name = name;
this.Items = items;
}
}
}
我将使用
flowLayoutPanel
控件来设置分组框的间距。
然后,您可以编写一个逻辑来动态创建groupbox
元素
以下是实现此任务的一种方法:
namespace WindowsFormsApplication47
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var dataFromDb = GetData();
foreach (var itm in dataFromDb)
{
flowLayoutPanel1.Controls.Add(GetGroupBox(itm, 200, 100));
}
}
private GroupBox GetGroupBox(Category c,int width,int height)
{
GroupBox g = new GroupBox();
g.Size = new Size(width, height);
g.Text = c.Name;
var y = 20;
foreach (var itm in c.Items)
{
CheckBox cb = new CheckBox();
cb.Text = itm;
cb.Location = new Point(5, y);
// you can add an event here...
cb.CheckedChanged += cb_SomeEvent;
g.Controls.Add(cb);
y += 20;
}
return g;
}
private void cb_SomeEvent(object sender, EventArgs e)
{
throw new NotImplementedException();
}
private List<Category> GetData()
{
// Just to simulate a database...
Category c1 = new Category("Fruit", new List<string>() { "Banana", "Apple" });
Category c2 = new Category("Vegetables", new List<string>() { "Avocado", "Tomato" });
Category c3 = new Category("Programming Languages", new List<string>() { "C#", "Visual Basic" });
Category c4 = new Category("Stars", new List<string>() { "Venus", "Mars" });
List<Category> result = new List<Category>();
result.Add(c1);
result.Add(c2);
result.Add(c3);
result.Add(c4);
return result;
}
}
class Category
{
public string Name;
public List<string> Items;
public Category(string name,List<string> items)
{
this.Name = name;
this.Items = items;
}
}
}
你被卡在哪一部分?通过类别循环?创建分组框?向它们添加项目?在c#中,我不知道如何将产品分组到它们的类别中,以及如何创建groupbox来创建结构:category=groupbox(文本和名称),以及groupbox@Dstanley中的产品您可能最好使用动态控件,如a。这的最终用途是,每个产品都有一个复选框,所以,这就是为什么我想作为组框,我上传了一张关于我的问题的图片,以便更清楚@DourHighArch@Jonathan. 我更新了答案中的代码,以更好地适应您更新的问题。这里的问题是调用
GetGroupBox()
四次,每次调用都会循环返回所有八行结果。您看到的标签是错误的,因为您使用itm.ToString()
获取子类别名称,而不是使用itm[“subcategory name”].ToString()
。希望这能帮上忙。你被卡在哪一部分?通过类别循环?创建分组框?向它们添加项目?在c#中,我不知道如何将产品分组到它们的类别中,以及如何创建groupbox来创建结构:category=groupbox(文本和名称),以及groupbox@Dstanley中的产品您可能最好使用动态控件,如a。这的最终用途是,每个产品都有一个复选框,所以,这就是为什么我想作为组框,我上传了一张关于我的问题的图片,以便更清楚@DourHighArch@Jonathan. 我更新了答案中的代码,以更好地适应您更新的问题。这里的问题是调用GetGroupBox()
四次,每次调用都会循环返回所有八行结果。您看到的标签是错误的,因为您使用itm.ToString()
获取子类别名称,而不是使用itm[“subcategory name”].ToString()
。希望这能帮上忙。看来它行得通,我稍后会测试,如果行得通,我会把它标记为正确答案,非常感谢你们,并和圣诞节结婚!它似乎是有效的,我稍后测试并标记为正确答案,如果它有效的话,非常感谢你和圣诞节结婚!是否可以使用Datatable代替列表?那么我如何从datatable中指定此产品属于此类别?是的,只需在datatable中输入,就像您在列表中输入一样。如果你想举个例子的话,我可以明天再去。我真的很感激。。我已经使用我的问题更新了我的问题DataTable@Jonathan我已经更新了我的答案,并建议直接使用datatable
。请参阅“更新”部分。是否可以使用Datatable代替列表?那么我如何从datatable中指定此产品属于此类别?是的,只需在datatable中输入,就像您在列表中输入一样。如果你想举个例子的话,我可以明天再去。我真的很感激。。我已经使用我的问题更新了我的问题DataTable@Jonathan我已经更新了我的答案,并建议直接使用datatable
。请参阅“更新”部分。