user7045250
user7045250

Reputation:

How to display DataGridView rows in blocks - Visual C#

I have a program that gets data from a MySQL Database and displays it to a DataGridView. Because each row is an app that can be downloaded, I want each row to be displayed in it's own little block. Here's a little sketch of what I want:

Each box shown is a row. Each section (Icon, app name, description, downloadbtn) is a column. Anyone know how to do this?

Upvotes: 1

Views: 260

Answers (1)

TaW
TaW

Reputation: 54433

ListViews don't support DataBinding and while DataGridviews do they only display a matrix of rows and columns, so they can't display row data side by side.

I suggest do away with your DataGridview.

Instead you tie the data to a suitable other container which you fill with a UserControl that display your data. An AutoScrolling FlowLayoutPanel is probably the best choice.

So you create a UserControl, called, say DataBox, add a few Labels and the Button and an extra constructor that can load the data from a DataTable.DataRow.

Then you code a loading function that creates a new DataBox for each row in the table and loads its fields into your Labels.

Then you call the function from all spots where the data change like maybe the RowChanged event of the DataTable..

Here is a minimal example class:

enter image description here

public delegate void ButtonClick(object sender, EventArgs e);

public partial class DataBox : UserControl
{
    public DataRow row  { get; set; }

    public ButtonClick ButtonClick { private get; set; }

    public DataBox()
    {
        InitializeComponent();
    }

    public DataBox(DataRow row)
    {
        InitializeComponent();
        loadRow(row);
        button1.GotFocus += (s, e) => { BackColor = Color.SkyBlue; };
        button1.LostFocus += (s, e) => { BackColor = Color.Azure; };
    }

    public void loadRow(DataRow row_)
    {
        if (row_ == null || row_.ItemArray.Length < 3) return;
        row = row_;
        label1.Text = row.ItemArray[0].ToString();
        label2.Text = row.ItemArray[1].ToString();
        label3.Text = row.ItemArray[2].ToString();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (ButtonClick != null) ButtonClick(sender, e);
    }
}

When data change the display will refresh:

private void DT_RowChanged(object sender, DataRowChangeEventArgs e)
{
    loadBoxes();
}

This is a loading function, which loads all rows in the table:

void loadBoxes()
{
    List<DataBox> boxes = new List<DataBox>();
    foreach (DataRow row in DT.Rows)
        boxes.Add(new DataBox(row) { ButtonClick = boxButton_Click } );
    flowLayoutPanel1.Controls.Clear();
    flowLayoutPanel1.Controls.AddRange(boxes.ToArray());
    boxes.Clear();
}

The Buttons are calling a central click processing function in you form:

private void boxButton_Click(object sender, EventArgs e)
{
    Button btn = sender as Button;
    DataBox box = btn.Parent as DataBox;
    if (box != null)
        Console.WriteLine(box.rowID + " clicked");
}

But of course you may instead code their click right in the DataBox class..

You may want to improve on a few other points, like updating single rows or making the Labels send focus to the Button, thus causing the BackColor to show the 'selection'..

Upvotes: 2

Related Questions