IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Presentation Foundation Discussion :

Binding et DependencyProperty avec une ObservableCollection<T> ou modifier une librairie existante [MVVM]


Sujet :

Windows Presentation Foundation

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 7
    Par défaut Binding et DependencyProperty avec une ObservableCollection<T> ou modifier une librairie existante
    Bonjour, j'ai un soucis qui me prends la tête depuis maintenant un bon moment et je ne parviens pas a trouver la solution...

    J'utilise une librairie qui permet de construire des graphiques, c'est OxyPlot ( http://oxyplot.codeplex.com/ sources dispo ) globalement elle marche bien sauf que, de base, la propriétés permettant de définir les différentes Séries n'est pas "bindable" malgré le fait que ce soit une ObservableCollection<>. Mon but étant de créer/effacer des séries "à la volée" je cherche a obtenir ce comportement.

    J'ai donc d'abord essayer de surcharger le Plot en y ajoutant une propriété SeriesSource qui irait modifier les Series de mon graphique.

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    class MyChartSeries : Plot
       {
     
     
          public MyChartSeries()
          {
             this.SeriesSource = new ObservableCollection<Series>();
             this.SeriesSource.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(SeriesSource_CollectionChanged);
          }
     
    public ObservableCollection<Series> SeriesSource
          {
             get { return (ObservableCollection<Series>)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<Series>), typeof(MyChartSeries), 
              new UIPropertyMetadata(null, OnListPropertyChanged));
     
     
          private static void OnListPropertyChanged(DependencyObject source,
            DependencyPropertyChangedEventArgs e)
          {
             MyChartSeries control = source as MyChartSeries;
             control.SeriesSource = (ObservableCollection<Series>)e.NewValue;
             // Put some update logic here...
     
          }
    }

    Mon OnListPropertyChanged (dans cet exemple il ne fait pas grand chose mais c'est pour illustrer) n'est appelé qu'une fois a la construction de mon ViewModel puis après plus rien.

    Dans mon ViewModel je crée juste une ObservalbleCollection<Series> que je bind en XAML sur SeriesSource de mon MyChartSeries:

    Code xaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <local:MyChartSeries Margin="0" Grid.Column="2" SeriesSource="{Binding ListeSeries, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
     
    <local:MyChartSeries.Axes>
    <OxyPlot_Wpf:DateTimeAxis Position="Bottom" FirstDateTime="2012-01-01" LastDateTime="2012-01-03" MinorIntervalType="Days"/>
    <OxyPlot_Wpf:LinearAxis EndPosition="0" Maximum="100" StartPosition="1"/>
    </local:MyChartSeries.Axes>
     
    </local:MyChartSeries>

    Je lance bien dans mon VM un RaisePropertyChanged("ListeSeries") (MVVM light) mais rien ne se passe au niveau du graphe...

    Ensuite je suis allé télécharger les sources et j'ai regardé un peu le fonctionnement mais je n'ai pas vraiment réussi a trouver comment modifier directement Series pour qu'il devienne bindable .

    Voilà les quelques parties de codes qu'il contient a ce sujet:

    Dans le constructeur de Plot.cs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    this.series = new ObservableCollection<Series>();
    ...
    this.series.CollectionChanged += this.OnSeriesChanged;
    Dans Plot.Properties.cs
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    /// <summary>
    ///   The series.
    /// </summary>
    private readonly ObservableCollection<Series> series; << Définition du this.series de Plot.cs
     
    /// <summary>
    ///   Gets the series.
    /// </summary>
    /// <value> The series. </value>
         public ObservableCollection<Series> Series
         {
             get
             {
                 return this.series;
             }
         }

    J'ai essayé de rajouter une DependencyProperty sur Series en remplaçant le getter/setter de la même façon que pour ma surcharge mais ça ne fonctionne pas mieux. J'ai bien la possibilité de mettre un binding mais il ne se passe rien lorsque je modifie ma liste de séries.

    Il y a pourtant tout un tas de dependencyProperty dans le fichier Plot.Properties mais aucune collection, que des objets "uniques" donc je pense qu'il me manque quelque chose (une implémentation des notifications de la collection? autre chose?) mais je n'arrive pas a mettre le doigt dessus.

    Après via surcharge ou en modifiant la source peu importe mais j'aimerai vraiment que quand je change ma liste dans mon VM hop ça me reconstruise le graphe avec les séries qui vont bien...

    Merci d'avance pour votre aide.

  2. #2
    Membre Expert
    Avatar de GuruuMeditation
    Homme Profil pro
    .Net Architect
    Inscrit en
    Octobre 2010
    Messages
    1 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2010
    Messages : 1 705
    Par défaut
    Dans ta dependencyproperty, essaye avec FrameworkMetadata au lieu de UiPropertyMetadata.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 7
    Par défaut
    Au niveau de la surcharge ou bien au niveau de la modification de la lib en elle même? Car il me semble avoir déjà essayé ça (j'y suis depuis tellement longtemps que j'ai du mal a me rappeler tout ce que j'ai tester...).

    Enfin bon, je vais essayer les deux, on verra bien, merci.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 7
    Par défaut
    Bon, ça avance (enfin :-) ).

    Donc si je mets ça dans ma surcharge:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // 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<Series>), typeof(MyChartSeries), 
              new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnListPropertyChanged));
    Ca ne change absolument rien...

    Par contre, en modifiant la lib directement, ça fonctionne mais a un petit détail prés > il faut que je change d'onglet (mon graphe est dans un tabControl) et que je reviennes pour que les séries s'affichent...

    Pour info ça me donne ça dans Plot.Properties:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public static readonly DependencyProperty SeriesProperty =
                DependencyProperty.Register(
                    "Series",
                    typeof(ObservableCollection<Series>),
                    typeof(Plot),
                    new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnListChanged));
     
            private static void OnListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
               ///////// Il faut que je trouve quoi mettre
            }
    Et la définition des getter/setter de series:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    /// <summary>
            ///   Gets the series.
            /// </summary>
            /// <value> The series. </value>
            public ObservableCollection<Series> Series
            {
                get
                {
                    return (ObservableCollection<Series>)this.GetValue(SeriesProperty);
                }
                set
                {
                   this.SetValue(SeriesProperty, value);
                }
            }
    Au lieu de ce que j'ai mis dans le premier post.

    Je vais voir les fonctions d'OxyPlot pour ce qui est de redessiner mais je ne sais pas si ça vient de lui ou pas... Quand on modifie les points d'une série (qui sont eux directement bindable), ça actualise bien "en live".
    Alors est ce que l'UI ne serait pas au courant de la modification des séries? Logiquement non vu que c'est le but d'une DP...

    Par contre avec la surcharge, rien a faire, il n'appelle jamais mon OnListPropertyChanged sauf a la construction, après je peux Raise ce que je veux ça ne fait rien .

    Merci beaucoup.

    EDIT: Bon ça ne vient pas juste d'un soucis d'affichage je pense, j'ai mis toutes les fonctions possible qui permettent de redessiner mais ça ne fonctionne pas du coup je ne sais même pas si ça vient d'autres modif a faire dans la lib ou de la DP en elle même...
    Pour les différents points de la série c'est différent, la classe hérite et surcharge ItemsControl contrairement au Plot.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 7
    Par défaut
    Aaaaaaah ça marche...

    Il semble qu'il y ai un "bug" du coup en regardant dans un des exemples d'Oxy, il y a dans le .cs de la vue un refresh qui est fait pour chaque CompositionTarget.Rendering. J'ai fais pareil dans mon appli et ça update bien quand je rajoute des séries wouhou !!!

    Je vais juste faire en sorte que ça se lance moins fréquemment plutôt qu'a chaque rendering de ma fenêtre car là c'est un peu gourmand en ressources processeur.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 02/12/2013, 11h54
  2. [AC-2007] Modifier une liste dont l'origine source est une Table/Requête
    Par Cinesra dans le forum VBA Access
    Réponses: 6
    Dernier message: 09/11/2010, 14h20
  3. Réponses: 3
    Dernier message: 23/10/2009, 18h25
  4. Réponses: 2
    Dernier message: 22/08/2008, 14h09
  5. Réponses: 3
    Dernier message: 04/07/2008, 11h33

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo