Jak zmienić kolor wiersza w Datagridview?

143

Chciałbym zmienić kolor konkretnego wiersza w moim datagridview. Wiersz należy zmienić na czerwony, gdy wartość kolumny kolumna 7 jest mniejsza niż wartość w kolumnie kolumna 10. Jakieś sugestie, jak to zrobić?

EB.
źródło

Odpowiedzi:

192

Musisz przejrzeć wiersze w datagridview, a następnie porównać wartości z kolumn 7 i 10 w każdym wierszu.

Spróbuj tego:

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
źródło
1
Dziękuję za pomoc Ricardo. Wypróbowałem kod, który zasugerowałeś. Nadal nie mogę zmusić go do pracy. Czy możesz spojrzeć na ten kod i powiedzieć mi, gdzie popełniłem błąd? Jestem początkującym studentem C #. Jestem pewien, że po prostu nie napisałem poprawnie kodu porównawczego. foreach (wiersz DataGridView w vendorsDataGridView.Rows) {if (row.Cells [7] .Value is <row.Cells [10] .Value) {dataGridViewTextBoxColumn7.DefaultCellStyle.BackColor = red; } } Doceniam twoją pomoc. EB
EB.
EB Dodałem nowy kod na podstawie podanego przez Ciebie kodu. Twój sintax był trochę wyłączony, wypróbuj kod, który właśnie dodałem powyżej.
Ricardo Sanchez
2
Ricardo. Zmieniłem .text na .value i zmieniłem na DefaultCellstyle.Backcolor = color.red i kod działał !!! Dziękuję za Twój czas! EB
EB.
60

Właśnie badałem ten problem (więc wiem, że to pytanie zostało opublikowane prawie 3 lata temu, ale może komuś pomoże ...), ale wydaje się, że lepszą opcją jest umieszczenie kodu wewnątrz RowPrePaint wydarzenia, aby nie muszą przejść każdy wiersz, tylko te, które zostaną pomalowane (więc będzie działać znacznie lepiej na dużej ilości danych:

Dołącz do wydarzenia

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

Kod zdarzenia

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;
    }
}
eden
źródło
3
Naprawdę podoba mi się sposób, w jaki łapiesz problem u źródła, zamiast czekać, aż wszystko zostanie pomalowane. To bardzo „nieszablonowe” podejście. Większość ludzi wolałaby po prostu ponownie przejść przez każdy wiersz ...
bird2920
Oprócz tego, że jest dużo szybszy, pomaga to również zrobić to we właściwym czasie. Miałem problem z tym, że moje rzędy się nie pokolorowały, prawdopodobnie dlatego, że ustawiłem kolor w złym momencie. Takie podejście gwarantuje, że nastąpi to we właściwym czasie.
sanderd17
1
To działa świetnie. Również po odpowiednim posortowaniu odświeżenia.
macmuri
24

Szukasz CellFormattingwydarzenia.
Oto przykład.

SLaks
źródło
2
Różnica w tym podejściu polega na tym, że każda pojedyncza komórka zostanie porównana, a nie tylko jedna. Może to być problem z wydajnością, jeśli masz kilkaset ogniw.
Ricardo Sanchez
21

Miałem również problem ze zmianą koloru tekstu - nigdy nie widziałem zmiany koloru.

Dopóki nie dodałem kodu, aby zmienić kolor tekstu wydarzenia DataBindingsCompletedlaDataGridView . Potem zadziałało.

Mam nadzieję, że pomoże to ludziom, którzy borykają się z tym samym problemem.

user1614017
źródło
kolor tekstu nie zmienia się w przypadku zastąpienia onLoad (..) lub zdarzenia. DataBindingsComplete jest znacznie lepszym miejscem do ustawiania kolorów wierszy.
Tymoteusza
13

Coś podobnego do następującego ... zakładając, że wartości w komórkach są liczbami całkowitymi.

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

nieprzetestowane, więc przepraszamy za każdy błąd.

Jeśli znasz konkretny wiersz, możesz pominąć iterację:

if (myDGV.Rows[theRowIndex].Cells[7].Value < myDGV.Rows[theRowIndex].Cells[10].Value)
{
  dgvr.DefaultCellStyle.ForeColor = Color.Red;
}
Demi
źródło
Dziękuję za pomoc. Twoja sugestia jest najbliższa mi do rozwiązania problemu. Ale ciągle pojawia się błąd informujący, że „Wartość” nie istnieje w kontekście lub „Komórki” nie istnieją w kontekście. Próbuję to rozgryźć ...
EB.
ta linia kodu (dgvr.Cells [7] .Value <dgvr.Cells [10] .Value) daje mi teraz ten błąd Operator '<' nie może być zastosowany do operandów typu 'obiekt' i 'obiekt'
EB.
W takim razie prześlij je na Integer. :-) coś takiego: Convert.ToInt32 (dvgr.Cells [7] .Value) <Convert.ToInt32 (dgvr.Cells [10] .Value)
Demi
8

Niektórzy ludzie lubią używać Paint, CellPaintinglub CellFormattingzdarzenia, ale pamiętać, że zmiana stylu w tych zdarzeń powoduje wywołań rekurencyjnych. Jeśli DataBindingCompletego użyjesz , uruchomi się tylko raz. Argumentem za CellFormattingjest to, że jest wywoływana tylko w widocznych komórkach, więc nie musisz formatować niewidocznych komórek, ale formatujesz je wielokrotnie.

Denise Skidmore
źródło
5

Można zmienić Backcolorwiersz po wierszu używając swojego condition.and to wywołanie funkcji po zastosowaniu Datasourceod DatagridView.

Oto funkcja do tego. Po prostu skopiuj to i umieść późniejDatabind

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
źródło
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;                   
    //    }
    //}
}
Krzysztof
źródło
2

To jest moje rozwiązanie do zmiany koloru na dataGridView z 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
źródło
1

Jeśli utworzysz powiązanie z (kolekcją) konkretnych obiektów, możesz pobrać ten konkretny obiekt za pośrednictwem właściwości DataBoundItem wiersza. (Aby uniknąć sprawdzania magicznych ciągów w komórce i używania „rzeczywistych” właściwości obiektu)

Przykład szkieletu poniżej:

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;}
}       

Powiązanie z 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;
    }       

następnie program obsługi zdarzeń i pobieranie konkretnego obiektu (zamiast DataGridRow i / lub komórek)

        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
źródło
0

Zazwyczaj lubię używać do tego zdarzenia zdarzenia GridView.RowDataBound.

protected void OrdersGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        e.Row.ForeColor = System.Drawing.Color.Red;
    }
}
Edison
źródło
1
Zostaje poproszony o DatagridView w aplikacji Windows. Twoja odpowiedź dotyczy widoku GridView sieci.
Pratik 1020
0

Działa na Visual Studio 2010. (Próbowałem i działa!) Pomaluje cały wiersz.

  1. Utwórz przycisk dla datagridview.
  2. Utwórz CellClickwydarzenie i umieść w nim następną linię kodu.

if (dataGridView3.Columns[e.ColumnIndex].Index.Equals(0)    
{
    dataGridView3.Rows[e.RowIndex].DefaultCellStyle.BackColor = Color.Beige;
}
Levi
źródło
0

Nie wspomniałeś, jak zmienia się wartość. Użyłem podobnej funkcji, gdy użytkownik wprowadza wartość. tj. wchodzenie i wychodzenie z trybu edycji.

Korzystanie ze zdarzenia CellEndEdit 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";
        }
    }                               
}

W podobny sposób możesz dodać logikę do usuwania powiadomień o błędach.

jeśli w twoim przypadku, jeśli dane są ładowane programowo, to zdarzenie CellLeave może być użyte z tym samym kodem.

Harshal Doshi Jain
źródło
0

Za pomocą tego kodu zmieniasz tylko kolor tła wierszy, w których wartość kolumny jest równa null, pozostałe wiersze są nadal kolorami domyślnymi.

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

Tylko uwaga na temat ustawienia DefaultCellStyle.BackColor... nie możesz ustawić dla niego żadnej przezroczystej wartości oprócz Color.Empty. To jest wartość domyślna. To fałszywie implikuje (przynajmniej dla mnie), że kolory przezroczyste są w porządku. Oni nie są. Każdy wiersz ustawiony na przezroczysty kolor rysuje tylko kolor wybranych wierszy.

Spędziłem o wiele za dużo czasu, uderzając głową o ścianę w tej sprawie.

ulatekh
źródło
0

Wylądowałem tutaj, szukając rozwiązania w przypadku, gdy nie używam wiązania danych. Nic mi nie pomogło, ale w końcu dostałem:

dataGridView.Columns.Clear(); 
dataGridView.Rows.Clear();
dataGridView.Refresh();
Gogu CelMare
źródło
0

Jeśli jesteś drugim najgłupszym programistą na świecie (ja jestem najgłupszy), wszystkie powyższe rozwiązania wydają się działać: CellFormatting, DataSourceChanged i RowPrePaint. Wolę RowPrePaint.

Zmagałem się z tym (zbyt długo), ponieważ musiałem zastąpić moje SelectionBackColor i SelectionForeColor zamiast BackColor i ForeColor, gdy zmieniałem wybrany wiersz.

Pęto
źródło
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
źródło