C # Создание групповых блоков динамически в зависимости от данных, полученных в Windows Forms - PullRequest
0 голосов
/ 24 декабря 2018

В настоящее время я работаю с приложением Windows Forms и хочу динамически создать форму, которая создает GroupBox в зависимости от категорий и продуктов.У меня есть две таблицы, например:

+-------------------------------+
|           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)             |
+-----------------------------+

Например, если у меня есть категория Fruit, а ее продукты Banana и Apple, но у меня есть еще одна категория, названная Vegetables, и ее продукты Avocado и Tomato вроде:

+--------------------------------------+---------------------+-------------------------+------------------------+
|    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 в зависимости от категорий и их продуктов?С уважением

В финале я хочу что-то вроде этого: enter image description here

Обновление

Я пытаюсь, как комментарии ниже, как:

Получение данных из таблицы данных:

  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 как:

enter image description here

Но вместо того, чтобы получать товары (товары) по категориям, я получаю объединенные данные: enter image description here

Что я делаю не так?Привет

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

Я бы использовал flowLayoutPanel control, чтобы сделать интервал для групповых блоков.Затем вы можете написать логику, которая будет динамически создавать ваши 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;
        }
    }
}

ВЫХОД GUI:

enter image description here

ОБНОВЛЕНИЕ:

Для запроса OP вот один из способов добиться этого без с использованием List<T>.

В этом примере мы выполняем прямую итерацию для DataTable (после того, как мы четко извлекли категории) и извлекаем соответствующие подкатегории для каждой категории, используя LINQ ,

Пожалуйста, смотрите комментарии внутри кода:

private void Form1_Load(object sender, EventArgs e)
{
    DataTable dataFromDb = GetData();
    // extract distinct categories into an array - for each group box
    string[] distinctCetgories = dataFromDb.AsEnumerable()
        .Select(x => x.Field<string>("CategoryName")).Distinct().ToArray();

    // iterate on the distinct categories
    foreach(var itm in distinctCetgories)
    {
        // extract all the subcategories for the checkboxes inside the groupbox
        string[] subcategories = dataFromDb.AsEnumerable().
            Where(x => x.Field<string>("SubCategoryName") == itm).
            Select(y => y.Field<string>("SubCategoryName")).ToArray();

        flowLayoutPanel1.Controls.Add(GetGroupBox(itm,subcategories, 200, 100));
    }
}

private GroupBox GetGroupBox(string categoryName,string[] subCategories,int width, int 
{
    GroupBox g = new GroupBox();
    g.Size = new Size(width, height);
    g.Text = categoryName;

    var y = 20;

    foreach (var itm in subCategories)
    {
        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 DataTable GetData()
{
    // return datadata using your query:
    // SELECT* FROM Category AS c
    // INNER JOIN Product AS P ON C.CategoryId = P.CategoryId
    // ..... create datatable ......
    return new DataTable();
}
0 голосов
/ 24 декабря 2018

Если вы можете добавить к своей хранимой процедуре предложение 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

Затем вы можете выполнить итерацию по возвращаемым вами строкам DataRow, как показано ниже.Обратите внимание, что я добавляю панель потока внутри группового поля, чтобы избежать необходимости сохранять переменную смещения.

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...