2010-09-08 4 views
9

Ho un DataGrid con associazione a dati con colori di sfondo a righe alternate. Vorrei colorare una cella in modo diverso in base ai dati che contiene. Ho provato la soluzione proposta dalla presente discussioneWPF - Come ottenere una cella da una DataGridRow?

http://wpf.codeplex.com/Thread/View.aspx?ThreadId=51143

Ma,

DataGridCellsPresenter presentatore = GetVisualChild (riga)

restituisce sempre nullo.

Sto usando

public static T GetVisualChild<T>(Visual parent) where T : Visual 
    { 
     T child = default(T); 
     int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < numVisuals; i++) 
     { 
      Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
      child = v as T; 
      if (child == null) 
      { 
       child = GetVisualChild<T>(v); 
      } 
      if (child != null) 
      { 
       break; 
      } 
     } 
     return child; 
    } 

Ma VisualTreeHelper.GetChildrenCount() di un DataGridRow restituisce sempre 0. Ho verificato che DataGridRow non è nullo ed è stato popolato con dati già. Qualsiasi aiuto è apprezzato.

Grazie.

risposta

8

Per prima cosa, non farlo in code-behind. Stai combattendo il quadro con questo modo di fare le cose. WPF è progettato diversamente; devi pensare in termini di come il framework vuole che tu faccia cose. Nel caso di WPF, sono le classi di markup e di markup XAML.

Hai bisogno di due cose per ottenere ciò che si vuole:

  • corretta markup XAML per impostare lo stile del DataGrid
  • implementazione Un IValueConverter di tradurre il valore del testo nella giusta colore di evidenziazione.

Qui va:

XAML In DataGrid

La prima cosa che voglio fare è definire il codice XAML necessaria per lo stile vostre cellule DataGrid. Ecco come si presenta:

<toolkit:DataGrid.CellStyle> 
     <Style TargetType="{x:Type toolkit:DataGridCell}"> 
     <Style.Setters> 
      <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Path=Content.Text, Converter={StaticResource dataGridCellConverter}}" /> 
     </Style.Setters> 
     </Style> 
    </toolkit:DataGrid.CellStyle> 

Che cosa questo sta facendo è la creazione di un legame con il RelativeSource (la DataGridCell) e dirgli di usare il Content.Text della cella come valore da passare al convertitore (dataGridCellConverter).

IValueConverter

La prossima cosa che serve è un'implementazione IValueConverter per determinare in realtà i colori in base al testo della cella:

using System; 
using System.Globalization; 
using System.Windows.Data; 
using System.Windows.Media; 
namespace UserControls.Utility.Converters 
{ 
    public class DataGridCellConverter : IValueConverter 
    { 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value == null) return Colors.White.ToString(); 

     if (value.ToString().ToUpper().Contains("CMS")) return "LIME"; 

     return "ORANGE"; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
    } 
} 

Qui, sto solo cercando il testo "CMS" e colorazione della cella di sfondo; se "CMS" non esiste, restituisce invece il colore arancione.

Specificare Risorse

Ora, è necessario aggiungere il markup nella finestra/UserControl per specificare il convertitore come risorsa appropriata:

<UserControl.Resources> 
    <Converters:DataGridCellConverter x:Key="dataGridCellConverter"/> 
</UserControl.Resources> 

e che dovrebbe farlo! In bocca al lupo.

+0

+1 - risposta molto dettagliata – David

+3

'Nel caso di WPF, sono le classi di markup XAML + convertitore.' - questa è la tua personale percezione –

11

Se si conosce la riga e l'indice della cellula che si desideri accedere, quindi ecco come si può fare in codice:

//here's usage 
var cell = myDataGrid.GetCell(row, columnIndex); 
if(cell != null) 
    cell.Background = Brushes.Green; 

DataGrid Estensione:

public static class DataGridExtensions 
{ 
    public static DataGridCell GetCell(this DataGrid grid, DataGridRow row, int columnIndex = 0) 
    { 
     if (row == null) return null; 

     var presenter = row.FindVisualChild<DataGridCellsPresenter>(); 
     if (presenter == null) return null; 

     var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); 
     if (cell != null) return cell; 

     // now try to bring into view and retreive the cell 
     grid.ScrollIntoView(row, grid.Columns[columnIndex]); 
     cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex); 

     return cell; 
    } 
+1

questa è la vera risposta. –

+0

Sto provando qualcosa del genere ma non sembra funzionare. Puoi controllare questo argomento http://stackoverflow.com/questions/32584353/wpf-control-datagrid-cell-color-change –

+1

È bello se aggiungi i seguenti [metodi] (http://stackoverflow.com/a/25229554/2470362) alla risposta. –