Como alterar a cor da linha no datagridview?

143

Gostaria de mudar a cor de uma linha específica no meu DataGridView. A linha deve ser alterada para vermelho quando o valor da célula da coluna 7 for menor que o valor da célula da coluna 10. Alguma sugestão sobre como fazer isso?

EB.
fonte

Respostas:

192

Você precisa percorrer as linhas no datagridview e comparar os valores das colunas 7 e 10 em cada linha.

Tente o seguinte:

foreach (DataGridViewRow row in vendorsDataGridView.Rows) 
     if (Convert.ToInt32(row.Cells[7].Value) < Convert.ToInt32(row.Cells[10].Value)) 
     {
         row.DefaultCellStyle.BackColor = Color.Red; 
     }
Ricardo Sanchez
fonte
1
Obrigado pela ajuda Ricardo. Eu tentei o código que você sugeriu. Ainda não consigo fazer funcionar. Você se importaria de dar uma olhada neste código e me dizer onde eu errei? Eu sou um estudante de C # inicial. Tenho certeza de que simplesmente não escrevi o código de comparação corretamente. foreach (linha DataGridView em vendorsDataGridView.Rows) {if (row.Cells [7] .Value é <row.Cells [10] .Value) {dataGridViewTextBoxColumn7.DefaultCellStyle.BackColor = red; } } Eu aprecio sua ajuda. EB
EB.
EB Adicionei um novo código com base no código que você forneceu. Sua sintaxe foi um pouco mais lenta, tente o código que acabei de adicionar acima.
Ricardo Sanchez
2
Ricardo. Alterei .text para .value e mudei para DefaultCellstyle.Backcolor = color.red e o código funcionou !!! Obrigado pelo seu tempo! EB
EB.
60

Eu estava apenas investigando esse problema (então eu sei que essa pergunta foi publicada há quase 3 anos, mas talvez ajude alguém ...), mas parece que uma opção melhor é colocar o código dentro do RowPrePaintevento para que você não precisa percorrer todas as linhas, apenas as que são pintadas (para que ele tenha um desempenho muito melhor em grande quantidade de dados:

Anexar ao evento

this.dataGridView1.RowPrePaint 
    += new System.Windows.Forms.DataGridViewRowPrePaintEventHandler(
        this.dataGridView1_RowPrePaint);

O código do evento

private void dataGridView1_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
{
    if (Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells[7].Text) < Convert.ToInt32(dataGridView1.Rows[e.RowIndex].Cells[10].Text)) 
    {
        dataGridView1.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Beige;
    }
}
Éden
fonte
3
Eu realmente gosto de como você pega o problema na raiz, em vez de esperar até que tudo tenha sido pintado. Essa é uma abordagem muito "fora da caixa". A maioria das pessoas prefere apenas loop através de cada linha de novo ...
bird2920
Além de ser muito mais rápido, também ajuda a fazê-lo no momento certo. Eu tive problemas com minhas linhas não ficarem coloridas, provavelmente porque defini a cor na hora errada. Com essa abordagem, é garantido que isso aconteça no momento correto.
sanderd17
1
Isso funciona bem. Também depois de ordenar a atualização da maneira correta.
macmuri
24

Você está procurando o CellFormattingevento.
Aqui está um exemplo.

SLaks
fonte
2
A diferença com essa abordagem é que cada célula será comparada em vez de apenas uma. Pode ser um problema de desempenho se você tiver várias centenas de células.
Ricardo Sanchez
21

Também tive problemas para alterar a cor do texto - nunca vi a cor mudar.

Até eu adicionei o código para alterar a cor do texto para o evento DataBindingsCompletepara DataGridView. Depois disso, funcionou.

Espero que isso ajude as pessoas que enfrentam o mesmo problema.

user1614017
fonte
a cor do texto não muda quando a substituição onLoad (..) ou o evento. DataBindingsComplete é um local muito melhor para fazer a configuração de cores das linhas.
Timothy
13

Algo como o seguinte ... assumindo que os valores nas células sejam Inteiros.

foreach (DataGridViewRow dgvr in myDGV.Rows)
{
  if (dgvr.Cells[7].Value < dgvr.Cells[10].Value)
  {
    dgvr.DefaultCellStyle.ForeColor = Color.Red;
  }
}

não testado, portanto, desculpe-me por qualquer erro.

Se você conhece a linha específica, pode pular a iteração:

if (myDGV.Rows[theRowIndex].Cells[7].Value < myDGV.Rows[theRowIndex].Cells[10].Value)
{
  dgvr.DefaultCellStyle.ForeColor = Color.Red;
}
Demi
fonte
Obrigado pela ajuda. Sua sugestão é a mais próxima que cheguei de resolver o problema. Mas continuo recebendo o erro dizendo que "Valor" não existe no contexto ou "Células" não existe no contexto. Tentando descobrir ...
EB.
esta linha de código (dgvr.Cells [7] .Value <dgvr.Cells [10] .Value) agora me fornece esse erro O operador '<' não pode ser aplicado a operandos do tipo 'objeto' e 'objeto'
EB.
Lance-os para Inteiro, então. :-) algo como: Convert.ToInt32 (dvgr.Cells [7] .Value) <Convert.ToInt32 (dgvr.Cells [10] .Value)
Demi
8

Algumas pessoas gostam de usar os eventos Paint, CellPaintingou CellFormatting, mas observe que a alteração de um estilo nesses eventos causa chamadas recursivas. Se você o usar, DataBindingCompleteele será executado apenas uma vez. O argumento para CellFormattingé que ele é chamado apenas em células visíveis, para que você não precise formatar células não visíveis, mas as formate várias vezes.

Denise Skidmore
fonte
5

Você pode alterar Backcolorlinha por linha usando seu condition.and esta chamada de função após a aplicação Datasourcede DatagridView.

Aqui está a função para isso. Simplesmente copie e coloque depoisDatabind

private void ChangeRowColor()
{
    for (int i = 0; i < gvItem.Rows.Count; i++)
    {
        if (BindList[i].MainID == 0 && !BindList[i].SchemeID.HasValue)
            gvItem.Rows[i].DefaultCellStyle.BackColor = ColorTranslator.FromHtml("#C9CADD");
        else if (BindList[i].MainID > 0 && !BindList[i].SchemeID.HasValue)
            gvItem.Rows[i].DefaultCellStyle.BackColor = ColorTranslator.FromHtml("#DDC9C9");
        else if (BindList[i].MainID > 0)
            gvItem.Rows[i].DefaultCellStyle.BackColor = ColorTranslator.FromHtml("#D5E8D7");
        else
            gvItem.Rows[i].DefaultCellStyle.BackColor = Color.White;
    }
}
Pratik 1020
fonte
3
private void dtGrdVwRFIDTags_DataSourceChanged(object sender, EventArgs e)
{
    dtGrdVwRFIDTags.Refresh();
    this.dtGrdVwRFIDTags.Columns[1].Visible = false;

    foreach (DataGridViewRow row in this.dtGrdVwRFIDTags.Rows)
    {
        if (row.Cells["TagStatus"].Value != null 
            && row.Cells["TagStatus"].Value.ToString() == "Lost" 
            || row.Cells["TagStatus"].Value != null 
            && row.Cells["TagStatus"].Value.ToString() == "Damaged" 
            || row.Cells["TagStatus"].Value != null 
            && row.Cells["TagStatus"].Value.ToString() == "Discarded")
        {
            row.DefaultCellStyle.BackColor = Color.LightGray;
            row.DefaultCellStyle.Font = new Font("Tahoma", 8, FontStyle.Bold);
        }
        else
        {
            row.DefaultCellStyle.BackColor = Color.Ivory;
        }
    }  

    //for (int i= 0 ; i<dtGrdVwRFIDTags.Rows.Count - 1; i++)
    //{
    //    if (dtGrdVwRFIDTags.Rows[i].Cells[3].Value.ToString() == "Damaged")
    //    {
    //        dtGrdVwRFIDTags.Rows[i].Cells["TagStatus"].Style.BackColor = Color.Red;                   
    //    }
    //}
}
Christopher
fonte
2

Esta é minha solução para alterar a cor para dataGridView com bindingDataSource:

private void dataGridViewECO_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{            

    if (e.ListChangedType != ListChangedType.ItemDeleted)
    {

        DataGridViewCellStyle green = this.dataGridViewECO.DefaultCellStyle.Clone();
        green.BackColor = Color.Green;

        DataGridViewCellStyle gray = this.dataGridViewECO.DefaultCellStyle.Clone();
        gray.BackColor = Color.LightGray;



        foreach (DataGridViewRow r in this.dataGridViewECO.Rows)
        {

            if (r.Cells[8].Value != null)
            {

                String stato = r.Cells[8].Value.ToString();


                if (!" Open ".Equals(stato))
                {
                    r.DefaultCellStyle = gray;
                }
                else
                {
                    r.DefaultCellStyle = green;
                }
            }

        }

    }
}
daniele3004
fonte
1

Se você vincular a uma (coleção) de objetos concretos, poderá obtê-lo através da propriedade DataBoundItem da linha. (Para evitar verificar seqüências de caracteres mágicas na célula e usar propriedades "reais" do objeto)

Exemplo de esqueleto abaixo:

DTO / POCO

public class Employee
{
    public int EmployeeKey {get;set;}

    public string LastName {get;set;}

    public string FirstName {get;set;}

    public bool IsActive {get;set;}
}       

Ligação à DataGridView

    private void BindData(ICollection<Employee> emps)
    {
        System.ComponentModel.BindingList<Employee> bindList = new System.ComponentModel.BindingList<Employee>(emps.OrderBy(emp => emp.LastName).ThenBy(emp => emp.FirstName).ToList());
        this.dgvMyDataGridView.DataSource = bindList;
    }       

o manipulador de eventos e a obtenção do objeto concreto (em vez de um DataGridRow e / ou células)

        private void dgvMyDataGridView_RowPrePaint(object sender, DataGridViewRowPrePaintEventArgs e)
        {
            Employee concreteSelectedRowItem = this.dgvMyDataGridView.Rows[e.RowIndex].DataBoundItem as Employee;
            if (null != concreteSelectedRowItem && !concreteSelectedRowItem.IsActive)
            {
                dgvMyDataGridView.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.LightGray;
            }
        }
granadaCoder
fonte
0

Eu normalmente gosto de usar o evento GridView.RowDataBound Event para isso.

protected void OrdersGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.ForeColor = System.Drawing.Color.Red;
    }
}
Edison
fonte
1
Ele é solicitado pelo DatagridView no aplicativo Window. E sua resposta é sobre o GridView of Web.
precisa
0

Funciona no Visual Studio 2010. (Eu tentei e funciona!) Ele pintará sua linha inteira.

  1. Crie um botão para o datagridview.
  2. Crie um CellClickevento e coloque a próxima linha de código dentro dele.

if (dataGridView3.Columns[e.ColumnIndex].Index.Equals(0)    
{
    dataGridView3.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Beige;
}
Levi
fonte
0

Você não mencionou como o valor é alterado. Eu usei funcionalidade semelhante quando o usuário está inserindo valor. ou seja, entrando e saindo do modo de edição.

Usando o evento CellEndEdit do datagridview.

private void dgMapTable_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    double newInteger;

    if (double.TryParse(dgMapTable[e.ColumnIndex,e.RowIndex].Value.ToString(), out newInteger)
    {
        if (newInteger < 0 || newInteger > 50)
        {
            dgMapTable[e.ColumnIndex, e.RowIndex].Style.BackColor = Color.Red; 

            dgMapTable[e.ColumnIndex, e.RowIndex].ErrorText 
                = "Keep value in Range:" + "0 to " + "50";
        }
    }                               
}

Você pode adicionar lógica para limpar a notificação de erro de maneira semelhante.

se no seu caso, se os dados forem carregados programaticamente, o evento CellLeave poderá ser usado com o mesmo código.

Harshal Doshi Jain
fonte
0

Com esse código, você altera apenas a cor de fundo das linhas onde o valor do nome da coluna é nulo, outras linhas ainda são as cores padrão

       foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    if (row.Cells["columnname"].Value != null)
                    {
                        dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.MistyRose;
                    }
                 }
bencemik95
fonte
0

Apenas uma observação sobre a configuração DefaultCellStyle.BackColor... você não pode configurá-lo para qualquer valor transparente, exceto Color.Empty. Esse é o valor padrão. Isso implica falsamente (para mim, pelo menos) que cores transparentes sejam aceitáveis. Eles não são. Cada linha que eu defino como uma cor transparente apenas desenha a cor das linhas selecionadas.

Passei muito tempo batendo minha cabeça contra a parede por causa dessa questão.

ulatekh
fonte
0

Cheguei aqui procurando uma solução para o caso em que não uso a ligação de dados. Nada funcionou para mim, mas eu consegui no final com:

dataGridView.Columns.Clear(); 
dataGridView.Rows.Clear();
dataGridView.Refresh();
Gogu CelMare
fonte
0

Se você é o segundo desenvolvedor mais burro do planeta (eu sendo o mais burro), todas as soluções acima parecem funcionar: CellFormatting, DataSourceChanged e RowPrePaint. Eu prefiro RowPrePaint.

Lutei com isso (por muito tempo) porque precisava substituir meu SelectionBackColor e SelectionForeColor em vez de BackColor e ForeColor, pois eu estava alterando a linha selecionada.

Jess
fonte
0
int counter = gridEstimateSales.Rows.Count;

for (int i = 0; i < counter; i++)
{
    if (i == counter-1)
    {
        //this is where your LAST LINE code goes
        //row.DefaultCellStyle.BackColor = Color.Yellow;
        gridEstimateSales.Rows[i].DefaultCellStyle.BackColor = Color.Red;
    }
    else
    {
        //this is your normal code NOT LAST LINE
        //row.DefaultCellStyle.BackColor = Color.Red;
        gridEstimateSales.Rows[i].DefaultCellStyle.BackColor = Color.White;
    }
}
Amit Patil
fonte