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

Silverlight Discussion :

Mettre à jour une combobox pendant un bind


Sujet :

Silverlight

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut Mettre à jour une combobox pendant un bind
    Bonjour,

    Je débute en Silverlight et je ne sais pas comment résoudre ce problème :

    Dans un formulaire j'ai une combobox dont la liste des éléments dépend de la valeur d'une autre combobox. Je n'arrive pas à faire un bind de mon formulaire (la liste des éléments de ma combobox n'est pas mise à jour au bind de l'autre combobox).

    Pour être plus clair/concret l'élément de ma form appartient à une sous-catégorie (dont la liste est donnée dans une combobox). Comme les sous-catégories sont nombreuses elles sont classées par catégories principales (l'autre combobox) et je n'affiche que les sous-catégories appartenant à la catégorie principale. Mais lorsque je veux faire le bind de ma form je n'arrive pas à n'afficher dans la combobox sous-catégories que les éléments appartenant à la catégorie sur laquelle se fait le bind.

    Quelqu'un a une idée pour me faire avancer ?
    Merci.

  2. #2
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Tu peux créer une propriété contenant les données filtrées et binder ta sous-combo dessus.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Citation Envoyé par Samoteph Voir le message
    Tu peux créer une propriété contenant les données filtrées et binder ta sous-combo dessus.
    Merci pour la réponse.

    En gros c'est déjà ce que je fais, mais je ne vois pas comment mettre à jour ma liste de sous-catégories au bind.

  4. #4
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Par exemple (code non testé) :

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
     
    public ObservableCollection<MonObjet> MonObjetCollection
    {
         get
         {
            //...
         }
     
         private set
         {
            //on fixe la valeur et on la notifie
         }     
    }
     
    public ObservableCollection<MonSousObjet> MonSousObjetCollection
    {
         get
         {
            //...
         }
     
          set
          {
            //on fixe la valeur et on la notifie
          }
    }
     
    public MonObjet SelectedMonObjet
    {
         get
        {
             return this.selectedMonObjet
        }
     
        set
        {
             if( this.selectedMonObjet != value )
             {
                 this.selectedMonObjet = value;
     
                 // ici on filtre la collection de SousObjets !
                 this.FilterMonSousObjetCollection(value);
     
                 // notification de changement
                 this.OnNotifyPropertyChanged("SelectedMonObjet");
             }
        }
    }
     
    private MonObjet selectedMonObjet = null;
     
    private FilterFilterMonSousObjetCollection(MonObjet monObjet)
    {
        // ici je filtre MonSousObjetCollection d'après la valeur MonObjet selectionnée
    }

    Code HTML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <!-- Combo -->
    <ComboBox ItemsSource="{Binding MonObjetCollection}" SelectedItem="{Binding SelectedMonObjet,Mode=TwoWay}">
    <!-- Sous Combo -->
    <ComboBox ItemsSource="{Binding MonSousObjetCollection}">

    L'important est de ne pas oublier les notifications dans les objets que tu modifies

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Ah merci je vois le truc.

    Mais ça ne marche pas tout à fait, la liste des sous-catégories est bien mise à jour, mais le binding sur la combobox ne se fait pas. Comme il faut une requête asynchrone à la base pour mettre à jour la combobox je pense que le binding de la valeur se fait avant la mise à jour de la combobox

    Merci encore pour l'aide.

  6. #6
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Comme il faut une requête asynchrone à la base pour mettre à jour la combobox je pense que le binding de la valeur se fait avant la mise à jour de la combobox
    Je ne vois pas le problème (même avec un accès asynchrone à une base).
    La comboBox se mettra à jour si tu fais une notification (OnNotifyPropertyChanged) sur la collection qui pointe sur son ItemsSource.

    Si tu veux allez plus loin dans la problématique poste nous un peu de code

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Voici ce qu'il y a dans mon ViewModel (j'utilise le pattern MVVM) :
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
     
            private Product _currentProduct;
            public Product CurrentProduct
            {
                get { return _currentProduct; }
                set
                {
                    _currentProduct = value;
                    LoadSubCategoryByCategory(_currentProduct.CategoryIDE);
                    RaisePropertyChanged("CurrentProduct");
                }
            }
     
            private ObservableCollection<Category> _listCategory;
            public ObservableCollection<Category> ListCategory
            {
                get
                {
                    return _listCategory;
                }
                set
                {
                    _listCategory = value;
                    RaisePropertyChanged("ListCategory");
                }
            }
     
            private ObservableCollection<Subcategory> _listSubcategory;
            public ObservableCollection<Subcategory> ListSubcategory
            {
                get
                {
                    return _listSubcategory;
                }
                set
                {
                    _listSubcategory = value;
                    RaisePropertyChanged("ListSubcategory");
                }
            }
     
            public void LoadSubCategoryByCategory(int CategoryIDE)
            {
                this.ListSubcategory = null;
                Domaine.Load(Domaine.GetSubCategoryOfCategoryQuery(CategoryIDE), (l) => { this.ListSubcategory = new ObservableCollection<Subcategory>(Domaine.Subcategories); }, null);
            }

    et pour la vue en XAML
    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <ComboBox x:Name="cbbCategory" ItemsSource="{Binding ListCategory}" DisplayMemberPath="Name" SelectedValuePath="IDE" SelectedValue="{Binding CurrentProduct.CategoryIDE}" />
    <ComboBox x:Name="cbbSubcategory" ItemsSource="{Binding ListSubcategory}" DisplayMemberPath="Name" SelectedValuePath="IDE" SelectedValue="{Binding CurrentProduct.SubcategoryIDE}" />

  8. #8
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Tu peux Commencer par mettre les SelectedValue de tes ComboBox en Mode TwoWay.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Malheureusement ça ne change rien

    (Encore merci pour ton aide en tous cas)

  10. #10
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Si tu mets un point d'arrêt sur le set de ton CurrentProduct, tu verras que lorsque tu change la selection combobox, il ne passera pas dedans. En effet ta selection s'effectue sur un membre de CurrentProduct (CategoryIDE) et donc aucun filtrage n'est effectué.

    Tu as plusieurs façon de faire pour détecter le changement de CategoryIDE. Si CurrentProduct hérite de INotifyPropertyChanged tu peux t'abonner à son évenement PropertyChanged en vérifiant le nom de la propriété qui change. (ne pas oublier de se désabonner si CurrentProduct change de valeur)

    Sinon, plus simple peut être, tu peux ajouter une propriété CategoryIDE au même niveau que CurrentProduct. Tu pointes le Binding du SelectedValue de taComboBox dessus. Dans cette propriété tu modifies la valeur de la propriété CategoryIDE.

    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
     
            public Product CurrentProduct
            {
                get { return _currentProduct; }
                set
                {
                    _currentProduct = value;
                    RaisePropertyChanged("CurrentProduct");
                    this.SelectedCategoryIDE = value.CategoryIDE;
                }
            }
     
            public Category SelectedCategoryIDE
            {
                get { return _currentProduct.CategoryIDE; }
                set
                {
                    if( _currentProduct != null &&  _currentProduct.CategoryIDE != value )
                   {
                    _currentProduct.CategoryIDE = value;
                    LoadSubCategoryByCategory(_currentProduct.CategoryIDE);
                    RaisePropertyChanged("SelectedCategoryIDE");
                    }
                }
            }

    Code XML : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <ComboBox x:Name="cbbCategory" ItemsSource="{Binding ListCategory}" DisplayMemberPath="Name" SelectedValuePath="IDE" SelectedValue="{Binding SelectedCategoryIDE}" />

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Bonjour (et merci une nouvelle fois)

    Je n'ai pas saisi la réponse, peut-être ai-je mal exprimé mon problème.

    Dans ma vue je sélectionne un produit (depuis une grille)
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        ViewModel.currentProduct = MyGrid.SelectedItem as Product;

    Ce produit possède une Category et une Subcategory. La liste des items de la Category est fixe et le binding est sans problème.
    Par contre la liste des items de SubCategory dépend de la Category sélectionnée, et il faut donc (enfin, je crois) que je remplisse la ComboBox SubCategory avant de faire le RaisePropertyChanged sur CurrentProduct.

    J'arrive à envoyer le RaisePropertyChanged sur la liste des SubCategories avant de faire le RaisePorpertyChanged sur CurrentProduct (grâce à ton aide), mais même dans ce cas aucun item n'est sélectionné dans la ComboBox SubCategory.

    J'espère avoir été un peu plus clair/précis.

  12. #12
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Je pense avoir bien compris le problème la première fois, en revanche, c'est sans doute moi qui ne suit pas assez clair dans mes explications

    Si on en revient à ton code départ :

    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
            public Product CurrentProduct
            {
                get { return _currentProduct; }
                set
                {
                    _currentProduct = value;
                    LoadSubCategoryByCategory(_currentProduct.CategoryIDE);
                    RaisePropertyChanged("CurrentProduct");
                }
            }

    On voit que tu veux filter ta sous-categorie en utilsant la méthode LoadSubCategoryByCategory. Ce filtrage s'effectue lorsqu'une modification est effectué sur l'objet CurrentProduct.

    Maintenant regarde ta ComboBox chargée de sélectionner une catégorie :

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <ComboBox x:Name="cbbCategory" ItemsSource="{Binding ListCategory}" DisplayMemberPath="Name" SelectedValuePath="IDE" SelectedValue="{Binding CurrentProduct.CategoryIDE}" />

    Lorsqu'une catégorie est sélectionné tu l'appliques sur la propriété CurrentProduct.CategoryIDE.

    ATTENTION : Ce n'est pas parce qu'une propriété enfant change, que l'objet sera notifié.

    Ainsi ta propriété CategoryIDE change mais ton objet CurrentProduct ne sera pas notifié pour autant. C'est pourquoi, le filtrage ne s'effectue pas (car il est placé dans CurrentProduct).

    J'espère avoir été plus clair sur le pourquoi du comment.
    Peut être que ma reponse précédente te semblera plus abordable après ces explications complémentaires.
    Si ce n'est pas le cas, n'hesite pas à poser des questions.

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Désolé d'être aussi lourd mais non, je n'ai pas compris.

    Tu me parles de Category alors que c'est Subcategory qui me crée des soucis :
    Lorsque je change de produit sélectionné (càd que je fais un set de _currentProduct) il faut pour la ComboBox SubCategory :
    • Mettre à jour l'ItemSource (Bind sur ListSubcategory)
    • Sélectionner la valeur dans la nouvelle liste (Bind de SelectedValue sur _currentProduct.SubcategoryIDE)


    Et je n'arrive pas à comprendre le rapport entre ton explication et mon problème (mais tout est loin d'être clair pour moi).

    Merci pour ta patience.

  14. #14
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Désolé d'être aussi lourd mais non, je n'ai pas compris.
    Pas de problème.

    Question : LoadSubCategoryByCategory(_currentProduct.CategoryIDE) est bien la méthode qui te permet de mettre en place tes sous categories ?

    Lorsque que tu changes de categorie via ta ComboBox, arrives-tu bien à cette méthode (qui se trouve dans CurrentProduct) ?

  15. #15
    Membre émérite
    Avatar de Samuel Blanchard
    Homme Profil pro
    Expert .NET
    Inscrit en
    Février 2010
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France

    Informations professionnelles :
    Activité : Expert .NET

    Informations forums :
    Inscription : Février 2010
    Messages : 1 504
    Points : 2 682
    Points
    2 682
    Par défaut
    Je te joins un article que je viens de rédiger qui explique le problème plus en détail :

    http://blog.naviso.fr/wordpress/?p=365

  16. #16
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Citation Envoyé par Samoteph Voir le message
    Question : LoadSubCategoryByCategory(_currentProduct.CategoryIDE) est bien la méthode qui te permet de mettre en place tes sous categories ?
    Oui c'est ça
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            public void LoadSubCategoryByCategory(int CategoryIDE)
            {
                Domaine.Load(Domaine.GetSubCategoryOfCategoryQuery(CategoryIDE), (l) => { this.ListSubcategory = new ObservableCollection<GeishaInputSolution.Web.Models.Subcategory>(Domaine.Subcategories); }, null);
            }
    Je fais une requête à la base qui va me remplir _listSubcategory sur laquelle je vais binder l'ItemSource de ma ComboBox Subcategory (bon en fait j'ai aussi un soucis la dessus car ma requête me ramène les éléments issus des précédentes requête en plus des nouvelles).
    Citation Envoyé par Samoteph Voir le message
    Lorsque que tu changes de categorie via ta ComboBox, arrives-tu bien à cette méthode (qui se trouve dans CurrentProduct) ?
    Quand je change de Category via la ComboBox j'utilise le SelectionChanged pour mettre à jour ma ComboBox Subcategory.

    Ce qui me fais penser qu'on ne parle pas de la même chose est que ça marche parfois (rarement), et c'est pourquoi j'imagine plus une espèce de "race condition".

    Je vais essayé de bien comprendre le post du blog pour être sûr de mes dires.

    En tous cas merci beaucoup.

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    J'ai fini par trouver la raison de mon problème. Il ne s'agit pas d'une "race condition" (quoi qu'il faille quand même bien s'assurer que la list des sous-catégories soit chargée avant de faire le bind) mais d'un bug de Silverlight 4 constaté par plusieurs personnes : si on utilise SelectedValue pour faire le bind alors le bind ne fonctionne plus après modification de ItemSource, alors qu'en utilisant SelectedItem le bind continue de fonctionner (enfin j'ai toujours un soucis, ça ne fonctionne bien que si le binding se fait en TwoWay, en OneWay j'ai aussi des soucis).

    Merci de vous être penché sur mon problème.

  18. #18
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    488
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 488
    Points : 397
    Points
    397
    Par défaut
    Bon, finalement comme la solution du binding TwoWay n'était pas satisfaisante (dans mon application réelle j'ai 3 ComboBox en cascade, et mettre la seconde en TwoWay créerait des inconsistances dans la base) j'ai finalement créé une ComboBox capable de continuer à se binder même après une modification de ItemSource comme expliqué dans ce blog.
    Voilà, si quelqu'un tombe sur ce même problème un jour qu'il sache qu'il existe une solution qui fonctionne.

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

Discussions similaires

  1. Impossible de mettre à jour une combobox
    Par nislog dans le forum Visual Studio
    Réponses: 2
    Dernier message: 01/06/2011, 13h18
  2. Réponses: 6
    Dernier message: 21/10/2009, 17h39
  3. Mettre à jour une base sous SQL SERVER 2000
    Par FilipeVV dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 11/02/2005, 12h24
  4. Comment mettre à jour une ligne sans doublon via déclencheur
    Par fuelcontact dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/08/2004, 15h56
  5. Mettre à jour une table depuis une autre
    Par rsc dans le forum SQL
    Réponses: 4
    Dernier message: 09/07/2004, 10h08

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