2010-01-12 8 views
1

Je vais essayer de l'expliquer aussi concis que possible. J'ai 2 objets, le premier que nous appellerons l'objet A qui a une propriété Id et le second nous appellerons l'objet B, qui a une propriété ParentId. La relation évidente est que ParentId de l'objet B est défini sur la propriété Id d'un objet A. J'utilise le pattern MVVM, donc sur le viewmodel j'ai 2 ObservableCollections, l'un contenant les objets A les autres objets B. Lors de la construction du viewmodel, je crée et remplit ObservableCollection < 'A'> nommé ListItems. Mon XAML est simple,Comportement de liaison étrange dans WPF

<StackPanel> 
    <ListBox IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding ListItems}"> 
    </ListBox> 

    <ComboBox SelectedValuePath="ParentId" SelectedValue="{Binding Path=ListItems/Id, Mode=OneWay}" ItemsSource="{Binding ComboItems}"> 
    </ComboBox> 

    <Button Click="Button_Click" Content="Push Me"/>    
</StackPanel> 

Comme vous pouvez le voir le SelectedValue du combobox est lié aux ListItems propriété ID élément en cours. Donc, essentiellement, la liste et la liste déroulante sont dans un détail principal.

Si vous appuyez sur le bouton, il remplira le champ ObservableCollection < 'B'> ComboItems, qui à son tour remplit la zone de liste déroulante. Maintenant, voici où commence la curiosité. Lorsque je démarre le programme, si la seule chose que je fais est d'appuyer sur le bouton, puis après avoir sélectionné un élément dans la liste, la liste déroulante sélectionnera correctement un élément en raison de la liaison SelectedValue. Mais si je démarre le programme et que je sélectionne d'abord un élément dans la liste puis que j'appuie sur le bouton, l'élément de liste déroulante en cours ne change pas avec l'élément de liste courant en cours. La liaison semble être définitivement brisée. Est-ce que quelqu'un sait pourquoi cela se produit?

Ps. Si je définis la ItemsSource sur la liste déroulante avant de définir le SelectedValue/SelectedValuePath, la liaison maître/détail ne fonctionnera jamais. Je sais qu'il y a de l'ordre à xaml, mais cela semble un peu fragile. Donc, si quelqu'un a des idées à ce sujet, je suis tout ouïe.

Merci, Nate

EDIT -

Lors de la liaison SelectedValue, il est très fragile. Si la liaison fonctionne, c'est-à-dire si vous n'avez rien sélectionné dans la liste, puis remplissez la liste déroulante, si vous choisissez un élément dans la liste déroulante, la liaison se rompra. Après beaucoup de temps perdu avec cela, j'ai choisi de lier SelectedItem. Cette liaison ne casse dans aucune des conditions que j'ai précédemment spécifiées. Je voudrais cependant prendre des réponses à la question pourquoi la liaison SelectedValue est si ridicule. Merci encore à tous ceux qui ont répondu ou qui répondront.

Répondre

2

Oui, c'est un problème sur lequel nous tombons énormément.

Le problème est qu'après que la propriété ItemsSource a reçu une nouvelle valeur, la liaison SelectedValue est effacée. Suce, et jusqu'à aujourd'hui nous n'avons pas trouvé une solution appropriée.

Voici quelques solutions de contournement:

  • Réinitialiser la SelectedValue obligatoire dans le code, dès que la nouvelle ItemsSource a été défini. Vous pouvez le faire dans un convertisseur, ou quelque part vous saurez ce qui va remplacer la liaison ItemsSource (comme l'événement DataContextChanged). Au lieu d'utiliser le Binding sur ItemsSource, essayez d'utiliser un CollectionViewSource et un filtre. Au lieu d'utiliser Binding sur ItemsSource, utilisez un et un filtre. Placez tous vos objets dans l'objet CollectionViewSource et filtrez les éléments lorsque votre liste modifiable change de valeur.

  • Obtenez manuellement votre élément à l'ancienne lorsque votre zone de liste génère un événement SelectionChanged.

Rappelez-vous, toutes les solutions ne sont pas les plus jolies dans le livre. Je voudrais aller pour l'option 2, son OMI le plus propre;)

Espérons que cela aide!

+0

Merci pour votre réponse. Je vois comment cela s'applique à l'ordre dans lequel vous accrochez vos liaisons dans xaml, mais je ne suis pas sûr que cela s'applique à ma première question, celle qui concerne la sélection d'un élément dans la liste avant de remplir la liste déroulante. Dans ce scénario, ObservableCollection est lié à la liste déroulante, elle n'est jamais remplacée mais seulement remplie avec des données, donc je ne comprends pas/pense que la liaison SelectedValue serait effacée. Merci d'avoir répondu à ma deuxième question. Il semble que la conception étrange, mais je devine owell. – NastyNateDoggy

+0

Cela semble étrange. Peut-être que votre collection ListItems est affectée d'une manière ou d'une autre. Vous semblez avoir IsSynchronizedWithCurrentItem défini sur true, ce qui signifie qu'il va correspondre à CurrentItem de votre collection à SelectedItem qui sera initialement null. Peut-être que cela va réinitialiser votre élément sélectionné dans votre ListBox? – Arcturus

+0

J'ai marqué cela comme la réponse même si je pense qu'elle ne répond pas complètement à ma question. Lisez ma modification ci-dessus pour voir ma solution finale. – NastyNateDoggy