2010-10-21 3 views
0

MISE À JOUR: Nettoyez le sujet et résumez-le.WPF - Liaison de plusieurs valeurs à un code de données

Salut, J'ai un rempli datable, où chaque cellule est une classe comme celui-ci

class CValue{ 
    public object Value; 
    public Brush Quality; 
    private int m_quality; 

    public override String toString(){ 
      return Value.toString(); 
    } 
} 

Mon DataGrid lie le datable, et cela fonctionne bien. Mais mon but est de changer la couleur de fond de la cellule en fonction de la valeur de qualité.

Je compte tu utiliser DataTemplate mais ne sais pas comment ça fonctionne du tout ...

<dg:DataGrid Name="DataGridResult" IsReadOnly="True" AutoGenerateColumns="False" 
    BorderThickness="1" BorderBrush="{DynamicResource clBLACK}" 
    CanUserReorderColumns="False" 
    ItemsSource="{Binding Path=Result}"> 
      <dg:DataGrid.Resources> 
      <Style TargetType="{x:Type dg:DataGridCell}"> 
       <Style.Setters> 
        <Setter Property="Background" Value="{Binding [1].Quality}"/> 
       </Style.Setters> 
      </Style> 
      </dg:DataGrid.Resources>   
      <dg:DataGrid.ItemTemplate> 
      <DataTemplate> 
       <dg:DataGridCell> 
        </dg:DataGridCell> 
      </DataTemplate> 
      </dg:DataGrid.ItemTemplate> 
</dg:DataGrid> 

En fait, si la valeur du compositeur de l'arrière-plan est réglé sur « Blue », toutes les cellules sont bleui, donc c'est bon, mais je ne peux pas trouver un moyen de le lier à ma propriété. le [1] semble retourner la colonne 1 de la ligne ...

Comment définir la cellule dynamiquement? Parce que j'ai un nombre dynamique de colonnes mais tout le type CValue.

+0

Vous ne voulez pas vraiment avoir un pinceau pour la qualité, n'est-ce pas? Bien sûr, vous pouvez avoir mais je dirais que son plus propre à utiliser un convertisseur ou DataTrigger pour la liaison de valeur. – Almund

+0

Yeap mais en fait j'ai besoin de mettre des valeurs et des couleurs dans la configuration, donc dans le code. Je suis à la recherche de la manière la plus simple :) – ykatchou

+0

Ok, cus dans ce cas vous n'avez pas vraiment besoin de convertisseurs, juste lier à la qualité directement Background = {Binding Quality}. Aimeriez-vous un petit exemple de l'application avec .cs qui démontre ce que je pense que vous essayez de faire? – Almund

Répondre

1

Ok. Donc, pour un exemple toute databinding au pinceau du modèle au lieu d'utiliser des convertisseurs, des styles, etc. Pour le -code cs suivant:

class CValue 
{ 
    public string Value { get; set; } // Notice we use properties for binding and not fields 
    public Brush Quality { get; set; } // Notice we use properties for binding and not fields 
    private int m_quality; 

    public override String ToString() 
    { 
     return Value.ToString(); 
    } 
} 

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 

     // Databind the list 
     myGrid.ItemsSource = new List<CValue> 
          { 
           new CValue 
            { 
             Value = "First", 
             Quality = new SolidColorBrush(Color.FromArgb(255, 0, 255, 255))}, 
           new CValue 
            { 
             Value = "Second", 
             Quality = new SolidColorBrush(Color.FromArgb(255, 255, 0, 255)) 
            }, 
           new CValue 
            { 
             Value = "Third", 
             Quality = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255)) 
            } 
          }; 
    } 
} 

Vous utiliseriez une XAML pour le rowstyle (notez le TargetType sur le style et le AutoGenerateColumns="false") pour lier la couleur de la ligne et la valeur:

<Controls:DataGrid x:Name="myGrid" AutoGenerateColumns="False"> 

    <Controls:DataGrid.RowStyle> 
     <Style TargetType="{x:Type Controls:DataGridRow}"> 
      <Setter Property="Background" Value="{Binding Quality}" /> 
     </Style> 
    </Controls:DataGrid.RowStyle> 

    <Controls:DataGrid.Columns> 
     <Controls:DataGridTemplateColumn Header="Value"> 
      <Controls:DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <Label Content="{Binding Value}" /> 
       </DataTemplate> 
      </Controls:DataGridTemplateColumn.CellTemplate> 
     </Controls:DataGridTemplateColumn> 
    </Controls:DataGrid.Columns> 

</Controls:DataGrid> 

Hope it helps!

+0

Salut, merci beaucoup, je ne suis pas vraiment loin je pensais, j'ai cette erreur: Erreur System.Windows.Data Erreur de chemin BindingExpression: propriété 'Quality' introuvable sur 'objet' '' DataRowView ' (HashCode = 9847817) '.BindingExpression: Path = Qualité; DataItem = 'DataRowView' (HashCode = 9847817); l'élément cible est 'DataGridRow' (Name = ''); La propriété target est 'Background' (type 'Brush'), peut-être parce que je lie une datable où chaque cellule est un CValue – ykatchou

+0

Vous liez toujours la mauvaise chose à ItemSource, vous ne voulez pas lier la DataGrid mais une liste. Où définissez-vous DataContext? – Almund

+0

Donc, je peux essayer quelque chose comme ItemsSource = {Binding Result.Rows}? – ykatchou

1

Vous devez utiliser la classe DataTemplateSelector pour effectuer cette logique. Le scénario est décrit ci-dessous:

  • Créer l'ensemble de DataTemplates;
  • Dériver à partir de DataTemplateSelector Class et implémenter il la logique de sélection appropriée DataTemplate comme décrit dans l'article MSDN;
  • Définissez votre DataTemplateSelector personnalisé comme ressource spécifiant l'attribut x:Key;
  • Liez l'objet nécessaire à la ressource DataTemplateSelector définie.

MISE À JOUR

L'approche supérieure fonctionne mieux lorsque vous avez besoin de cellules complètement nouvelle conception que les gars mentionnés dans le commentaire.

Donc, pour cette tâche, vous devez créer votre convertisseur, définir comme une ressource et l'ajouter à votre reliure:

<!--somewhere in resources--> 
<QualityToBackgroundConverter x:Key="qualityToBackgroundConverter "/> 

liant alors ressemblera:

Background="{Binding Quality, Converter={StaticResource qualityToBackgroundConverter }}" 

et enfin le convertisseur :

[ValueConversion(typeof(Quality), typeof(Brush))] 
public class QualityToBackgroundConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value != null) 
     { 
      Quality quality = (Quality)value;   
      switch (quality) 
      { 
       case 0: return Brushes.Red; 
       case 1: return Brushes.Yellow; 
       case 2: return Brushes.Green; 
       default: return Brushes.Transparent; 
      } 
     } 
     return Brushes.Transparent; 
    } 

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

Il est quelque peu unnessesary de remplacer le modèle entier juste pour changer l'arrière-plan ne pensez-vous? L'utilisation d'un style ou d'un convertisseur devrait être plus pratique. – Almund

+0

J'ai un peu peur de DataTemplateSelector, ça semble trop, n'est-ce pas? – ykatchou

+0

Voir mise à jour avec le convertisseur. –

1

Une bonne façon de faire cela qui conserve la couleur visible dans le XAML est utiliser un style avec une liaison à la qualité. Nous avons mis ce style dans le resourcedictionary ci-dessus le modèle, comme dans mon cas dans le DataGrid.Resources.

<Controls:DataGrid> 
    <Controls:DataGrid.Resources> 
     <Style TargetType="{x:Type Controls:DataGridCell}"> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding Quality}" Value="0"> 
        <Setter Property="Background" Value="Red" /> 
       </DataTrigger> 

       <DataTrigger Binding="{Binding Quality}" Value="0"> 
        <Setter Property="Background" Value="Blue" /> 
       </DataTrigger> 

      </Style.Triggers> 
     </Style> 
    </Controls:DataGrid.Resources> 
    <Controls:DataGrid.ItemTemplate> 
     <DataTemplate> 
      <Controls:DataGridCell> 
      </Controls:DataGridCell> 
     </DataTemplate> 
    </Controls:DataGrid.ItemTemplate> 
</Controls:DataGrid> 

Mise à jour:

Pour pouvoir DataBind les valeurs ou quel que soit utiliser un convertisseur comme celui-ci:

[ValueConversion(typeof(int), typeof(SolidColorBrush))] 
public class QualityToColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     // Cast value 
     int intValue = (int) value; 

     if (intValue == 1) 
      return new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)); 

     return new SolidColorBrush(Color.FromArgb(255, 0, 0, 255)); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException("TwoWay binding not supported!"); 
    } 
} 

Bind dans le XAML comme le follwing:

<Window.Resources> 
    <WpfApplication1:QualityToColorConverter x:Key="ColorConverter" /> 
</Window.Resources> 

<Controls:DataGridCell Background="{Binding Quality, Converter={StaticResource ColorConverter}}"> 
</Controls:DataGridCell> 
+0

Je pense qu'il est plus facile pour moi de faire un "convertisseur" dans ma classe CValue et de me lier directement à la couleur car j'utilise le masque de bits pour vérifier la qualité ... Dois-je utiliser un datatemplate? – ykatchou

+0

Mis à jour avec un exemple de convertisseur, donnez un commentaire si vous avez besoin d'aide pour tout ajustement. – Almund

+0

En remarque, j'ai remarqué que votre qualité est une instance 'objet', cela signifie que l'attribut ValueConversion devrait être typeof (objet), typeof (SolidColorBrush) mais je pense que vous devriez plutôt taper la qualité car cela améliorerait votre compilation vérification d'erreur de temps. – Almund