La liaison bidirectionnelle problème avec WPF zone de liste déroulante à l'aide de MVVM
J'ai un Activity
objet avec de nombreuses propriétés. L'un d'eux est comme suit:
public ActivityStatus Status
{
get { return status; }
set { status = value; NotifyPropertyChanged("Status"); }
}
La ActivityStatus
de classe dispose de deux propriétés:
public Guid Guid
{
get { return guid; }
set { guid = value; NotifyPropertyChanged("Guid"); }
}
public string Name
{
get { return name; }
set { name = value; NotifyPropertyChanged("Name"); }
}
et la Equals
méthodes:
public override bool Equals(object otherObject)
{
if (!(otherObject is ActivityStatus)) return false;
return Equals(otherObject as ActivityStatus);
}
public bool Equals(ActivityStatus otherStatus)
{
if (!(otherStatus is ActivityStatus) || otherStatus == null) return false;
return Guid == otherStatus.Guid && Name == otherStatus.Name;
}
J'ai un ActivityViewModel
classe que le DataContext
d'un ActivityView
classe. Le ActivityViewModel
a un Activity
propriété de type Activity
et, entre autres, un ActivityStatuses
propriété de type ObservableCollection<ActivityStatus>
. Dans le ActivityView
j'ai un ComboBox
déclarée comme suit:
<ComboBox ItemsSource="{Binding ActivityStatuses}"
SelectedItem="{Binding Activity.Status, Mode=TwoWay}"
DisplayMemberPath="Name" />
Cela me permet de sélectionner un ActivityStatus
de la ComboBox
et ce met correctement à jour la Status
propriété de la Activity
dans le Activity
propriété du viewmodel. Le problème est avec la liaison bidirectionnelle... lors du chargement d'un nouveau Activity
, le ComboBox.SelectedItem
n'est pas à jour pour afficher la Activity.Status
la valeur de la propriété.
À l'aide de cette déclaration de la ComboBox
, le SelectedItem
est lié à la ActivityStatus
objet dans le Activity
et c'est un autre objet de l'un avec les mêmes valeurs dans le viewmodel ActivityStatuses
de la propriété. Par conséquent, le Framework WPF ne pense pas que les articles sont de la même et ne pas sélectionner l'élément dans le ComboBox
.
Si je affecter l'élément de la collection avec les mêmes valeurs pour les Activity.Status
de la propriété après le chargement de chaque Activity
, puis le ComboBox
trouve une correspondance dans son ItemsSource
collecte et définit correctement le SelectedItem
propriété de l'affichage de la valeur. Je n'ai pas vraiment envie de faire ce que parce que j'ai beaucoup d'autres propriétés similaires dans th Activity
classe et je vais répéter ce code n'importe où, je veux les deux sens de se lier à ComboBox
es.
Donc, j'ai aussi essayé de liaison à ActivityStatus.Guid
propriété comme suit:
<ComboBox ItemsSource="{Binding ActivityStatuses}"
SelectedValue="{Binding Activity.Status.Guid, Mode=TwoWay}"
SelectedValuePath="Guid"
DisplayMemberPath="Name" />
Correctement sélectionné l'objet avec le même Guid
que celui de la Activity.Status
bien de la ComboBox.ItemsSource
collection lors du chargement de différents Activity
objets. Le problème avec cette méthode est que la SelectedValue
est lié à la ActivityStatus.Guid
propriété dans le ActivityStatus
objet et, ainsi, lorsque l'évolution des valeurs dans l'INTERFACE utilisateur, seul le "Guid" propriété de la ActivityStatus
objet de mise à jour, en laissant le nom inchangé. L'objet dans la Activity.Status
propriété ne change pas, sauf pour la valeur de son Guid
propriété.
Comme vous pouvez le voir, j'ai aussi essayé la mise en œuvre de la Equals
méthode que j'ai supposé que le ComboBox
aurait à utiliser pour comparer les objets, mais il n'a fait aucune différence. Donc finalement, je suis à une perte et désireux de trouver un simple moyen propre à résoudre ce problème... je l'espère, il y a une propriété simple que j'ai raté sur le ComboBox
.
Je veux simplement être en mesure de sélectionner un élément dans la ComboBox
et ont la Activity.Status
objet de modifier en conséquence et de modifier la valeur de la Activity.Status
propriété de code et le ComboBox.SelectedItem
également mettre à jour en conséquence. Je serais reconnaissant de tout conseil.
Mise à JOUR >>>
Après lecture de la réponse, j'ai essayé le code de l'échantillon dans une solution nouvelle et vu qu'il a fonctionné comme prévu. J'ai ensuite examiné son code thorouhly et vu que c'était le même que le mien, donc couru mon propre solution de nouveau (pour la première fois depuis ce post). À ma grande surprise, il a fonctionné comme prévu, sans me changer tout le code!
Cela me laisse perplexe grandement et j'ai passé un peu de temps pour savoir ce qui s'est passé. Il s'avère que le problème a été/est Visual Studio 2010! J'avais ajouté le Equals
méthodes pour mon des types de données comme la dernière étape. Pour une raison que Visual Studio n'a pas construit les types de données du projet lors de l'exécution de l'application.
De sorte que la demande doit avoir été à l'aide d'un ancien fichier dll et mes modifications n'ont pas été utilisés... je ne me demande pourquoi mes points de rupture sur le Equals
méthodes n'ont jamais été touchés. Cela a conduit à mon hypothèse que la mise en œuvre de la Equals
methids n'a pas aidé. Visual Studio a le même comportement qu'aujourd'hui, et c'est ainsi que j'ai découvert ce qui s'était passé.
J'ai vérifié le projet de construction de l'ordre dans ma solution, mais qui répertorie les types de données de projet dans le bon endroit dans l'ordre. Lors de l'exécution de l'application bien que, la fenêtre de Sortie de Visual Studio affiche le projet dll chargées dans un ordre différent. Je ne suis pas sûr pourquoi l'exécution de l'application n'est plus une construction complète, mais au moins je sais que je dois construire ce projet après avoir fait des modifications avant l'exécution de l'application.
Dernière mise à JOUR >>>
Je viens de trouver pourquoi mon des types de données de projet n'a pas été... j'ai regardé dans le Gestionnaire de Configuration de la fenêtre et a vu que d'une certaine façon, la Plateforme était incorrecte de ce projet et la case à cocher générer était devenu décochée! Je n'ai aucune idée de comment c'est arrivé, mais je suis très soulagé que j'ai enfin réussi à le fond du problème.
Merci @Will, mais je viens de trouver pourquoi mon des types de données de projet n'a pas été... j'ai regardé dans le Gestionnaire de Configuration de la fenêtre et a vu que d'une certaine façon, la Plateforme était incorrecte de ce projet et la case à cocher générer était devenu décochée! Je n'ai aucune idée de comment c'est arrivé, mais je suis très soulagé que j'ai enfin réussi à le fond du problème.
OriginalL'auteur Sheridan | 2011-05-26
Vous devez vous connecter pour publier un commentaire.
J'ai quelques mauvaises nouvelles pour vous. Il devrait fonctionner. Il y a un bug/effet indésirable inattendu quelque part d'autre qui est à l'origine de votre problème.
J'ai jeté un projet rapide à faire ce que vous essayez de faire. Comme de le voir ici, il va.
Créer un nouveau projet WPF appelé NestedProperties. Ajoutez une nouvelle classe à la racine et collez le code suivant (je l'ai retiré beaucoup de choses donc c'est un peu moche):
Maintenant ouvrir MainWindow le et collez-le dans:
Lorsque vous exécutez cette application, vous trouverez vous avez des quatre les Activités et les quatre Statuts. Si vous feuilletez les Activités de liste déroulante, vous verrez de chaque Statut est marqué comme Activité, c'est à dire l'exemple donné à l'Activité dans le constructeur du ViewModel. Vous verrez aussi que le Statut de zone de liste déroulante change comme les changements de l'Activité, ce qui signifie que le
Equals
méthode de travail.Ensuite, le changement de statut pour chaque Activité. Vous verrez le type de l'état des changements de Collection, ce qui signifie que cette instance a été créée et ajoutée pour les états de collection dans le constructeur.
Alors, pourquoi est-ce de travailler, mais ton code n'est pas? Je ne suis pas sûr. Votre problème se trouve ailleurs, dans votre code.
OriginalL'auteur Will
Homme je ne sais pas si j'ai suivi votre question exactement, mais quand vous dites
Êtes-vous en ajoutant que la nouvelle
Activity
à votreActivityStatuses
collection? Parce que si vous n'êtes pas, alors je suis assez sûr que la liaison ne fonctionne pas parce que le SelectedItem doit être dans le ItemsSource.Juste une pensée.
OriginalL'auteur Jose