2010-09-02 5 views
2

En utilisant le DataGrid WPF j'ai besoin de changer diverses propriétés d'affichage et connexes d'un DataGridCell - tels que Foreground, FontStyle, IsEnabled et ainsi de suite - basé sur la valeur pertinente de la propriété de l'objet de la cellule.Liaison d'une propriété d'objet de cellule à un DataGridCell dans WPF DataGrid

Maintenant, c'est facile à faire dans le code, par exemple (en utilisant une collection Observable de ObservableDictionaries):

var b = new Binding("IsLocked") { Source = row[column], Converter = new BoolToFontStyleConverter() }; 
    cell.SetBinding(Control.FontStyleProperty, b); 

et fonctionne très bien, mais je ne vois pas comment faire en XAML depuis que je ne trouve pas façon de définir Chemin à la propriété d'un objet de cellule.

Une tentative XAML est:

<Setter Property="FontStyle"> 
    <Setter.Value> 
     <MultiBinding Converter="{StaticResource IsLockedToFontStyleConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"> 
       <Binding /> 
       <Binding RelativeSource="{x:Static RelativeSource.Self}"/> 
     </MultiBinding> 
    </Setter.Value> 
</Setter> 

mais il n'y a pas de liaison à la IsLocked propriété

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
{ 
    var row = (RowViewModel) values[0]; 
    var cell = (DataGridCell) values[1]; 
    if (cell != null && row != null) 
    { 
     var column = DataGridMethods.GetColumn(cell); 
     return row[column].IsLocked ? "Italic" : "Normal"; 
    } 

    return DependencyProperty.UnsetValue; 
} 

S'il vous plaît noter qu'une version précédente est revenu ligne [col] .IsLocked et définir le FontStyle en utilisant un DataTrigger mais un objet retourné n'est pas databound.

Notez, bien entendu, que l'application ne sait pas ce que sont les colonnes au moment du design. Enfin, DataTable est beaucoup trop inefficace pour mes besoins mais je serais intéressé de voir comment cela se fait avec DataTables de toute façon, si une telle solution existe pour eux, cela pourrait être utile ailleurs (bien que je préfère utiliser des collections).

Sûrement c'est un problème commun et je suis un noobie de WPF essayant d'aller tout MVVM sur mon projet, mais ce problème me retient en ce qui concerne l'utilisation du DataGrid de WPF.

Répondre

4

Eh bien voici la solution la plus simple que j'ai trouvée. (En fait, je l'avais avant que je posté cette question et l'autre, mais a été gêné par une telle solution.Après avoir entendu rien d'autre ici et juste au cas où quelqu'un d'autre est confronté au même problème, je pensais le partager.)

Placez une référence à l'objet de cellule dans la propriété Tag DataGridCell. Je le fais avec une combinaison de XAML et d'un code de liaison à l'intérieur d'un convertisseur comme suit:.

et

public class CellViewModelToTagConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var row = values[0] as RowViewModel; 
     var cell = values[1] as DataGridCell; 
     if (row != null && cell != null) 
     { 
      var column = DataGridMethods.GetColumn(cell); 
      // hack within hack!!! (using tag way is itself a hack?) 
      var b = new Binding("Self") {Source = row[column]}; 
      cell.SetBinding(FrameworkElement.TagProperty, b); 
      //... 
      //return row[column]; 
      return DependencyProperty.UnsetValue; 
     } 
     return DependencyProperty.UnsetValue; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

Vous pouvez dire ce que je pense de cette solution par mes commentaires à l'intérieur du convertisseur (J'ai dû ajouter une propriété Self à l'objet Cell et rendre Self = this dans le constructeur).

Cependant, il permet à mon codage Datagrid d'être entièrement MVVM - si vous acceptez que ce que j'ai fait dans le convertisseur est compatible avec MVVM. En tout cas ça marche! Ainsi, je peux tout voir et tout gérer à partir de XAML, par exemple en contrôlant une telle liaison sur certaines colonnes en plaçant le XAML dans la colonne correspondante cellstyles (ce qui n'est pas le cas via DataGrid.CellStyle).

Quoi qu'il en soit, un exemple d'utilisation est

<Style.Triggers> 
     <DataTrigger Value="true" Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag.IsLocked}"> 
      <Setter Property="FontStyle" Value="Italic"/> 
      <Setter Property="IsEnabled" Value="False"/> 
     </DataTrigger> 
</Style.Triggers> 

Au niveau XAML est à la fois simple et à mon humble avis élégant (en particulier pour les différentes info-bulles et les popups pour lesquels je fais une utilisation intensive des propriétés de l'objet cellulaire). Cependant, je suis sûr qu'il y a une meilleure façon de faire cela, n'est-ce pas?

J'espère que tout cela s'en va lorsque je peux utiliser Net 4.0 et des objets dynamiques, mais pour ce projet, je ne peux pas.

+0

merci pour le partage. C'est très moche, mais c'est aussi de loin la solution la plus simple que j'ai vu jusqu'ici pour ce problème ... – David

+0

Je réalise que c'est un vieux post mais j'ai trouvé que je peux simplement mettre 'row row [column];' dans le bloc if .. et ça marche. Que fait le code ci-dessus différemment (c'est-à-dire créer une liaison)? –

+0

La liaison ne se produit pas sauf dans le convertisseur. Si vous ne liez pas dans le convertisseur et ne renvoyez que la ligne [column], puis mettez à jour la cellule référencée, elle n'est pas liée et vous ne voyez aucune mise à jour dans le DataGrid. J'ai une solution beaucoup mieux et non hacky, bien que le XAML soit plus compliqué. Je vais l'ajouter ici quand j'ai le temps. – Martino

Questions connexes