VARIAVEL NO LUGAR DE PROPRIEDADE E POSSIVEL?

LUIS.HERRERA 20/01/2014 15:57:44
#433283
Estou pesquisando, mas não acho nada a respeito.

é possível usar o conteúdo de uma variável, para substituir o nome de uma propriedade num objeto, como se passássemos um parâmetro para dizer qual o [Ô]Campo/Atributo[Ô] deste objeto queremos usar?

ex. ao invés de fazer assim....
private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
List<InstrutoresModelo> instrutor = grid.DataSource as List<InstrutoresModelo>;
switch (grid.Columns[e.ColumnIndex].Name)
{
case [Ô]Nome[Ô]:
instrutor = instrutor.OrderBy(c => c.Nome.Trim()).ToList();
break;
case [Ô]IDInstrutor[Ô]:
instrutor = instrutor.OrderBy(c => c.IDInstrutor).ToList();
break;
}

grid.DataSource = instrutor;
}


Seria possível fazer algo deste modo em negrito:

private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
List<InstrutoresModelo> instrutor = grid.DataSource as List<InstrutoresModelo>;
instrutor = instrutor.OrderBy(c => c[grid.Columns[e.ColumnIndex].Name].Trim().ToList();

grid.DataSource = instrutor;
}


Um único problema se possível, seria identificar o tipo do dado no campo, pois se for texto usa o .Trim(), mas se for número não usa. Queria otimizar o código e deixa-lo mais versátil, pois como está tem que fazer um Switch para cada grid e cada campo dele para ordenar. Dessa forma seria muito mais simples.

OCELOT 20/01/2014 16:07:52
#433284
Resposta escolhida
Você já tentou ao invés de reorganizar o datasource usar o método Sort do DataGridView?

http://msdn.microsoft.com/pt-br/library/0868ft3z(v=vs.100).aspx
KERPLUNK 20/01/2014 16:31:06
#433285
Sim! E é bem simples, basta usar em cada propriedade seu respectivo Decoration [Ô]DisplayName[Ô]:

public class Cliente
{
[DisplayName([Ô]Nome do cliente[Ô])]
public string Nome {get; set;}
[DisplayName([Ô]Data de nascimento[Ô])]
public DateTime? DataNascimento {get; set;}
}
LUIS.HERRERA 20/01/2014 16:35:02
#433287
Vi o código, mas não funciona. O Grid é configurado para selecionar os registros por linha, o código exige que seja selecionada uma coluna, aí vai sempre para msgbox que pede pra selecionar uma coluna simples e não dá.
KERPLUNK 20/01/2014 16:45:40
#433288
Tentou como eu mostrei, com o atributo?
LUIS.HERRERA 20/01/2014 16:49:38
#433289
Kerplunk não entendi, esse DisplayName fica dentro da classe entidade antes de cada campo?

Incluí lá, mas DisplayName não é reconhecido pelo VS. Será que não existe no VS 2008? Ou tem de incluir alguma using para habilitar ?

Uma coisa não entendi na sua resposta, o nome do campo na instância já aparece normal:

instrutor = instrutor.OrderBy(c => c.IDInstrutor).ToList();

Veja: c.IDInstrutor

O que eu gostaria é ao invés de declarar cada campo separadamente, usar uma referência ao nome da coluna selecionada no clique dentro dessa instrução, assim reduzindo muitas linhas de código.

instrutor = instrutor.OrderBy(c => c[grid.Columns[e.ColumnIndex].Name].Trim().ToList();


Assim: c[grid.Columns[e.ColumnIndex].Name].
KERPLUNK 20/01/2014 16:53:56
#433290
Exato, acima da declaração de cada propriedade, coloque aquele decoration(DisplayName), e não esqueça do using, que fica no topo:
using System.ComponentModel;
OCELOT 20/01/2014 17:45:38
#433293
Citação:

:
Vi o código, mas não funciona. O Grid é configurado para selecionar os registros por linha, o código exige que seja selecionada uma coluna, aí vai sempre para msgbox que pede pra selecionar uma coluna simples e não dá.


Aquilo é apenas um exemplo, você não precisa fazer como está no exemplo da documentação, que no caso usa um button para organizar as colunas e por isso precisa que uma esteja selecionada, só que tem um outro problema ai, como você está usando um List<T> o sort do grid não funciona também.

Existe uma outra alternativa, que torna até mais fácil fazer isso, você pode usar a seguinte classe para permitir que qualquer objeto que implemente IList<T> sirva como fonte de dados com suporte a Sort
public class SortableBindingListCollection<T> : BindingList<T>
{
private bool isSorted;
private ListSortDirection sortDirection;
private PropertyDescriptor sortProperty;

public SortableBindingListCollection(IList<T> list)
: base(list)
{
}

public void Sort(string field, ListSortDirection direction)
{
if (this.Count > 0)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(this.Items[0]);
PropertyDescriptor myProperty = properties.Find(field,
false);
if (myProperty != null)
ApplySortCore(myProperty, direction);
}
}

protected override bool SupportsSortingCore
{
get { return true; }
}

protected override bool IsSortedCore
{
get { return isSorted; }
}

protected override ListSortDirection SortDirectionCore
{
get { return sortDirection; }
}

protected override PropertyDescriptor SortPropertyCore
{
get { return sortProperty; }
}

protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
sortProperty = prop;
sortDirection = direction;
List<T> list = (List<T>)Items;
list.Sort(delegate(T lhs, T rhs)
{
if (sortProperty != null)
{
isSorted = true;
object lhsValue = lhs == null ? null :
sortProperty.GetValue(lhs);
object rhsValue = rhs == null ? null :
sortProperty.GetValue(rhs);
int result =
System.Collections.Comparer.Default.Compare(lhsValue, rhsValue);
if (sortDirection == ListSortDirection.Descending)
{
result = -result;
}
return result;
}
else
{
isSorted = false;
return 0;
}
});
}

protected override void RemoveSortCore()
{
sortDirection = ListSortDirection.Ascending;
sortProperty = null;
}
}

O que muda no seu código ai é que você não precisa usar o evento ColumnHeaderMouseClick mais, se você criou as colunas manualmente só precisa se certificar que o SortMode delas está como automático, então na hora de definir o DataSource do grid você deve fazer algo do tipo
grid.DataSource = new SortableBindingListCollection<InstrutoresModelo>(seuListComOsDados);

Assim o sort deve funcionar automaticamente quando clicar no header sem precisar de mais nenhum código.
LUIS.HERRERA 21/01/2014 09:25:09
#433313
Ocelot Criei uma classe como você disse, mas tá dando vários erros veja:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HCSGI
{
// aqui entrou todo o seu código da classe


Erro 1:

public SortableBindingListCollection(IList<T> list) : [txt-color=#e80000]base(list)
[/txt-color]
{
} // o erro na parte vermelha diz: [Ô]object does not contain a constructor that takes [ô]1[ô] arguments[Ô]


Erro 2:
public void Sort(string field, ListSortDirection direction)
{
if [txt-color=#e80000](this.Count > 0[/txt-color]) // operador [ô]>[ô] cannot be applied to operands of type [ô]method group [ô]and [ô]int[ô]
{
// aqui não tem as diretivas do assembled, quais são ?
[txt-color=#e80000]PropertyDescriptorCollection properties [/txt-color]=
[txt-color=#e80000]TypeDescriptor[/txt-color].GetProperties(this.[txt-color=#e80000]Items[/txt-color][0]);
[txt-color=#e80000]PropertyDescriptor[/txt-color] myProperty = properties.Find(field,
false);
if (myProperty != null)
ApplySortCore(myProperty, direction);
}
}


Erro 3:
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
sortProperty = prop;
sortDirection = direction;
List<T> list = (List<T>)[txt-color=#e80000]Items[/txt-color]; //Não existe no contexto atual
list.Sort(delegate(T lhs, T rhs)
{
if (sortProperty != null)
{
isSorted = true;
object lhsValue = lhs == null ? null :
sortProperty.GetValue(lhs);
object rhsValue = rhs == null ? null :
sortProperty.GetValue(rhs);
int result =
System.Collections.Comparer.Default.Compare(lhsValue, rhsValue);
if (sortDirection == [txt-color=#e80000]ListSortDirection[/txt-color].Descending) //Não existe no contexto atual
{
result = -result;
}
return result;
}
else
{
isSorted = false;
return 0;
}
});
}

protected override void RemoveSortCore()
{
sortDirection = [txt-color=#e80000]ListSortDirection[/txt-color].Ascending; //Não existe no contexto atual
sortProperty = null;
}
OCELOT 21/01/2014 09:42:06
#433315
Eu devia ter passado os namespaces necessários, mas são apenas dois que são necessários para esta classe

using System.Collections.Generic;
using System.ComponentModel;

Adicionando estes using deve resolver todos os erros.
OCELOT 21/01/2014 09:56:23
#433319
Apenas para registrar aqui o que já respondi para o LUIS HERRERA por PM, o próprio DataGridView já sabe ordenar os itens dele sozinho sem você precisar fazer nada.

O problema é que para isso o DataSource dele precisa dar suporte a ordenação, coisa que neste caso, um List<T> não tem suporte.

Para resolver o problema se usa então esta classe SortableBindingListCollection<T>, que vai encapsular um IList<T> adicionado todos os métodos necessários para ordenar os dados, assim quando se passa este SortableBindingListCollection<T> como DataSource para o DataGridView ele já sabe o que fazer para ordenar os itens automaticamente quando se clica no cabeçalho das colunas.
Página 1 de 2 [12 registro(s)]
Tópico encerrado , respostas não são mais permitidas