Come impostare lo sfondo di una cella datagrid durante l’evento AutoGeneratingColumn in base al suo valore?

Sto ancora combattendo con la manipolazione di sfondi di celle, quindi sto facendo una nuova domanda.

Un utente “HB” ha scritto che posso effettivamente impostare lo stile della cella durante l’evento AutoGeneratingColumn – Cambia il colore della cella DataGrid in base ai valori . Il problema è che non sono sicuro di come farlo.

Cosa voglio: imposta colors di sfondo diversi per ciascuna cella in base al suo valore. Se il valore è null voglio anche che non sia cliccabile (immaginabile per la messa a fuoco).

Cosa ho / sto cercando di fare:

 private void mydatagrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { foreach (Cell cell in e.Column) { if (cell.Value < 1) { cell.Background = Color.Black; cell.isFocusable = false; } else { cell.Background = Color.Pink; } } } 

Questo è solo lo pseudocodice. È qualcosa di simile a questo durante la generazione automatica delle colonne e, in tal caso, come posso modificare il mio codice in modo che sia valido?

Ho letto dei convertitori di valore, ma voglio sapere se è in qualche modo ansible a livello di codice, senza scrivere XAML.

Per favore, comprendi che sono ancora un principiante di C # / WPF / DataGrid.

Soluzione part1:

Ho usato la risposta che ho accettato. Mettilo dentro

                      

E fatto per esso un convertitore MultiBinding così posso anche impostare il colore di sfondo per le celle selezionate.

Problema:

Ora devo solo risolvere il problema dell’impostazione delle celle vuote. Qualche suggerimento?

       

Questo non funziona. Ho avuto stringhe vuote nelle celle vuote, ma sono piene di “null” quindi dovrebbe funzionare, giusto? O cosa sto sbagliando: | ?

Soluzione parte 2:

Quindi il codice sopra non funzionerà finché il valore della cella è un “TextBox”, quindi ho deciso di trovare un altro modo per affrontarlo che può essere trovato nella mia risposta qui: https://stackoverflow.com/a/16673602 / 2296407

Grazie per aver cercato di aiutarmi 🙂

Posso proporre due diverse soluzioni per la tua domanda: la prima è “code-behind-style” (che stai chiedendo ma personalmente penso che non sia l’approccio giusto in WPF) e più stile WPF (che è più complicato ma mantiene il codice -behind clean e utilizza stili, trigger e convertitori)

Soluzione 1. Gestione degli eventi e logica code-behind per la colorazione

Innanzitutto, l’approccio che hai scelto non funzionerà direttamente: l’evento AutoGeneratingColumn deve essere utilizzato per alterare l’ intero aspetto della colonna , non in base alla cella per cella. Quindi può essere usato, per esempio, attaccando lo stile corretto a tutta la colonna basandosi sul suo indice di visualizzazione o sulla sua proprietà legata.

In generale, per la prima volta in cui viene generato l’evento, il tuo datagrid non avrà alcuna riga (e di conseguenza – le celle). Se hai davvero bisogno di prendere l’evento, considera il tuo evento DataGrid.LoadingRow. E non sarai in grado di ottenere le cellule così facilmente 🙂

Quindi, cosa fai: gestisci l’evento LoadingRow, ottieni la riga (ha la proprietà Item che contiene (sorprendentemente :)) l’object associato, ottieni l’object associato, fai tutti i calcoli necessari, ottieni la cella che devi modificare e finalmente alterare lo stile della cellula bersaglio.

Ecco il codice (come elemento utilizzo un object campione con la proprietà int “Value” che utilizzo per colorare).

XAML

   

.CS

  private void DataGrid_OnLoadingRow(object sender, DataGridRowEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => AlterRow(e))); } private void AlterRow(DataGridRowEventArgs e) { var cell = GetCell(mygrid, e.Row, 1); if (cell == null) return; var item = e.Row.Item as SampleObject; if (item == null) return; var value = item.Value; if (value < = 1) cell.Background = Brushes.Red; else if (value <= 2) cell.Background = Brushes.Yellow; else cell.Background = Brushes.Green; } public static DataGridRow GetRow(DataGrid grid, int index) { var row = grid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow; if (row == null) { // may be virtualized, bring into view and try again grid.ScrollIntoView(grid.Items[index]); row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromIndex(index); } return row; } public static T GetVisualChild(Visual parent) where T : Visual { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { var v = (Visual)VisualTreeHelper.GetChild(parent, i); child = v as T ?? GetVisualChild(v); if (child != null) { break; } } return child; } public static DataGridCell GetCell(DataGrid host, DataGridRow row, int columnIndex) { if (row == null) return null; var presenter = GetVisualChild(row); if (presenter == null) return null; // try to get the cell but it may possibly be virtualized var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); if (cell == null) { // now try to bring into view and retreive the cell host.ScrollIntoView(row, host.Columns[columnIndex]); cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); } return cell; } 

Soluzione 2. Stile WPF

Questa soluzione utilizza il code-behind solo per le conversioni value-to-color (assumendo che quella logica di colorazione sia più complessa del confronto di uguaglianza – in tal caso è ansible utilizzare i trigger e non fare confusione con i convertitori).

Cosa fai: imposta la proprietà DataGrid.CellStyle con lo stile che contiene un trigger di dati, che controlla se la cella si trova all’interno di una colonna desiderata (in base al suo DisplayIndex) e se lo è: applica lo sfondo attraverso un convertitore.

XAML

          

.CS

 public class ValueColorConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var str = value as string; if (str == null) return null; int intValue; if (!int.TryParse(str, out intValue)) return null; if (intValue < = 1) return Brushes.Red; else if (intValue <= 2) return Brushes.Yellow; else return Brushes.Green; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } 

UPD: Se è necessario colorare l'intero datagrid, XAML è molto più semplice (non è necessario utilizzare i trigger). Usa il seguente CellStyle:

     

Quello che intendevo è che puoi impostare la proprietà CellStyle della colonna, non puoi manipolare le celle direttamente perché non sono disponibili in questo evento. Lo stile può contenere la tua logica condizionale sotto forma di DataTriggers (avrà bisogno di un convertitore perché hai “meno di” e non è uguale) e Setters .

Inoltre, se la logica non è specifica delle colonne, è ansible impostare lo stile globalmente sulla griglia stessa. Il punto di utilizzo dell’evento sarebbe manipolare le proprietà della colonna a cui non si può accedere diversamente.

Non sono sicuro se questa proprietà (Cell.Style) sia disponibile nel tuo Datagrid WPF. Probabilmente esistono alcune alternative nel tuo caso. Ha funzionato per datagrid di WinForms.

  cell.Style.BackColor = System.Drawing.Color.Black;