How to make a datagridview C # sort a list (IList) with click on the grid header? [closed]

0

How to make a DataGridView C # sort a list (IList) with click on the grid header?

For example, I have a list with three fields (id, name, city), when the user clicks on the name column, I want to sort by Name, if I click on the city I want to sort 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 click of the column heading in the Grid.

    
asked by anonymous 02.01.2017 / 20:49

2 answers

2

If you create a dataTable you do not have to worry about it

This function converts your list to datatable , you need to install this package via nuget, FastMember , because uses 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 in your program

 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
    
03.01.2017 / 13:39
1

I would like to share the solution I found: Here's an example.

In the ColumnHeaderMouseClick I put a select in the list using a field created in the template just for query, in this select feed the field "query" with the information of the field that I want to sort and then I direct 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; }
}
    
03.01.2017 / 11:31