PROBLEMA COM CABECALHO DATAGRIDVIEW
Bom dia.
Estou tendo um problema com Datagridview.
Inclui o código abaixo para evitar que o grid preenchesse os campos no form, quando se clicar no cabeçalho da coluna, pois pegava sempre a primeira linha de dados, mas o correto é preencher só se clicar na linha e não no cabeçalho.
Ok está funcionando, porém quero que ao clicar no cabeçalho, as linhas sejam ordenadas(primeiro clique ascendente, segundo clique descendente).
Li que isso é automático, mas não está funcionando. Pesquisei mas não consegui resolver, pois todos os exemplos não são compatÃveis com o meu caso, onde povoo o grid com um List na propriedade DataSource.
Alguém sabe como resolver isso?
Estou tendo um problema com Datagridview.
Inclui o código abaixo para evitar que o grid preenchesse os campos no form, quando se clicar no cabeçalho da coluna, pois pegava sempre a primeira linha de dados, mas o correto é preencher só se clicar na linha e não no cabeçalho.
private void grid_Click(object sender, EventArgs e)
{
if ((grid.CurrentRow == null) || (grid.CurrentRow.Selected == false))
return;
Ok está funcionando, porém quero que ao clicar no cabeçalho, as linhas sejam ordenadas(primeiro clique ascendente, segundo clique descendente).
Li que isso é automático, mas não está funcionando. Pesquisei mas não consegui resolver, pois todos os exemplos não são compatÃveis com o meu caso, onde povoo o grid com um List na propriedade DataSource.
Alguém sabe como resolver isso?
Bem na base da tentativa e erro, pois isso automático não funciona do grid, não sei onde viram que funcionava, consegui, mas é meio trabalhoso, pois se tem de fazer em cada form, para cada grid e identificar no Switch a coluna que ser quer ordenar e como. Ficou assim:
Se cria no inÃcio do form uma variável static para se setar o tipo de ordenação ascendente ou descendente, de modo que o sistema marque o último tipo selecionado.
static string coluna3 = [Ô]Descendente[Ô];
Agora se usa o evento do datagrid abaixo:
nota: para cada coluna será preciso ter uma variável estática e incrementar o switch. Pode existir uma forma mais prática e que evite fazer uma instrução para cada coluna etc.. mas não tive tempo para otimizar isso agora.
O método de orcenação. pego os dados do grid num list, ordeno e devolvo ao grid
Bem amigos é isso, está funcionando perfeitamente, agora se alguém souber de uma forma mais prática, que facilite otimizar a identificação de qual coluna foi clicada, e reduzir o código, agradeço se compartilhar.
abraços
Se cria no inÃcio do form uma variável static para se setar o tipo de ordenação ascendente ou descendente, de modo que o sistema marque o último tipo selecionado.
static string coluna3 = [Ô]Descendente[Ô];
Agora se usa o evento do datagrid abaixo:
private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
switch (e.ColumnIndex -1) // aqui identifico a coluna clicada no grid, tem que subtrair 1 pois ele considera a coluna iniciando em 1 e não no zero.
{
case 3:
coluna3 = coluna3 == [Ô]Ascendente[Ô] ? [Ô]Descendente[Ô] : [Ô]Ascendente[Ô]; //aqui troco o tipo para inverter no próximo clique do cabeçalho.
OrderGrid([Ô]Nome[Ô], coluna3); //chamo o método ordenar, informando o nome da coluna e o tipo de ordenação pela variável coluna3
break;
}
}
nota: para cada coluna será preciso ter uma variável estática e incrementar o switch. Pode existir uma forma mais prática e que evite fazer uma instrução para cada coluna etc.. mas não tive tempo para otimizar isso agora.
O método de orcenação. pego os dados do grid num list, ordeno e devolvo ao grid
private void OrderGrid(string myNomeColuna, string myDirecao)
{
List<InstrutoresModelo> instrutor = grid.DataSource as List<InstrutoresModelo>;
switch (myNomeColuna)
{
case [Ô]Nome[Ô]:
if (myDirecao == [Ô]Ascendente[Ô])
instrutor = instrutor.OrderBy(c => c.Nome.Trim()).ToList(); //ordena ascendente
else
instrutor = instrutor.OrderByDescending(c => c.Nome.Trim()).ToList(); //ordena descendente
break;
}
grid.DataSource = instrutor; //devolvo a lista ordenada ao grid
}
Bem amigos é isso, está funcionando perfeitamente, agora se alguém souber de uma forma mais prática, que facilite otimizar a identificação de qual coluna foi clicada, e reduzir o código, agradeço se compartilhar.
abraços
Bom dia amigos.
Será que não há como fazer essa ordenação de modo mais simples?
Ninguém implementou ordenação no datagridview ainda?
Será que não há como fazer essa ordenação de modo mais simples?
Ninguém implementou ordenação no datagridview ainda?
Alterou a propriedade AllowUserToOrderColluns para True ?
Nilson eu coloquei sim, inclusive como o grid é sempre recriado (colunas) via código a cada carregamento, uma vez que se associa um List a ele, eu inclui essa instrução também no grid_DataBindingComplete para forçar que seja ativada, depois de completar o carregamento, mas em nenhuma das duas opções funciona.
Eu uso os seguintes métodos, não sei se pode estar causando algum conflito, mas não deveria:
Nota: Estou usando o C# 2008, será que há algum bug nele? Tem todas as atualizações que foram disponibilizadas pelo Windows Update.
realmente não sei o que pode ser, testei em alguns forms diferentes e nenhum funciona.
Alguma outra ideia???
Eu uso os seguintes métodos, não sei se pode estar causando algum conflito, mas não deveria:
//Aqui monto o grid via código, a cada pesquisa.
public void MontaGrid()
{
grid.DataSource = null;
grid.Columns.Clear();
// criando as colunas
grid.Columns.Add([Ô]ID[Ô], [Ô]Código[Ô]);
grid.Columns[0].DataPropertyName = [Ô]ID[Ô];
grid.Columns[0].Visible = false;
grid.Columns.Add([Ô]ID_EMPRESA[Ô], [Ô]ID Empresa[Ô]);
grid.Columns[1].DataPropertyName = [Ô]ID_EMPRESA[Ô];
grid.Columns[1].Visible = false;
grid.Columns.Add([Ô]DEPTO[Ô], [Ô]Departamento[Ô]);
grid.Columns[2].DataPropertyName = [Ô]DEPTO[Ô];
grid.Columns[2].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
grid.Columns[2].Width = 125;
grid.Columns[2].DividerWidth = 1;
grid.Columns[2].Visible = true;
grid.Columns.Add([Ô]ID_CHEFE[Ô], [Ô]Código do Chefe[Ô]);
grid.Columns[3].DataPropertyName = [Ô]ID_CHEFE[Ô];
grid.Columns[3].Visible = false;
grid.Columns.Add([Ô]NOME[Ô], [Ô]Nome do Chefe[Ô]);
grid.Columns[4].DataPropertyName = [Ô]NOME[Ô];
grid.Columns[4].Visible = false;
grid.Columns.Add([Ô]INATIVO[Ô], [Ô]Situação[Ô]);
grid.Columns[5].DataPropertyName = [Ô]INATIVO[Ô];
grid.Columns[5].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
grid.Columns[5].Width = 50;
grid.Columns[5].DividerWidth = 1;
grid.Columns[5].Visible = true;
grid.Columns.Add([Ô]RAZAOSOCIAL[Ô], [Ô]Razão Social[Ô]);
grid.Columns[6].DataPropertyName = [Ô]RAZAOSOCIAL[Ô];
grid.Columns[6].Visible = false;
grid.Refresh();
[txt-color=#e80000]grid.AllowUserToOrderColumns = true; [/txt-color] // tentei aqui e também não resolver
}
private void grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// aqui formato o conteúdo de um campo, trocando seu valor numérico com (branco ou X) em função do conteúdo no banco.
if (e.ColumnIndex == grid.Columns[[Ô]INATIVO[Ô]].Index)
{
e.Value = (e.Value.ToString() == 0.ToString() ? string.Empty : [Ô]X[Ô]); //aqui pega o valor como 0 = byte
}
}
private void grid_KeyDown(object sender, KeyEventArgs e) //-> evento disparado ao terminar de pressionar uma tecla
{
if (grid.CurrentRow == null) //-> testar se há linha/registro selecionado no grid
return;
if (e.KeyCode == Keys.Enter) //-> testar se a tecla é ENTER (seleção do registro pelo usuário)
{
grid_Click(grid, new EventArgs()); //-> crio um novo evento click simulando o click no grid para que o item selecionado pela setinha teclado seja realçado no grid.
// seta linha correta selecionada para corrigir erro da tecla ENTER que pula uma linha pra frente
e.SuppressKeyPress = true;
return;
}
if (e.KeyCode == Keys.Down)
{
grid.DefaultCellStyle.SelectionBackColor = corfundo; //-> coloca cor padrão da seleção de uma linha
grid.DefaultCellStyle.SelectionForeColor = corfonte;
return;
}
if (e.KeyCode == Keys.Up)
{
grid.DefaultCellStyle.SelectionBackColor = corfundo; //-> coloca cor padrão da seleção de uma linha
grid.DefaultCellStyle.SelectionForeColor = corfonte;
return;
}
}
private void grid_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
// Evento que ocorre após carregar o grid pelo DataSource, assim eu tiro a seleção do primeiro registro no grid.
// Nota: Se não fizesse assim, sempre ao terminar o carregamento a última linha vinha selecionada e não desejo isso.
DataGridView grid;
grid = (DataGridView)sender;
grid.ClearSelection();
LimparCampos(); //aqui eu limpo os campos, pois foram preenchidos pelo evento Change do grid após carregar o DataTable.
[txt-color=#e80000]grid.AllowUserToOrderColumns = true; [/txt-color] // também tentei aqui e nada
}
private void grid_Click(object sender, EventArgs e) //-> usado evento para selecionar registro do grid/povoar campos no form e evitar erros gerados por outros eventos
{
if (grid.CurrentRow == null)
return;
// se houver seleção de registro no grid, povoa os campos.
txtID.Text = grid.CurrentRow.Cells[[Ô]ID[Ô]].Value.ToString();
.....
// Define a cor da seleção de um registro no grid, para ficar diferente do zebrado.
grid.DefaultCellStyle.SelectionBackColor = Color.Red;
grid.DefaultCellStyle.SelectionForeColor = Color.White;
}
}
Nota: Estou usando o C# 2008, será que há algum bug nele? Tem todas as atualizações que foram disponibilizadas pelo Windows Update.
realmente não sei o que pode ser, testei em alguns forms diferentes e nenhum funciona.
Alguma outra ideia???
Bem amigos, pesquisando muito, mas muito mais, descobri que a ordenação no DataGridView não funciona se usar o preenchimento programaticamente do DataSource. Neste caso tem que se criar métodos / funções especÃficas para ordenar seus dados.
A propriedade AllUserToOrderColums só funciona para dados da coleção Itens do componente ou se o banco estiver vinculado ao grid.
Bem então a solução que encontrei e deixo aqui se alguém precisar, foi usar um switch n evento ColumnHeaderMouseClick do grid que faz a ordenação, tem que definir cada coluna que quer ordenar, e usar uma variável estática auxiliar para cada coluna, a fim de marcar se a última ordenação foi ascendente ou descendente.
Nota: Não sei se funciona com Datas, pois não testei.
Espero que ajude. Vou deixar o tópico aberto só mais alguns dias, pois pode aparecer alguém com uma solução melhor.
IMPORTANTE: Quando postarem uma dúvida e descobrirem como resolver, não feche o post apenas dizendo....[Ô]Já resolvi obrigado[Ô], mas coloque a solução para que outros possam usar se necessário.
A propriedade AllUserToOrderColums só funciona para dados da coleção Itens do componente ou se o banco estiver vinculado ao grid.
Bem então a solução que encontrei e deixo aqui se alguém precisar, foi usar um switch n evento ColumnHeaderMouseClick do grid que faz a ordenação, tem que definir cada coluna que quer ordenar, e usar uma variável estática auxiliar para cada coluna, a fim de marcar se a última ordenação foi ascendente ou descendente.
Nota: Não sei se funciona com Datas, pois não testei.
private void grid_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
List<InstrutoresModelo> instrutor = grid.DataSource as List<InstrutoresModelo>;
switch (grid.Columns[e.ColumnIndex].Name)
{
case [Ô]Nome[Ô]:
colunaNome = colunaNome == [Ô]Ascendente[Ô] ? [Ô]Descendente[Ô] : [Ô]Ascendente[Ô];
if (colunaNome == [Ô]Ascendente[Ô])
instrutor = instrutor.OrderBy(c => c.Nome.Trim()).ToList();
else
instrutor = instrutor.OrderByDescending(c => c.Nome.Trim()).ToList();
break;
case [Ô]ID[Ô]:
colunaID = colunaID == [Ô]Ascendente[Ô] ? [Ô]Descendente[Ô] : [Ô]Ascendente[Ô];
if (colunaID == [Ô]Ascendente[Ô])
instrutor = instrutor.OrderBy(c => c.ID).ToList();
else
instrutor = instrutor.OrderByDescending(c => c.ID).ToList();
break;
}
grid.DataSource = instrutor;
}
Espero que ajude. Vou deixar o tópico aberto só mais alguns dias, pois pode aparecer alguém com uma solução melhor.
IMPORTANTE: Quando postarem uma dúvida e descobrirem como resolver, não feche o post apenas dizendo....[Ô]Já resolvi obrigado[Ô], mas coloque a solução para que outros possam usar se necessário.
Por isso que apesar de muitos condenarem, preencho minhas dezenas ou centenas de datagrids que tenho, tudo na unha, assim não tenho nenhum tipo de limitação, me irritava muito preenchendo via datasource, porque era muito cheio de frescura a manipulação.
E em testes que fiz, a diferença no desempenho é muito pequena, não vale a pena.
E em testes que fiz, a diferença no desempenho é muito pequena, não vale a pena.
Nossa Nilson, mas ficar reinventando a roda não tem lógica. O problema aqui talvez seja exatamente eu não conhecer 100% dos recursos da linguagem, ou como exatamente fazer, mas fazer na mão isso você acaba perdendo outros benefÃcios da linguagem também. Vou testar o código do Ocelot para ver se resolve.
Na realidade perdi o benefÃcio do Order do grid, mas tenho todos os outros recursos que não teria fazendo eu mesmo o preenchimento como Cast. Além disso, continuo com tudo que o List<T> oferece e não teria, assim basta fazer cast e usar os métodos do List, sem ter que escrever nenhuma linha de código (recriar a roda novamente).
Bem gosto é gosto. Valeu sua participação.
Na realidade perdi o benefÃcio do Order do grid, mas tenho todos os outros recursos que não teria fazendo eu mesmo o preenchimento como Cast. Além disso, continuo com tudo que o List<T> oferece e não teria, assim basta fazer cast e usar os métodos do List, sem ter que escrever nenhuma linha de código (recriar a roda novamente).
Bem gosto é gosto. Valeu sua participação.
Citação:Bem gosto é gosto. Valeu sua participação.
Muito bem colocado.
Abraço.
Tópico encerrado , respostas não são mais permitidas