2015-11-16 1 views
0

Je travaille sur un projet de code important qui a été écrit par quelqu'un d'autre, j'essaie donc d'ajouter un changement avec le moins d'impact possible. Il utilise System.Windows.Controls.DataVisualization.Toolkit pour créer un graphique linéaire avec un nombre de LineSeries combiné en un MultiChart, qui est une classe que mon prédécesseur a créée lui-même.Boucler les couleurs dans la reliure

Les lignes sont toutes de la même couleur. On m'a demandé de leur faire des couleurs différentes. Ou plus d'une couleur vraiment. Le nombre de lignes n'est pas constant, alors j'espérais faire défiler une liste de couleurs. Alors tout ce que je devrais faire est de faire un assez grand pour couvrir la plupart des cas.

En raison de l'incohérence du numéro de ligne, je ne peux pas définir explicitement chaque couleur. En outre, le MultiChart a une propriété SeriesSource, qui est un ObservableCollection de plusieurs LineSeries qui est à son tour un ObservableCollection de points de données, qui est défini via la liaison à ViewModel. Donc, je pense que je vais devoir lier la couleur à une valeur en dehors du xaml. Comme c'est un travail lié à la vue, j'imagine que le code derrière serait un emplacement valide pour mon changement de couleur, mais j'ai été incapable de trouver une solution qui fonctionne là-bas.

J'ai examiné un certain nombre de questions sur SO et ailleurs et aucune d'entre elles n'a vraiment fonctionné, avec ou sans considération pour le modèle MVVM. Je cherche juste une solution de travail que je peux retravailler dans MVVM, mais des points bonus si c'est aussi une bonne pratique. J'ai travaillé avec WPF pendant un moment maintenant, et pour une raison quelconque, je ne peux pas me concentrer entièrement sur la liaison de données, ce qui est probablement la raison pour laquelle j'ai échoué avec la plupart des solutions que j'ai trouvées. Malgré cela, je pense que je me suis rapproché avec ceci:

Dans <UserControl.Resources>

<local:LocalColorConverter x:Key="MyColorConverter"/> 

<Style x:Key="dataPointStyle" TargetType="{x:Type charting:LineDataPoint}"> 
     <Setter Property="Background" Value="{Binding Path=DataContext.ColorCount, 
               RelativeSource={RelativeSource AncestorType=local:MultiChart, Mode=FindAncestor}, 
               Converter={StaticResource MyColorConverter}}"/> 
</Style> 

En LocalColorConverter.cs:

class LocalColorConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     int count = (int)value; 
     //SolidColorBrush returnBrush = new SolidColorBrush(); 
     SolidColorBrush color = new SolidColorBrush(); 
     switch (count % 5) 
     { 
      case 0: 
       color.Color = Colors.Blue; 
       break; 
      case 1: 
       color.Color = Colors.Green; 
       break; 
      case 2: 
       color.Color = Colors.Red; 
       break; 
      case 3: 
       color.Color = Colors.Purple; 
       break; 
      case 4: 
       color.Color = Colors.Yellow; 
       break; 
     } 
     return color; 
    } 

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

Je sais que ce n'est pas très bon dans la pratique. Il s'appuie sur une valeur ColorCount à partir du viewmodel, qui est des informations pertinentes pour la vue. Mauvais MVVM, mais j'essaie juste de le faire fonctionner avant de le faire correspondre au modèle.

En outre, il ne fonctionne pas vraiment tel quel, car ColorCount n'est jamais modifié. Il est initialement défini sur 0 dans le viewmodel. Si je devais continuer dans cette voie, je voudrais incrémenter la valeur de ColorCount afin que les couleurs changent chaque fois que le convertisseur est utilisé.

J'ai essayé de faire ((int)value)++ avant le retour du convertisseur, mais cela n'a pas fonctionné. Je ne le pensais pas, mais cela vous donne une idée de ce que je cherche.

Sinon, je pense que ma meilleure solution est de faire cette opération dans le code derrière. Mais je ne sais pas où/comment le faire. Il devrait changer la couleur quand le UserControl obtient un nouveau LineSeries. Le code actuel a un gestionnaire d'événements LineSeries_Loaded implémenté, mais la couleur n'est pas définie dans la ligne, elle est définie pour chaque point de la ligne. J'ai donc besoin d'incrémenter mon compteur de couleur à chaque ligne, puis d'utiliser le compte à chaque point pour déterminer sa couleur.

J'ai essayé ceci, mais je n'arrive pas à trouver la propriété Background de cette façon. Notez que chart est le nom donné à l'objet MultiChart.

private void LineSeries_Loaded(object sender, RoutedEventArgs e) 
    { 
     foreach(LineSeries line in chart.Series.Cast<LineSeries>()) 
     { 
      foreach(LineDataPoint point in line) 
      { 

      } 
     } 
    } 

Mais j'obtiens l'erreur que cette ligne n'a pas GetEnumerator publique.

Des suggestions?

+0

C'est une bonne boîte à outils wpf? N'a-t-il pas de support pour définir la propriété de dépendance 'Palette' sur une StaticResource et attribuer des couleurs du type [this] (http://stackoverflow.com/questions/3703301/changing-default-colors-of-wpftoolkit-chart -contrôle)? Été un certain temps depuis que j'ai dinked avec lui donc je peux me tromper. –

+0

J'ai essayé un certain nombre d'options avec 'Palette'. Le problème est que j'ai besoin d'une 'Palette' pour le' MultiChart', qui n'a pas cette propriété. C'est une collection de graphiques. Et je ne peux pas imaginer créer cette propriété serait facile, et j'ai eu beaucoup de mal à faire des propriétés de dépendance. Je ne saurais pas par où commencer. – MichaelN

Répondre

0

Eh bien, on dirait que l'écriture de la question a fait couler mon énergie créatrice. Je me suis souvenu que j'avais essayé de placer le style setter dans le code derrière, mais vous ne pouvez pas modifier le style au moment chargé. Mais je viens de réaliser que je peux changer de style à tout moment. Je fis donc ces:

<Style x:Key="blueDataPointStyle" TargetType="{x:Type charting:LineDataPoint}" BasedOn="{StaticResource dataPointStyle}"> 
    <Setter Property="Background" Value="Blue"/> 
</Style> 

<Style x:Key="redDataPointStyle" TargetType="{x:Type charting:LineDataPoint}" BasedOn="{StaticResource dataPointStyle}"> 
    <Setter Property="Background" Value="Red"/> 
</Style> 

<Style x:Key="greenDataPointStyle" TargetType="{x:Type charting:LineDataPoint}" BasedOn="{StaticResource dataPointStyle}"> 
    <Setter Property="Background" Value="Green"/> 
</Style> 

Ensuite, dans le code derrière:

private void UserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     int count = 0; 
     foreach (LineSeries line in chart.Series) 
     { 
      switch (count % 3) 
      { 
       case 0: 
        line.DataPointStyle = Resources["blueDataPointStyle"] as Style; 
        break; 
       case 1: 
        line.DataPointStyle = Resources["redDataPointStyle"] as Style; 
        break; 
       case 2: 
        line.DataPointStyle = Resources["greenDataPointStyle"] as Style; 
        break; 
      } 
      count++; 

     } 
    } 

Il travaille! Eh bien, la plupart du temps, toutes les autres lignes sont groupées en une, donc j'ai encore du travail à faire. Mais c'est la réponse à ce que j'ai demandé. De plus, il semble convenir à MVVM. Il s'avère que je n'ai pas besoin de liaison (probablement pourquoi j'ai été capable de le faire). Mais je suis toujours intéressé par d'autres idées. Je voudrais un bon exemple de liaison.