Show property value instead of class name in Datagridview

Asked

Viewed 257 times

2

I have a Datagridview that should show data between related tables and I can’t get it to show the data correctly, it shows the namespace name followed by the class name. I saw some things and showed an override, but I also read that it is not good practice and suggested to do through the event cellFormating.

What happens to me is this:

inserir a descrição da imagem aqui

This class is in the DTO namespace

 public class Despesa
{
    public int id_despesa { get; set; }
    public Categoria categoria { get; set; }
    public string descricao { get; set; }
    public decimal valor { get; set; }
    public Mes mes { get; set; }
    public string previsao { get; set; }
    public Forma_Pagamento forma_Pagamento { get; set; }
    public Periodo periodo { get; set; }
}

Then my expense collection will inherit a list of expenses

public class DespesaCollection : List<Despesa>
{
}

In the business layer I put all expenses within the collection

foreach (DataRow linha in DataTableDespesas.Rows)
            {
                Despesa despesa = new Despesa();
                despesa.id_despesa = Convert.ToInt32(linha["id_despesa"]);
                despesa.categoria = new Categoria();
                despesa.categoria.id_categoria = Convert.ToInt32(linha["id_categoria"]);
                despesa.descricao = linha["descricao"].ToString();
                despesa.valor = Convert.ToDecimal(linha["valor"]);
                despesa.mes = new Mes();
                despesa.mes.id_mes = Convert.ToInt32(linha["id_mes"]);
                despesa.previsao = linha["previsao"].ToString();
                despesa.forma_Pagamento = new Forma_Pagamento();
                despesa.forma_Pagamento.id_forma_pagamento = Convert.ToInt32(linha["id_formaPagamento"]);
                despesa.periodo = new Periodo();
                despesa.periodo.id_periodo = Convert.ToInt32(linha["id_periodo"]);

                despesaCollection.Add(despesa);
            }

And here’s how I load the collection to display on dataGridView.

 private void carregarDataGridView()
    {
        DespesaCollection despesaCollection = new DespesaCollection();
        DespesaNegocio despesaNegocio = new DespesaNegocio();

        despesaCollection = despesaNegocio.ConsultarTudo();


        dataGridView1.DataSource = null;
        dataGridView1.DataSource = despesaCollection;
        dataGridView1.Refresh();
    }
  • 1

    Show how you are giving bind on the grid. The solution I have, several including.

  • I already edited the question and left everything necessary so you can show me how it’s done, thanks!!! @jbueno

  • @jbueno I was very curious to know what solutions I had for my case!

  • I posted an answer, Diogo. I hope it’s useful.

3 answers

5

Initially I see 2 options:

Include a new property IdCategoria in your DTO:

public class Despesa
{
    public int id_despesa { get; set; }
    public Categoria categoria { get; set; }
    public string descricao { get; set; }
    public decimal valor { get; set; }
    public Mes mes { get; set; }
    public string previsao { get; set; }
    public Forma_Pagamento forma_Pagamento { get; set; }
    public Periodo periodo { get; set; }

    public string IdCategoria 
    {
       get { return categoria.id_categoria; }
    }
}

Or do override of the method ToString in the category object:

public class Categoria
{
  .
  .
  .

  public override string ToString()
  {
    return id_categoria;
  }
}

(I’m not sure the second option works properly in your case)

(If @jbueno replies, you can mark his reply. He came to help you first. :) )

  • The first option worked, but then I have some difficulty editing the columns of dataGridView because I put dataGridView1.Autogeneratecolumns = false;

5


First of all: forget the history of using the CellFormatting for this kind of thing. With a considerable amount of data, you will already start to have performance problems, not to mention that there are much simpler ways to do this.

From what you posted, I see no need to create a Collection to play the dice on the grid. As you are already following this pattern, perhaps the best solution is to actually overwrite the method ToString() of all its models, as long as it doesn’t get in the way of anything.

From what I understand, you make the query in the database, this query returns you a DataTable and from it you create a collection of Despesas to play on the grid. Having a DataTable, you can already do the bind in a DataGridView. So if all the necessary you need to show on grid are in the DataTable, you can do so

private void carregarDataGridView()
{
    var dataTable = RetonarDataTable(); // Vamos supor que este método devolva o datatable

    dataGridView1.DataSource = null;
    dataGridView1.DataSource = dataTable;
    dataGridView1.Refresh();
}

Another, also interesting, way to solve this is to create an "intermediate class" that will contain only the necessary information in the grid. There, instead of instantiating a DespesaCollection, you can create a list of this class and do the bind. See the example below

// essa é a classe "intermediária"
public class DespesaViewModel
{
    public int id_despesa { get; set; }
    public string nome_categoria { get; set; } // Apenas supus que deveria ser assim
    public string descricao { get; set; }
    public decimal valor { get; set; }
    public string descr_mes { get; set; } // Apenas supus que deveria ser assim
    public string previsao { get; set; }
    public string forma_pagamento_descr { get; set; } // Apenas supus que deveria ser assim
    public Periodo periodo { get; set; }
}


var listaDespesas = new List<DespesaViewModel>();
foreach (DataRow linha in DataTableDespesas.Rows)
{
    var despesaVm = new DespesaViewModel
    {
        id_despesa = Convert.ToInt32(linha["id_despesa"]);      
        nome_categoria = Convert.ToInt32(linha["nome_categoria"]);
        ///... assim por diante
    }

    listaDespesas.Add(despesaVm);
}

private void carregarDataGridView()
{
    var lista = CarregarLista();

    dataGridView1.DataSource = null;
    dataGridView1.DataSource = lista;
    dataGridView1.Refresh();
}
  • I was following a tutorial so I was doing this way but it really gets much simpler if my Datagridview receives as datasource the datatable. Thanks for the tips.

  • 1

    Tutorials are usually problems, especially if it is material in Portuguese. You have to pick up the essence and do not try to follow cake recipe, otherwise you will always end up encountering problems like this.

2

When Voce binds an object of a non-primary type, winform calls the Tostring method of that object. So, if you override the Tostring method of each of the classes you are showing (Category, Month, Payment form and Period) you can configure what appears on the grid.

For example, if I want id_category to appear

public class Categoria
{
  public override string ToString()
  {
    return id_categoria.ToString();
  }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.