2010-08-16 12 views
1

J'essaie d'ajouter une liaison série à l'ensemble de contrôles graphiques Visifire. À cette fin, j'ai créé une propriété de dépendance SeriesSource de l'heure DataSeriesCollection. Ceci est lié à l'extrémité avant à l'aide:La liaison WPF ne s'applique pas à la cible après l'initialisation

`<Chart SeriesSource={Binding Series} />` 

Problème
Lorsque la source change, le rappel de validation est appelée. La valeur qui est passée à ceci est la valeur correcte, une ObservableCollection<something> remplie. Immédiatement après l'appel de la valeur de validation, le rappel CoerceValue est appelé par quelque chose, et la valeur qui lui est envoyée est ObservableCollection<something>. Bounty ira à tous ceux qui peuvent:

  1. Obtenez le bon peuplé ObservableCollection<someting> passé au rappel CoerceValue OU
  2. obtenir la valeur correcte étant passé à la fonction de rappel OnSeriesSourceChanged OU
  3. Expliquez-moi comment je peux faire tout de ce qui précède :)

Voici le modèle de données pour la vue:

<DataTemplate DataType="{x:Type vm:ReportViewModel}"> 
    <Grid Name="rootGrid"> 
    <visifire:Chart Grid.Row="1" SeriesSource="{Binding Series}"> 
     <visifire:Chart.AxesX> 
       <visifire:Axis Title="X axis" /> 
     </visifire:Chart.AxesX> 
     <visifire:Chart.AxesY> 
       <visifire:Axis Title="Y axis" /> 
     </visifire:Chart.AxesY> 
    </visifire:Chart> 
    </Grid> 
</DataTemplate> 

Voici la cible de propriété de dépendance

//Getter and setter for Dependency Property 
    public ObservableCollection<DataSeries> SeriesSource 
    { 
     get { return (ObservableCollection<DataSeries>)GetValue(SeriesSourceProperty); } 
     set { SetValue(SeriesSourceProperty, value);   } 
    } 

    // Using a DependencyProperty as the backing store for SeriesSource. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty SeriesSourceProperty = 
     DependencyProperty.Register("SeriesSource", typeof(ObservableCollection<DataSeries>), typeof(Chart), new UIPropertyMetadata(new ObservableCollection<DataSeries>(), new PropertyChangedCallback(OnSeriesSourceChange), new CoerceValueCallback(CoerceSeries)), new ValidateValueCallback(ValidateSeriesSource)); 

    //Value validation callback 
    private static bool ValidateSeriesSource(object value) 
    { 
     if (value as ObservableCollection<DataSeries> != null) 
      return true; 
     return false; 
    } 

    //Dependency Property Changed callback 
    private static void OnSeriesSourceChange(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     Chart c = d as Chart; 
     if (c == null) 
      return; 
     //This line was causing the issue. It was overriding the setter 
     c.SeriesSource = (DataSeriesCollection)e.NewValue; 
    } 

    //Coerce Value callback 
    private static object CoerceSeries(DependencyObject d, object value) 
    { 
     Chart c = d as Chart; 
     var collection = value as System.Collections.ObjectModel.ObservableCollection<Visifire.Charts.DataSeries>; 
     foreach (var item in c.Series) 
     { 
      if (!collection.Contains(item)) 
       c.Series.Remove(item); 
     } 
     foreach (var item in collection) 
     { 
      if (!c.Series.Contains(item)) 
       c.Series.Add(item); 
     } 
     return collection; 
    } 

De nouvelles informations
La valeur reçue par le rappel de CoerceValue est toujours la première valeur que la propriété a été définie sur. Donc si la première valeur que je passe est une liste avec 1 item, elle forcera toujours la valeur à revenir à une liste avec un item!

Modifier: a trouvé le problème, il était dans la propriété a changé callback. Crédit à Matt pour m'avoir aidé avec le rappel CoerceValue

+0

Juste pour confirmer: Vous vérifiez si la valeur est définie à l'aide d'un point d'arrêt sur le setter de la propriété de dépendance SeriesSource du graphique. Cela ne fonctionnera pas - les getters et les setters sur les points de données liés aux données sont ignorés. –

+0

Voir le code ci-dessus. Im en utilisant des points d'arrêt sur la fonction OnSeriesChange – TerrorAustralis

+0

Parfois, ces choses ne font que se réparer! :) Désolé je ne pourrais pas être plus d'aide, mais au moins je vous ai aidé à vous aider je suppose. –

Répondre

2

Ce n'est peut-être pas le problème exact, mais vous avez de la logique dans votre setter. Ce code ne va pas être exécuté lorsque la propriété est assignée via une liaison. Au lieu d'ajouter de la logique à votre setter, pensez à utiliser un rappel "forcé" qui est appelé chaque fois qu'une valeur est affectée à votre propriété. See here for more details about "coerce value" callbacks. Ils sont très similaires à ce que vous avez fait pour votre callback "propriété modifiée".

+0

Hey Matt, j'ai ajouté le callback CoerceValue, il est appelé à chaque fois que la liaison est modifiée, mais l'objet qui lui est passé n'est pas l'objet renvoyé par la source ... Tat explique pourquoi la propriété propertychanged n'est jamais appelée l'article est toujours le même, une liste vide – TerrorAustralis

+0

voir les modifications pour les nouvelles infos – TerrorAustralis