How to make a datagridview C# sort a list (Ilist) by clicking on the grid header?

Asked

Viewed 974 times

0

How to make a Datagridview C# sort a list (Ilist) by clicking on the grid header?

For example, I have a list with three fields (id, name, city), when the user click on the column name, I want to order by Name, if click on the city I want to order by City.

public class Pessoa
{
    public int Id { get; set; }
    public String Nome { get; set; }
    public String Cidade { get; set; }
}

Using Ilist People;

Using the column header click in the Grid.

  • Where is the question? The site works different from forum. If you want to share something you’ve done, you need to do it in the format that is shown in [tour]

  • Hello @diegofm, I am new here on the site, thanks for the tip, the next posts I will put the questions, separate from the answers.

2 answers

2

If you create a dataTable you don’t have to "worry" about it

This function converts your list to the datatable, you need to install this package via nuget, Fastmember, because use the TypeAccessor.

public static DataTable ConvertToDatatable(this IList source, String nameColumnPK)
{
    if (source == null) throw new ArgumentNullException();
    var table = new DataTable();
    if (source.Count == 0) return table;

    Type itemType = source[0].GetType();
    table.TableName = itemType.Name;
    List<string> names = new List<string>();
    foreach (var prop in itemType.GetProperties())
    {
        if (prop.CanRead && prop.GetIndexParameters().Length == 0)
        {
            names.Add(prop.Name);
            Type propType = prop.PropertyType;
            if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                propType = propType.GetGenericArguments()[0];
            }
            DataColumn column = new DataColumn(prop.Name, propType);
            table.Columns.Add(column);
            if (nameColumnPK != null && nameColumnPK == prop.Name)
                table.PrimaryKey = new DataColumn[] { column };
        }
    }
    names.TrimExcess();

    var accessor = TypeAccessor.Create(itemType);
    object[] values = new object[names.Count];
    foreach (var row in source)
    {
        for (int i = 0; i < values.Length; i++)
        {
           values[i] = accessor[row, names[i]];
        }
        table.Rows.Add(values);
    }

    return table;
}

and create this extension:

public static DataTable ConvertToDatatable<T>(this IList source, Expression<Func<T, object>>  columnPK)
{
    String member = ((columnPK.Body as UnaryExpression).Operand as System.Linq.Expressions.MemberExpression).Member.Name;
    return ConvertToDatatable(source, member);
}

and then just do this on your show

 listaTeste = new List<Teste>();
 listaTeste.Add(new Teste() { Id = 1, Nome = "Maria", Cidade = "São Paulo" });
 listaTeste.Add(new Teste() { Id = 2, Nome = "Luiza", Cidade = "Curitiba" });
 listaTeste.Add(new Teste() { Id = 3, Nome = "Ana", Cidade = "Porto Alegre" });

 dataGridView1.DataSource = listaTeste.ConvertToDatatable<Teste>(t => t.id);

//o `sort` vai funcionar normalmente, para Id, Nome e Cidade

1

I would like to share the solution I found: Following example.

In Columnheadermouseclick I put a select in the list using a field created in the model for reference only, in this select feed the field "query" with the information of the field I want to sort and then order by the query field.

Achei que seria útil compartilhar, segue Exemplo:

    public partial class Form1 : Form
{
    IList<Teste> listaTeste;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        listaTeste = new List<Teste>();
        listaTeste.Add(new Teste() { Id = 1, Nome = "Maria", Cidade = "São Paulo" });
        listaTeste.Add(new Teste() { Id = 2, Nome = "Luiza", Cidade = "Curitiba" });
        listaTeste.Add(new Teste() { Id = 3, Nome = "Ana", Cidade = "Porto Alegre" });

        var lista = listaTeste.Select(s => new { Id = s.Id, Nome = s.Nome, Cidade = s.Cidade, Consulta = s.GetType().GetProperty("Nome").GetValue(s) }).OrderBy(x => x.Consulta).ToList();

        dataGridView1.DataSource = lista ;

    }

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {

        var lista = listaTeste.Select(s => { s.Consulta = s.GetType().GetProperty(dataGridView1.Columns[e.ColumnIndex].Name).GetValue(s); return s; }).OrderBy(x => x.Consulta).ToList();

        dataGridView1.DataSource = lista;

    }
}


public class Teste
{
    public int Id { get; set; }
    public String Nome { get; set; }
    public String Cidade { get; set; }
    public Object Consulta { get; set; }
}

Browser other questions tagged

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