WPF DataGridTemplateColumn avec zone de liste déroulante de Liaison (pattern MVVM)
Je vais dingue avec la suite de WPF DataGrid+ComboBox scénario.
J'ai un ensemble de classes qui se ressemblent;
class Owner
{
int ID { get; }
string Name { get; }
public override ToString()
{
return this.Name;
}
}
class House
{
int ID { get; }
Owner HouseOwner { get; set; }
}
class ViewModel
{
ObservableCollection<Owner> Owners;
ObservableCollection<House> Houses
}
Maintenant mon résultat souhaité est un DataGrid qui affiche une liste de lignes de type Maison, et dans l'une des colonnes, est une zone de liste déroulante qui permet à l'utilisateur de modifier la valeur de Maison.HouseOwner.
Dans ce scénario, le DataContext de la grille est ViewModel.Maisons et pour la zone de liste déroulante, je veux le ItemsSource d'être lié à ViewModel.Propriétaires.
Est-ce même possible? Je vais mentale avec ce... le meilleur que j'ai pu faire est de correctement obtenir le ItemsSource lié, cependant la zone de liste déroulante (à l'intérieur d'un DataGridTemplateColumn) n'est pas en montrant les valeurs correctes pour la Maison.HouseOwner dans chaque ligne.
REMARQUE: Si je prends de la zone de liste déroulante de la photo et de mettre un TextBlock dans le DataTemplate au lieu de cela, je peux voir correctement les valeurs de chaque ligne, mais avoir à la fois un ItemsSource ainsi que de montrer la valeur correcte dans la sélection ne fonctionne pas pour moi...
À l'intérieur de mon code derrière, j'ai mis le DataContext sur la Fenêtre de ViewModel et sur la grille, le DataContext est défini à ViewModel.Maisons. De tout, sauf de cette zone de liste déroulante, ça fonctionne...
Mon XAML de la délinquance de la colonne ressemble;
<DataGridTemplateColumn Header="HouseOwner">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Path=DataContext.Owners, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
DisplayMemberPath="Name"
SelectedItem="{Binding HouseOwner, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
SelectedValue="{Binding HouseOwner.ID, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Mode=OneWay}"
SelectedValuePath="ID" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Aimerais un peu d'aide sur ce coup... semble comme un peu de Vaudou est requis...
OriginalL'auteur RJ Lohan | 2011-08-17
Vous devez vous connecter pour publier un commentaire.
comme par défaut.kramer dit, vous devez supprimer le
RelativeSource
de vos fixations pour leSelectedItem
etSelectedValue
comme ceci (notez que vous devez ajouterMode=TwoWay
de votre liaison, de sorte que le changement dans la zone de liste déroulante est reflété dans votre modèle).Cependant, à la différence qu'il a dit, vous n'avez pas à supprimer la liaison pour l'
SelectedValue
. En fait, si vous l'enlever, il ne fonctionne pas (les deuxSelectedValue
etSelectedValuePath
doit être définie ici, comme vous l'avez fait), parce que c'est ce que permet le mécanisme de liaison pour identifier la sélection de la zone de liste déroulante à la grille de laHouseOwner
propriété.SelectedValue
/SelectedValuePath
combinaison est très intéressant.SelectedValuePath
raconte la liaison de données que leID
propriété de laOwner
objet actuellement sélectionné représente son valeur,SelectedValue
qu'il indique que cette valeur doit être lié à laHouseOwner.ID
qui est l'objet sélectionné sur la grille de données.Par conséquent, si vous supprimez ceux de la liaison, la seule chose que le mécanisme de liaison de données savent "ce que l'objet est sélectionné", et de faire la correspondance entre l'élément sélectionné dans la zone de liste déroulante et le
HouseOwner
de propriété sur l'élément sélectionné dans la grille de données, ils doivent être "de la même référence d'objet". Ce qui signifie que, par exemple, le code suivant ne fonctionne pas:(notez que les "propriétaires de maison" des Maisons de la collection sont différents (nouveau) de ceux dans les Propriétaires de la collection). Cependant, la suite de serait travail:
Espère que cela aide 🙂
Mise à jour: dans le second cas, vous pouvez obtenir le même résultat sans avoir les références étant la même en remplaçant est Égal à sur le
Owner
classe (naturellement, car il est utilisé pour comparer les objets en premier lieu). (merci à @RJ Lohan pour le signaler dans les commentaires ci-dessous)Honnêtement, j'ai aussi pensé que c'était le problème, jusqu'à ce que j'ai essayé moi-même 🙂
Merci pour la réponse, mais ce n'est toujours pas assez de travail pour moi. J'ai le code XAML de liaison de configuration comme vous le notez, avec un changement dans la mesure où le Propriétaire.ID n'a qu'un getter, je dois mettre la SelectedValue de liaison de OneWay, tandis que le SelectedItem de liaison est défini comme Bidirectionnelle (sinon je reçois des exceptions d'exécution). Aussi, j'ai pensé liaison Bidirectionnelle est la valeur par défaut, donc n'aurait pas besoin d'être spécifié sur la SelectedItem? De toute façon, ne fonctionne toujours pas pour moi - je suis toujours incapable de changer la sélection dans la zone de liste déroulante...
Une autre pensée; RE: "pour faire la correspondance entre l'élément sélectionné dans la zone de liste déroulante et le HouseOwner de propriété sur l'élément sélectionné dans la grille de données, ils doivent être "de la même référence d'objet"... j'ai annulé le Equals méthode à mon Propriétaire de l'objet (dans le code réel) à correspondent sur ID, alors j'ai pensé que la valeur liaisons deviendrait redondant comme le SelectedItem liaison a pu comparer les différentes instances de Propriétaire de lorsque les Identifiants sont les mêmes. Par ailleurs, j'ai réussi à le faire fonctionner dans le code-behind avec un DataGridComboBoxColumn... le XAML approche encore m'échappe
Le mode par défaut de la Liaison est OneWay, et d'oublier de la mettre à l' Bidirectionnelle m'a donné beaucoup de maux de tête. Pour votre remarque sur le "même de l'objet de référence", vous avez raison. Je l'ai juste essayé, et en remplaçant la Equals fonctionne (c'est normal, puisque c'est la méthode qui est utilisée pour vérifier l'égalité, et par défaut, il vérifie si c'est la "même" 😉 ). Heureux de vous aider de toute façon 🙂
OriginalL'auteur AbdouMoumen
Merci pour l'aide de tous j'ai enfin pourquoi je ne pouvais pas sélectionner la zone de liste déroulante d'éléments - était due à une souris aperçu de gestionnaire d'événement que j'avais attaché à la cellule de style quand j'étais à l'aide d'un DataGridComboBoxColumn.
Ont frappé moi-même pour que l'on, merci pour les autres de l'aide.
Aussi, comme une note, la seule façon que cela fonctionne pour moi, c'est avec un supplément;
Ajouté à la zone de liste déroulante, sinon ils montrent tous la même valeur pour une raison quelconque.
Aussi, je ne me semblent exiger la SelectedValue/SelectedValuePath propriétés dans mon Contraignant, je crois parce que j'ai annulé est Égal à dans mon lié type de Propriétaire.
Et enfin, j'ai explicitement défini;
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
Dans la Liaison pour les valeurs d'écriture sur les objets liés quand la zone de liste déroulante a changé.
Donc, la finale (de travail) XAML pour la liaison ressemble à ceci;
Cheers!
rJ
OriginalL'auteur RJ Lohan
C'est certainement possible et vous êtes sur la bonne voie à l'aide d'un
AncestorType
de liaison pour laItemsSource
. Mais je crois que je vois un couple d'erreurs.Tout d'abord, votre
ItemsSource
devrait être obligatoire pourDataContext.Owners
, pasDataContext.Houses
, correct? Vous voulez que le viewmodel de la collection des Propriétaires à afficher dans la liste déroulante. Donc, d'abord, changer leItemsSource
et de prendre les liés à la Sélection des trucs, comme ceci:Maintenant le tester et assurez-vous que le
ItemsSource
fonctionne correctement. N'essayez pas de déconner avec la sélection jusqu'à ce que cette partie des travaux.Au sujet de la sélection, je pense que vous devriez être en liaison
SelectedItem
seulement - pasSelectedValue
. Pour cette liaison, vous ne pas souhaitez unRelativeSource
de liaison - le DataContext sera une seuleHouse
de sorte que vous pouvez lier directement sesHouseOwner
. Je suppose que ça:Enfin, pour le débogage des liaisons, vous pouvez voir la fenêtre Sortie de Visual Studio ou passer à un outil comme Snoop ou WPF Inspecteur. Si vous prévoyez de faire beaucoup de WPF, je vous recommande de commencer avec Snoop tôt que plus tard.
J'ai bricolé avec mon code un peu, et maintenant, j'ai touché un peu différente de plomb dans l'aile. Avec le code implémenté comme vous avez, avec seulement SelectedItem lié, toutes les lignes indiquent la même valeur pour HouseOwner... aucune idée de ce que cela signifie, mais il semble qu'ils ne sont pas correctement lié. Alors que sur google, je suis tombé sur une autre suggestion où j'ai ajouté; IsSynchronizedWithCurrentItem="False" À ma zone de liste déroulante. Cela a permis de corriger les valeurs indiquées pour chaque produit, et le bon choix dans la liste déroulante... mais maintenant je suis incapable de modifier la sélection!
OriginalL'auteur default.kramer
Exemple complet basé sur AbdouMoumen de la suggestion. Également supprimé SelectedValue & SelectedValuePath.
OriginalL'auteur rr789