Robertcode
Robertcode

Reputation: 1001

Is there a way to have a WinForms DataGridView with a column displaying multiple values from a record

I am trying to display 2 or 3 values from a record into a single cell row of a DataGridView. Below is a class representing a record to databind to:

Class Book
{
  public int BookId {get;set;}
  public string Title {get;set;}
  public string Publisher {get;set}
  public string Author {get;set}
  public Date CopyrightDate {get;set}
  public byte[] BookCoverImage {get;set}
}

Id like to have a grid that looks like the following:

enter image description here

I am only interested in finding out how to create the second column titled Summary Information. I've been wondering if there is a way to have the information in the Summary Column displayed from a data bound source. For now I am displaying the information each in their own column but would like multiple values in single cell like the sample picture shows. If this can be done in a WinForms DataGridView (or maybe there is another control I should be using?) can someone please provide information or a link to information on how this can be done? Thanks in advance.

Upvotes: 2

Views: 3122

Answers (2)

Reza Aghaei
Reza Aghaei

Reputation: 125197

You can use either of the following solutions:

  • Add a readonly summary property to the class and use a bound column.
  • Use CellFormatting event to provide value for an unbound column.
  • Use CellPainting event to custom draw the content of a bound or unbound cell.
  • Use DataRepeater control.

Option 1 - Adding Summary Property

You can add a new Summary property containing the information which you want to show in cell:

Class Book
{
    // rest of properties ...
    public string Summary
    {
        get 
        {
            return
                $"Title: {this.Title}\n" +
                $"Author: {this.Author}\n" +
                $"Copyright Date: {this.CopyrightDate}";
        }
    }
}

Then you can simply use a bound column to show data in the DataGridView.

Note 1: If the model is auto generated, you can put the new property in a partial class.

Note 2: In case of using DataTable you can simply create a formula column by setting expression for the column.

Option 2 - Cell Formatting

You can add an unbound column and simply provide the value of the cell at runtime in CellFormatting event of the DataGridView control:

private void dgv_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    var dgv = (DataGridView)sender;
    if (e.RowIndex < 0 || e.RowIndex == dgv.NewRowIndex)
        return;
    if (e.ColumnIndex == 1 /*The column index which you want to format*/)
    {
        var book = dgv.Rows[e.RowIndex].DataBoundItem as Book;
        if (book != null)
            e.Value =
                $"Title: {book.Title}\n" +
                $"Author: {book.Author}\n" +
                $"Copyright Date: {book.CopyrightDate}";
    }
}

Option 3 - Using CellPaintig event to custom draw cell

You can see an example of painting cell content with different fonts in this post: How can I create a footer for cell in DataGridView.

Option 4 - Using DataRepeater Control

You can use a DataRepeater control.

The Visual Basic Power Packs DataRepeater control is a scrollable. container for controls that display repeated data, for example, rows in a database table. It can be used as an alternative to the DataGridView control when you need more control over the layout of the data. The DataRepeater "repeats" a group of related controls by creating multiple instances in a scrolling view. This enables users to view several records at the same time.

Upvotes: 4

Amit
Amit

Reputation: 1857

suppose you have dataGridView1 and you want to display data as you have shown in image of question. You can do something like below.

here we have used "\n" to add new lines in cell's value and DefaultCellStyle.WrapMode will take care of putting data in new line properly.

you would need to set columns re-sizable as per content.

List<Book> bookList = new List<Book>();
for(int i = 0; i < 3; i++)
{
    //for simplicity of solution, i have used cover as string not image,
    // you can perform same logic with cover as image too.
    bookList.Add(new Book(i, "title" + i, "publisher" + i, "auther" + i, "cover" + i));
}

DataTable dt = new DataTable();
dt.Columns.Add("ColBook");
dt.Columns.Add("ColData");

foreach(Book book in bookList)
{
    DataRow dr = dt.NewRow();
    dr["ColBook"] = book.BookCoverImage;
    dr["ColData"] = "Title:"+book.Title + "\nPublisher:" + book.Publisher + "\nAuthor:" + book.Author;
    dt.Rows.Add(dr);
}

dataGridView1.DataSource = dt;
dataGridView1.Columns[1].DefaultCellStyle.WrapMode = DataGridViewTriState.True;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

Upvotes: 1

Related Questions